Hello team,

I ran into the address sanitizer error that I hope you could help me with. I 
don't really know what's wrong with the way the code frees memory. The relevant 
code file is attached. The line number following domain.cpp specifically 
referenced to the vector _q, which seems a little odd, since some other vectors 
are constructed and freed the same way.

==1719==ERROR: AddressSanitizer: attempting free on address which was not 
malloc()-ed: 0x61f0000076c0 in thread T0
    #0 0x7fbf195282ca in __interceptor_free 
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x7fbf1706f895 in PetscFreeAlign 
/home/yyy910805/petsc/src/sys/memory/mal.c:87
    #2 0x7fbf1731a898 in VecDestroy_Seq 
/home/yyy910805/petsc/src/vec/vec/impls/seq/bvec2.c:788
    #3 0x7fbf1735f795 in VecDestroy 
/home/yyy910805/petsc/src/vec/vec/interface/vector.c:408
    #4 0x40dd0a in Domain::~Domain() 
/home/yyy910805/scycle/source/domain.cpp:132
    #5 0x40b479 in main /home/yyy910805/scycle/source/main.cpp:242
    #6 0x7fbf14d2082f in __libc_start_main 
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #7 0x4075d8 in _start (/home/yyy910805/scycle/source/main+0x4075d8)

0x61f0000076c0 is located 1600 bytes inside of 3220-byte region 
[0x61f000007080,0x61f000007d14)
allocated by thread T0 here:
    #0 0x7fbf19528b32 in __interceptor_memalign 
(/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98b32)
    #1 0x7fbf1706f7e0 in PetscMallocAlign 
/home/yyy910805/petsc/src/sys/memory/mal.c:41
    #2 0x7fbf17073022 in PetscTrMallocDefault 
/home/yyy910805/petsc/src/sys/memory/mtr.c:183
    #3 0x7fbf170710a1 in PetscMallocA 
/home/yyy910805/petsc/src/sys/memory/mal.c:397
    #4 0x7fbf17326fb0 in VecCreate_Seq 
/home/yyy910805/petsc/src/vec/vec/impls/seq/bvec3.c:35
    #5 0x7fbf1736f560 in VecSetType 
/home/yyy910805/petsc/src/vec/vec/interface/vecreg.c:51
    #6 0x7fbf1731afae in VecDuplicate_Seq 
/home/yyy910805/petsc/src/vec/vec/impls/seq/bvec2.c:807
    #7 0x7fbf1735eff7 in VecDuplicate 
/home/yyy910805/petsc/src/vec/vec/interface/vector.c:379
    #8 0x4130de in Domain::setFields() 
/home/yyy910805/scycle/source/domain.cpp:431
    #9 0x40c60a in Domain::Domain(char const*) 
/home/yyy910805/scycle/source/domain.cpp:57
    #10 0x40b433 in main /home/yyy910805/scycle/source/main.cpp:242
    #11 0x7fbf14d2082f in __libc_start_main 
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: bad-free ??:0 __interceptor_free
==1719==ABORTING

Thanks very much!
Yuyun
#include "domain.hpp"

#define FILENAME "sbpOps_fc.cpp"

using namespace std;

// member function definitions including constructor
// first type of constructor with 1 parameter
Domain::Domain(const char *file)
: _file(file),_delim(" = "),_outputDir("data/"),
  _bulkDeformationType("linearElastic"),
  _momentumBalanceType("quasidynamic"),
  _sbpType("mfc_coordTrans"),_operatorType("matrix-based"),
  _sbpCompatibilityType("fullyCompatible"),
  _gridSpacingType("variableGridSpacing"),
  _isMMS(0),_loadICs(0), _inputDir("unspecified_"),
  _order(4),_Ny(-1),_Nz(-1),_Ly(-1),_Lz(-1),
  _vL(1e-9),
  _q(NULL),_r(NULL),_y(NULL),_z(NULL),_y0(NULL),_z0(NULL),_dq(-1),_dr(-1),
  _bCoordTrans(-1)
{
  #if VERBOSE > 1
    std::string funcName = "Domain::Domain(const char *file)";
    PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
  #endif

  // load data from file
  loadData(_file);

  // check domain size and set grid spacing in y direction
  if (_Ny > 1) {
    _dq = 1.0 / (_Ny - 1.0);
  }
  else {
    _dq = 1;
  }

  // set grid spacing in z-direction
  if (_Nz > 1) {
    _dr = 1.0 / (_Nz - 1.0);
  }
  else {
    _dr = 1;
  }

  #if VERBOSE > 2 // each processor prints loaded values to screen
    PetscMPIInt rank,size;
    MPI_Comm_size(PETSC_COMM_WORLD,&size);
    MPI_Comm_rank(PETSC_COMM_WORLD,&rank);

    for (int Ii = 0; Ii < size; Ii++) {
      view(Ii);
    }
  #endif

  checkInput(); // perform some basic value checking to prevent NaNs
  setFields();
  setScatters();

  #if VERBOSE > 1
    PetscPrintf(PETSC_COMM_WORLD,"Ending %s in %s\n",funcName.c_str(),FILENAME);
  #endif

}


// second type of constructor with 3 parameters
Domain::Domain(const char *file,PetscInt Ny, PetscInt Nz)
: _file(file),_delim(" = "),_outputDir("data/"),
  _bulkDeformationType("linearElastic"),_momentumBalanceType("quasidynamic"),
  
_sbpType("mfc_coordTrans"),_operatorType("matrix-based"),_sbpCompatibilityType("fullyCompatible"),_gridSpacingType("variableGridSpacing"),
  _isMMS(0),_loadICs(0),_inputDir("unspecified_"),
  _order(4),_Ny(Ny),_Nz(Nz),_Ly(-1),_Lz(-1),
  _vL(1e-9),
  _q(NULL),_r(NULL),_y(NULL),_z(NULL),_y0(NULL),_z0(NULL),_dq(-1),_dr(-1),
  _bCoordTrans(-1)
{
  #if VERBOSE > 1
    std::string funcName = "Domain::Domain(const char *file,PetscInt Ny, 
PetscInt Nz)";
    PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
  #endif

  loadData(_file);

  _Ny = Ny;
  _Nz = Nz;

  if (_Ny > 1) {
    _dq = 1.0/(_Ny-1.0);
  }
  else {
    _dq = 1;
  }
  
  if (_Nz > 1) {
    _dr = 1.0/(_Nz-1.0);
  }
  else {
    _dr = 1;
  }

  #if VERBOSE > 2 // each processor prints loaded values to screen
    PetscMPIInt rank,size;
    MPI_Comm_size(PETSC_COMM_WORLD,&size);
    MPI_Comm_rank(PETSC_COMM_WORLD,&rank);

    for (int Ii = 0; Ii < size; Ii++) {
      view(Ii);
    }
  #endif

  checkInput(); // perform some basic value checking to prevent NaNs  
  setFields();
  setScatters();

  #if VERBOSE > 1
    PetscPrintf(PETSC_COMM_WORLD,"Ending %s in %s\n",funcName.c_str(),FILENAME);
  #endif

}


// destructor
Domain::~Domain()
{
  #if VERBOSE > 1
    std::string funcName = "Domain::~Domain";
    PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
  #endif

  // free memory
  VecDestroy(&_q);
  VecDestroy(&_r);
  VecDestroy(&_y);
  VecDestroy(&_z);
  VecDestroy(&_y0);
  VecDestroy(&_z0);

  // set map iterator, free memory from VecScatter
  map<string,VecScatter>::iterator it;
  for (it = _scatters.begin(); it != _scatters.end(); it++ ) {
    VecScatterDestroy(&it->second);
  }

  #if VERBOSE > 1
    PetscPrintf(PETSC_COMM_WORLD,"Ending %s in %s\n",funcName.c_str(),FILENAME);
  #endif
}


// define loadData function, takes 1 parameter - the filename
PetscErrorCode Domain::loadData(const char *file)
{
  PetscErrorCode ierr = 0;
  PetscMPIInt rank,size;

  #if VERBOSE > 1
    std::string funcName = "Domain::loadData";
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  // determines size of the group associated with a communicator
  MPI_Comm_size(PETSC_COMM_WORLD,&size); 
  // determines rank of the calling processes in the communicator
  MPI_Comm_rank(PETSC_COMM_WORLD,&rank);

  // read file inputs
  ifstream infile(file);
  string line, var, rhs, rhsFull;
  size_t pos = 0;
  while (getline(infile, line))
  {
    istringstream iss(line);
    pos = line.find(_delim); // find position of the delimiter
    var = line.substr(0,pos);
    rhs = "";
    if (line.length() > (pos + _delim.length())) {
      rhs = line.substr(pos+_delim.length(),line.npos);
    }
    rhsFull = rhs; // everything after _delim

    // interpret everything after the appearance of a space on the line as a 
comment
    pos = rhs.find(" ");
    rhs = rhs.substr(0,pos);

    // set variables, convert string to ints/floats
    if (var.compare("order") == 0) {
      _order = atoi(rhs.c_str());
    }
    else if (var.compare("Ny") == 0 && _Ny < 0) {
      _Ny = atoi(rhs.c_str());
    }
    else if (var.compare("Nz") == 0 && _Nz < 0) {
      _Nz = atoi(rhs.c_str());
    }
    else if (var.compare("Ly") == 0) {
      _Ly = atof(rhs.c_str());
    }
    else if (var.compare("Lz") == 0) {
      _Lz = atof(rhs.c_str());
    }
    else if (var.compare("isMMS") == 0) {
      _isMMS = 0;
      std::string temp = rhs;
      if (temp.compare("yes") == 0 || temp.compare("y") == 0) {
        _isMMS = 1;
      }
    }
    else if (var.compare("sbpType")==0) {
      _sbpType = rhs;
    }
    else if (var.compare("operatorTYpe")==0) {
      _operatorType = rhs;
    }
    else if (var.compare("sbpCompatibilityType")==0) {
      _sbpCompatibilityType = rhs;
    }
    else if (var.compare("gridSpacingType")==0) {
      _gridSpacingType = rhs;
    }
    else if (var.compare("bulkDeformationType")==0) {
      _bulkDeformationType = rhs;
    }
    else if (var.compare("momentumBalanceType")==0) {
      _momentumBalanceType = rhs;
    }
    else if (var.compare("loadICs")==0) {
      _loadICs = (int)atof(rhs.c_str());
    }
    else if (var.compare("inputDir")==0) {
      _inputDir = rhs;
    }
    else if (var.compare("bCoordTrans")==0) {
      _bCoordTrans = atof( rhs.c_str() );
    }
    else if (var.compare("outputDir")==0) {
      _outputDir =  rhs;
    }
    else if (var.compare("vL")==0) {
      _vL = atof( rhs.c_str() );
    }
  }

  #if VERBOSE > 1
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif
  return ierr;
}


// Specified processor prints scalar/string data members to stdout.
PetscErrorCode Domain::view(PetscMPIInt rank)
{
  PetscErrorCode ierr = 0;
  PetscMPIInt localRank;
  MPI_Comm_rank(PETSC_COMM_WORLD,&localRank);

  if (localRank==rank) {
    #if VERBOSE > 1
      std::string funcName = "Domain::view";
      ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
      CHKERRQ(ierr);
    #endif

    // start printing all the inputs
    PetscPrintf(PETSC_COMM_SELF,"\n\nrank=%i in Domain::view\n",rank);
    ierr = PetscPrintf(PETSC_COMM_SELF,"order = %i\n",_order);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"Ny = %i\n",_Ny);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"Nz = %i\n",_Nz);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"Ly = %e\n",_Ly);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"Lz = %e\n",_Lz);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"\n");CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"isMMS = %i\n",_isMMS);CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"momBalType = 
%s\n",_momentumBalanceType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"bulkDeformationType = 
%s\n",_bulkDeformationType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"sbpType = 
%s\n",_sbpType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"operatorType = 
%s\n",_operatorType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"sbpCompatibilityType = 
%s\n",_sbpCompatibilityType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"gridSpacingType = 
%s\n",_gridSpacingType.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"outputDir = 
%s\n",_outputDir.c_str());CHKERRQ(ierr);
    ierr = PetscPrintf(PETSC_COMM_SELF,"\n");CHKERRQ(ierr);

    #if VERBOSE > 1
      ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
      CHKERRQ(ierr);
    #endif
  }
  return ierr;
}


// Check that required fields have been set by the input file
PetscErrorCode Domain::checkInput()
{
  PetscErrorCode ierr = 0;
  #if VERBOSE > 1
    std::string funcName = "Domain::checkInput";
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  assert(_bulkDeformationType.compare("linearElastic") == 0 ||
    _bulkDeformationType.compare("powerLaw") == 0);

  assert(_sbpCompatibilityType.compare("fullyCompatible") == 0 ||
    _sbpCompatibilityType.compare("compatible") == 0);

  if (_bCoordTrans > 0.0) {
    _gridSpacingType = "variableGridSpacing";
  }

  assert(_gridSpacingType.compare("variableGridSpacing") == 0 ||
     _gridSpacingType.compare("constantGridSpacing") == 0);

  assert(_momentumBalanceType.compare("quasidynamic") == 0 ||
    _momentumBalanceType.compare("dynamic") == 0 ||
    _momentumBalanceType.compare("quasidynamic_and_dynamic") == 0 ||
    _momentumBalanceType.compare("steadyStateIts") == 0);

  assert(_order == 2 || _order == 4);
  assert(_Ly > 0 && _Lz > 0);
  assert(_dq > 0 && !isnan(_dq));
  assert(_dr > 0 && !isnan(_dr));

  #if VERBOSE > 1
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif
  return ierr;
}


// Save all scalar fields to text file named domain.txt in output directory.
// Also writes out coordinate systems q, r, y, z into respective files in 
output directory
// Note that only the rank 0 processor's values will be saved.
PetscErrorCode Domain::write()
{
  PetscErrorCode ierr = 0;
  #if VERBOSE > 1
    std::string funcName = "Domain::write";
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  // output scalar fields
  std::string str = _outputDir + "domain.txt";
  PetscViewer    viewer;

  // write into file using PetscViewer
  PetscViewerCreate(PETSC_COMM_WORLD, &viewer);
  PetscViewerSetType(viewer, PETSCVIEWERASCII);
  PetscViewerFileSetMode(viewer, FILE_MODE_WRITE);
  PetscViewerFileSetName(viewer, str.c_str());

  // domain properties
  ierr = PetscViewerASCIIPrintf(viewer,"order = %i\n",_order);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"Ny = %i\n",_Ny);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"Nz = %i\n",_Nz);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"Ly = %g # (km)\n",_Ly);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"Lz = %g # (km)\n",_Lz);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"isMMS = %i\n",_isMMS);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"momBalType = 
%s\n",_momentumBalanceType.c_str());CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"bulkDeformationType = 
%s\n",_bulkDeformationType.c_str());CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"sbpType = 
%s\n",_sbpType.c_str());CHKERRQ(ierr);

  // linear solve settings
  ierr = PetscViewerASCIIPrintf(viewer,"bCoordTrans = 
%.15e\n",_bCoordTrans);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"outputDir = 
%s\n",_outputDir.c_str());CHKERRQ(ierr);
  ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);

  // get number of processors
  PetscMPIInt size;
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  ierr = PetscViewerASCIIPrintf(viewer,"numProcessors = 
%i\n",size);CHKERRQ(ierr);
  ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);

  // output q
  str =  _outputDir + "q";
  ierr = 
PetscViewerBinaryOpen(PETSC_COMM_WORLD,str.c_str(),FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
  ierr = VecView(_q,viewer);CHKERRQ(ierr);
  ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);

  // output r
  str =  _outputDir + "r";
  ierr = 
PetscViewerBinaryOpen(PETSC_COMM_WORLD,str.c_str(),FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
  ierr = VecView(_r,viewer);CHKERRQ(ierr);
  ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);

  // output y
  str =  _outputDir + "y";
  ierr = 
PetscViewerBinaryOpen(PETSC_COMM_WORLD,str.c_str(),FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
  ierr = VecView(_y,viewer);CHKERRQ(ierr);
  ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);

  // output z
  str =  _outputDir + "z";
  ierr = 
PetscViewerBinaryOpen(PETSC_COMM_WORLD,str.c_str(),FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
  ierr = VecView(_z,viewer);CHKERRQ(ierr);
  ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);

  #if VERBOSE > 1
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif
  return ierr;
}


// construct coordinate transform, setting vectors q, r, y, z
PetscErrorCode Domain::setFields()
{
  PetscErrorCode ierr = 0;
  #if VERBOSE > 1
    std::string funcName = "Domain::setFields";
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  // generate vector _y with size _Ny*_Nz
  ierr = VecCreate(PETSC_COMM_WORLD,&_y); CHKERRQ(ierr);
  ierr = VecSetSizes(_y,PETSC_DECIDE,_Ny*_Nz); CHKERRQ(ierr);
  ierr = VecSetFromOptions(_y); CHKERRQ(ierr);
  ierr = PetscObjectSetName((PetscObject) _y, "y"); CHKERRQ(ierr);

  // duplicate _y into _z, _q, _r
  VecDuplicate(_y,&_z); PetscObjectSetName((PetscObject) _z, "z");
  VecDuplicate(_y,&_q); PetscObjectSetName((PetscObject) _q, "q");
  VecDuplicate(_y,&_r); PetscObjectSetName((PetscObject) _r, "r");

  // construct coordinate transform
  PetscInt Ii,Istart,Iend,Jj = 0;
  PetscScalar *y,*z,*q,*r;
  ierr = VecGetOwnershipRange(_q,&Istart,&Iend);CHKERRQ(ierr);

  // return pointers to local data arrays (the processor's portion of vector 
data)
  VecGetArray(_y,&y);
  VecGetArray(_z,&z);
  VecGetArray(_q,&q);
  VecGetArray(_r,&r);

  // set vector entries for q, r (coordinate transform) and y, z (no transform)
  for (Ii=Istart; Ii<Iend; Ii++) {
    q[Jj] = _dq*(Ii/_Nz);
    r[Jj] = _dr*(Ii-_Nz*(Ii/_Nz));

    // matrix-based, fully compatible, allows curvilinear coordinate 
transformation
    if (_sbpType.compare("mfc_coordTrans") ) {
      y[Jj] = (_dq*_Ly)*(Ii/_Nz);
      z[Jj] = (_dr*_Lz)*(Ii-_Nz*(Ii/_Nz));
    }
    else {
      // hardcoded transformation (not available for z)
      if (_bCoordTrans > 0) {
        y[Jj] = _Ly * sinh(_bCoordTrans * q[Jj]) / sinh(_bCoordTrans);
      }
      // no transformation
      y[Jj] = q[Jj]*_Ly;
      z[Jj] = r[Jj]*_Lz;
    }
    Jj++;
  }

  // restore arrays
  VecRestoreArray(_y,&y);
  VecRestoreArray(_z,&z);
  VecRestoreArray(_q,&q);
  VecRestoreArray(_r,&r);

  // load y and z instead, if provided in input file
  loadVecFromInputFile(_y,_inputDir,"y");
  loadVecFromInputFile(_z,_inputDir,"z");

  #if VERBOSE > 1
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif
  return ierr;
}


// scatters values from one vector to another
// used to get slip on the fault from the displacement vector, i.e., slip = 
u(1:Nz); shear stress on the fault from the stress vector sxy; surface 
displacement; surface heat flux
PetscErrorCode Domain::setScatters()
{
  PetscErrorCode ierr = 0;
  #if VERBOSE > 1
    std::string funcName = "Domain::setFields";
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Starting %s in 
%s.\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  // set _y0 to be zero vector with length _Nz
  VecCreate(PETSC_COMM_WORLD,&_y0);
  VecSetSizes(_y0,PETSC_DECIDE,_Nz);
  VecSetFromOptions(_y0);
  VecSet(_y0,0.0);  

  // set _z0 to be zero vector with length _Ny
  VecCreate(PETSC_COMM_WORLD,&_z0);
  VecSetSizes(_z0,PETSC_DECIDE,_Ny);
  VecSetFromOptions(_z0);
  VecSet(_z0,0.0);

  { // set up scatter context to take values for y = 0 from body field and put 
them on a Vec of size Nz
    PetscInt *indices;
    IS is;  // index set
    PetscMalloc1(_Nz,&indices);

    // we want to scatter from index 0 to _Nz - 1, i.e. take the first _Nz 
components of the vector to scatter from
    for (PetscInt Ii = 0; Ii<_Nz; Ii++) {
      indices[Ii] = Ii;
    }

    // creates data structure for an index set containing a list of integers
    ierr = ISCreateGeneral(PETSC_COMM_WORLD, _Nz, indices, PETSC_COPY_VALUES, 
&is);

    // creates vector scatter context, scatters values from _y (at indices is) 
to _y0 (at indices is)
    ierr = VecScatterCreate(_y, is, _y0, is, &_scatters["body2L"]); 
CHKERRQ(ierr);

    // free memory
    PetscFree(indices);
    ISDestroy(&is);
  }

  { // set up scatter context to take values for y = Ly from body field and put 
them on a Vec of size Nz
    // indices to scatter from
    PetscInt *fi;
    IS isf;
    PetscMalloc1(_Nz,&fi);

    // we want to scatter from index _Ny*_Nz - _Nz to _Ny*_Nz - 1, i.e. the 
last _Nz entries of the vector to scatter from
    for (PetscInt Ii = 0; Ii<_Nz; Ii++) {
      fi[Ii] = Ii + (_Ny*_Nz-_Nz);
    }
    ierr = ISCreateGeneral(PETSC_COMM_WORLD, _Nz, fi, PETSC_COPY_VALUES, &isf);

    // indices to scatter to
    PetscInt *ti;
    IS ist;
    PetscMalloc1(_Nz,&ti);
    for (PetscInt Ii = 0; Ii<_Nz; Ii++) {
      ti[Ii] = Ii;
    }
    ierr = ISCreateGeneral(PETSC_COMM_WORLD, _Nz, ti, PETSC_COPY_VALUES, &ist);
    ierr = VecScatterCreate(_y, isf, _y0, ist, &_scatters["body2R"]); 
CHKERRQ(ierr);

    // free memory
    PetscFree(fi);
    PetscFree(ti);
    ISDestroy(&isf);
    ISDestroy(&ist);
  }

  { // set up scatter context to take values for z = 0 from body field and put 
them on a Vec of size Ny
    // indices to scatter from
    IS isf;
    /* creates a data structure for an index set with a list of evenly spaced 
integers
     * locally owned portion of index set has length _Ny
     * first element of locally owned index set is 0
     * change to the next index is _Nz (the stride)
     * takes indices [0, _Nz, 2*_Nz, ..., (_Ny-1)*_Nz]
    */
    ierr = ISCreateStride(PETSC_COMM_WORLD, _Ny, 0, _Nz, &isf);

    // indices to scatter to
    PetscInt *ti;
    IS ist;
    PetscMalloc1(_Ny,&ti);

    // length _Ny
    for (PetscInt Ii=0; Ii<_Ny; Ii++) {
      ti[Ii] = Ii;
    }
    ierr = ISCreateGeneral(PETSC_COMM_WORLD, _Ny, ti, PETSC_COPY_VALUES, &ist);
    ierr = VecScatterCreate(_y, isf, _z0, ist, &_scatters["body2T"]); 
CHKERRQ(ierr);

    // free memory
    PetscFree(ti);
    ISDestroy(&isf);
    ISDestroy(&ist);
  }

  { // set up scatter context to take values for z = Lz from body field and put 
them on a Vec of size Ny
    // indices to scatter from
    IS isf;
    // takes indices [_Nz - 1, 2*_Nz - 1, ..., _Ny*_Nz - 1]
    ierr = ISCreateStride(PETSC_COMM_WORLD, _Ny, _Nz - 1, _Nz, &isf);

    // indices to scatter to
    PetscInt *ti;
    IS ist;
    PetscMalloc1(_Ny,&ti);
    for (PetscInt Ii = 0; Ii<_Ny; Ii++) {
      ti[Ii] = Ii;
    }
    ierr = ISCreateGeneral(PETSC_COMM_WORLD, _Ny, ti, PETSC_COPY_VALUES, &ist);
    ierr = VecScatterCreate(_y, isf, _z0, ist, &_scatters["body2B"]); 
CHKERRQ(ierr);

    // free memory
    PetscFree(ti);
    ISDestroy(&isf);
    ISDestroy(&ist);
  }

  #if VERBOSE > 1
    ierr = PetscPrintf(PETSC_COMM_WORLD,"Ending %s in 
%s\n",funcName.c_str(),FILENAME);
    CHKERRQ(ierr);
  #endif

  return ierr;
}


// create example vector for testing purposes
PetscErrorCode Domain::testScatters() {
  Vec body;
  VecDuplicate(_y,&body);
  PetscInt      Istart,Iend,Jj = 0;
  PetscScalar   *bodyA;
  PetscErrorCode ierr = 0;
  VecGetOwnershipRange(body,&Istart,&Iend);
  VecGetArray(body,&bodyA);

  for (PetscInt Ii = Istart; Ii<Iend; Ii++) {
    PetscInt Iy = Ii/_Nz;
    PetscInt Iz = (Ii-_Nz*(Ii/_Nz));
    bodyA[Jj] = 10.*Iy + Iz;
    PetscPrintf(PETSC_COMM_WORLD,"%i %i %g\n",Iy,Iz,bodyA[Jj]);
    Jj++;
  }
  VecRestoreArray(body,&bodyA);

  // test various mappings
  // y = 0: mapping to L
  Vec out;
  VecDuplicate(_y0,&out);
  VecScatterBegin(_scatters["body2L"], body, out, INSERT_VALUES, 
SCATTER_FORWARD);
  VecScatterEnd(_scatters["body2L"], body, out, INSERT_VALUES, SCATTER_FORWARD);
  VecView(out,PETSC_VIEWER_STDOUT_WORLD);

  // y = Ly: mapping to R
  VecDuplicate(_y0,&out);
  VecSet(out,-1.);
  VecScatterBegin(_scatters["body2R"], body, out, INSERT_VALUES, 
SCATTER_FORWARD);
  VecScatterEnd(_scatters["body2R"], body, out, INSERT_VALUES, SCATTER_FORWARD);
  VecView(out,PETSC_VIEWER_STDOUT_WORLD);

  // z=0: mapping to T
  VecDuplicate(_z0,&out);
  VecSet(out,-1.);
  VecScatterBegin(_scatters["body2T"], body, out, INSERT_VALUES, 
SCATTER_FORWARD);
  VecScatterEnd(_scatters["body2T"], body, out, INSERT_VALUES, SCATTER_FORWARD);
  VecView(out,PETSC_VIEWER_STDOUT_WORLD);

  // z=Lz: mapping to B
  VecDuplicate(_z0,&out);
  VecSet(out,-1.);
  VecScatterBegin(_scatters["body2B"], body, out, INSERT_VALUES, 
SCATTER_FORWARD);
  VecScatterEnd(_scatters["body2B"], body, out, INSERT_VALUES, SCATTER_FORWARD);
  VecView(out,PETSC_VIEWER_STDOUT_WORLD);

  // z=Lz: mapping from B to body
  VecDuplicate(_z0,&out);
  VecSet(out,-1.);
  VecScatterBegin(_scatters["body2T"], out, body, INSERT_VALUES, 
SCATTER_REVERSE);
  VecScatterEnd(_scatters["body2T"], out, body, INSERT_VALUES, SCATTER_REVERSE);
  VecView(body,PETSC_VIEWER_STDOUT_WORLD);

  VecDestroy(&out);
  VecDestroy(&body);
  assert(0);

  return ierr;
}

Reply via email to