Hi,

I am trying to do something apparently really simple but with no success.

I need to perform a matrix-vector multiplication x = B f , where the length
of x is bigger than the length of f (or viceversa). Thus, B cannot be
created using DMCreateMatrix.

Both x and f are obtained from different DMs, the smaller covering only a
subdomain of the larger. The application is to apply a control f to a
system, e.g. \dot{x} = A x + B f.

The problem is, when running on more than one core, the vector x is not
organized as I would expect (everything works fine on a single core).

I attach a short example where B is intended to map f to the interior of x.

mpirun -n 1 ./test -draw_pause -1     works fine while
mpirun -n 2 ./test -draw_pause -1     shows the problem

I have not found any example with non square matrices in the src folder,
any help is very welcome.

Thanks for your time,

Gianluca
static char help[]="Test for x = B f";

#include <petscdmda.h>

int main(int argc,char **argv) {
  PetscErrorCode ierr =0;
  PetscInitialize(&argc,&argv,(char*)0,help);
  int Mx = 20, Nx = 10; // domain size
  int bs = 1;		// depth of the boundary
  DM dax,daf;		// domain and interior point da
  Vec x,f;		// vectors for each domain
  Mat B;		// matrix x = B f
  DMDACreate2d(PETSC_COMM_WORLD , DM_BOUNDARY_GHOSTED , DM_BOUNDARY_GHOSTED , DMDA_STENCIL_BOX ,
      Mx      , Nx      , PETSC_DECIDE , PETSC_DECIDE , 1 , 0 , 0 , 0 , &dax); 
  DMDACreate2d(PETSC_COMM_WORLD , DM_BOUNDARY_NONE    , DM_BOUNDARY_NONE    , DMDA_STENCIL_BOX ,
      Mx-2*bs , Nx-2*bs , PETSC_DECIDE , PETSC_DECIDE , 1 , 0 , 0 , 0 , &daf); 

  // Creating the vectors
  DMCreateGlobalVector(dax,&x); 
  DMCreateGlobalVector(daf,&f); 
  VecSet(f,1.); 
  VecSet(x,0.); 

  // Creating the matrix
  DMDALocalInfo infox,infof; 
  DMDAGetLocalInfo(dax,&infox); 
  DMDAGetLocalInfo(daf,&infof); 
  PetscInt nrows = infox.xm * infox.ym * infox.dof,
	   ncols = infof.xm * infof.ym * infof.dof; 
  MatCreate(PETSC_COMM_WORLD,&B); 
  MatSetSizes(B,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE); 
  MatSetFromOptions(B); 
  MatSeqAIJSetPreallocation(B,1,NULL); 
  MatMPIAIJSetPreallocation(B,1,NULL,1,NULL); 

  ISLocalToGlobalMapping xmap,fmap; 
  DMGetLocalToGlobalMapping(dax,&xmap); 
  DMGetLocalToGlobalMapping(daf,&fmap); 
  MatSetLocalToGlobalMapping(B,xmap,fmap); 

  // Filling the matrix
  PetscInt xs = infox.xs,
	   xe = infox.xs+infox.xm,
	   ys = infox.ys,
	   ye = infox.ys+infox.ym; 
  if (ys ==        0) ys+=bs; 
  if (ye == infox.my) ye-=bs; 
  if (xs ==        0) xs+=bs; 
  if (xe == infox.mx) xe-=bs; 

  for (int j = ys; j < ye; j++) {
    for (int i = xs; i < xe; i++) {
      for (int k = 0; k < infof.dof; k++) {
	int row = k+ i    * infox.dof +  j     * infox.dof * infox.mx; 
	int col = k+(i-bs)* infof.dof + (j-bs) * infof.dof * infof.mx; 
	const PetscScalar one = 1.; 
	MatSetValue(B,row,col,one,INSERT_VALUES); 
      }
    }
  }
  MatAssemblyBegin ( B,MAT_FINAL_ASSEMBLY ); 
  MatAssemblyEnd   ( B,MAT_FINAL_ASSEMBLY ); 

  // Multiplying and viewing
  MatMult(B,f,x); 
  VecView(x,PETSC_VIEWER_DRAW_WORLD); 
  PetscFinalize(); 

}

Reply via email to