Actual source code: matis.c

  1: /*$Id: is.c,v 1.15 2001/08/06 21:15:46 bsmith Exp $*/
  2: /*
  3:     Creates a matrix class for using the Neumann-Neumann type preconditioners.
  4:    This stores the matrices in globally unassembled form. Each processor 
  5:    assembles only its local Neumann problem and the parallel matrix vector 
  6:    product is handled "implicitly".

  8:      We provide:
  9:          MatMult()

 11:     Currently this allows for only one subdomain per processor.

 13: */

 15:  #include src/mat/impls/is/matis.h

 19: int MatDestroy_IS(Mat A)
 20: {
 21:   int    ierr;
 22:   Mat_IS *b = (Mat_IS*)A->data;

 25:   if (b->A) {
 26:     MatDestroy(b->A);
 27:   }
 28:   if (b->ctx) {
 29:     VecScatterDestroy(b->ctx);
 30:   }
 31:   if (b->x) {
 32:     VecDestroy(b->x);
 33:   }
 34:   if (b->y) {
 35:     VecDestroy(b->y);
 36:   }
 37:   if (b->mapping) {
 38:     ISLocalToGlobalMappingDestroy(b->mapping);
 39:   }
 40:   PetscFree(b);
 41:   return(0);
 42: }

 46: int MatMult_IS(Mat A,Vec x,Vec y)
 47: {
 48:   int         ierr;
 49:   Mat_IS      *is = (Mat_IS*)A->data;
 50:   PetscScalar zero = 0.0;

 53:   /*  scatter the global vector x into the local work vector */
 54:   VecScatterBegin(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);
 55:   VecScatterEnd(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);

 57:   /* multiply the local matrix */
 58:   MatMult(is->A,is->x,is->y);

 60:   /* scatter product back into global memory */
 61:   VecSet(&zero,y);
 62:   VecScatterBegin(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);
 63:   VecScatterEnd(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);

 65:   return(0);
 66: }

 70: int MatView_IS(Mat A,PetscViewer viewer)
 71: {
 72:   Mat_IS      *a = (Mat_IS*)A->data;
 73:   int         ierr;
 74:   PetscViewer sviewer;

 77:   PetscViewerGetSingleton(viewer,&sviewer);
 78:   MatView(a->A,sviewer);
 79:   PetscViewerRestoreSingleton(viewer,&sviewer);
 80:   return(0);
 81: }

 85: int MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping mapping)
 86: {
 87:   int    ierr,n;
 88:   Mat_IS *is = (Mat_IS*)A->data;
 89:   IS     from,to;
 90:   Vec    global;

 93:   is->mapping = mapping;
 94:   PetscObjectReference((PetscObject)mapping);

 96:   /* Create the local matrix A */
 97:   ISLocalToGlobalMappingGetSize(mapping,&n);
 98:   MatCreate(PETSC_COMM_SELF,n,n,n,n,&is->A);
 99:   PetscObjectSetOptionsPrefix((PetscObject)is->A,"is");
100:   MatSetFromOptions(is->A);

102:   /* Create the local work vectors */
103:   VecCreateSeq(PETSC_COMM_SELF,n,&is->x);
104:   VecDuplicate(is->x,&is->y);

106:   /* setup the global to local scatter */
107:   ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);
108:   ISLocalToGlobalMappingApplyIS(mapping,to,&from);
109:   VecCreateMPI(A->comm,A->n,A->N,&global);
110:   VecScatterCreate(global,from,is->x,to,&is->ctx);
111:   VecDestroy(global);
112:   ISDestroy(to);
113:   ISDestroy(from);
114:   return(0);
115: }


120: int MatSetValuesLocal_IS(Mat A,int m,const int *rows, int n,const int *cols,const PetscScalar *values,InsertMode addv)
121: {
122:   int    ierr;
123:   Mat_IS *is = (Mat_IS*)A->data;

126:   MatSetValues(is->A,m,rows,n,cols,values,addv);
127:   return(0);
128: }

132: int MatZeroRowsLocal_IS(Mat A,IS isrows,const PetscScalar *diag)
133: {
134:   Mat_IS      *is = (Mat_IS*)A->data;
135:   int         ierr,i,n,*rows;
136:   PetscScalar *array;


140:   {
141:     /*
142:        Set up is->x as a "counting vector". This is in order to MatMult_IS
143:        work properly in the interface nodes.
144:     */
145:     Vec         counter;
146:     PetscScalar one=1.0, zero=0.0;
147:     VecCreateMPI(A->comm,A->n,A->N,&counter);
148:     VecSet(&zero,counter);
149:     VecSet(&one,is->x);
150:     VecScatterBegin(is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);
151:     VecScatterEnd  (is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);
152:     VecScatterBegin(counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);
153:     VecScatterEnd  (counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);
154:     VecDestroy(counter);
155:   }
156:   ISGetLocalSize(isrows,&n);
157:   if (n == 0) {
158:     is->pure_neumann = PETSC_TRUE;
159:   } else {
160:     is->pure_neumann = PETSC_FALSE;
161:     ISGetIndices(isrows,&rows);
162:     VecGetArray(is->x,&array);
163:     MatZeroRows(is->A,isrows,diag);
164:     for (i=0; i<n; i++) {
165:       MatSetValue(is->A,rows[i],rows[i],(*diag)/(array[rows[i]]),INSERT_VALUES);
166:     }
167:     MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);
168:     MatAssemblyEnd  (is->A,MAT_FINAL_ASSEMBLY);
169:     VecRestoreArray(is->x,&array);
170:     ISRestoreIndices(isrows,&rows);
171:   }

173:   return(0);
174: }

178: int MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
179: {
180:   Mat_IS *is = (Mat_IS*)A->data;
181:   int    ierr;

184:   MatAssemblyBegin(is->A,type);
185:   return(0);
186: }

190: int MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
191: {
192:   Mat_IS *is = (Mat_IS*)A->data;
193:   int    ierr;

196:   MatAssemblyEnd(is->A,type);
197:   return(0);
198: }

200: EXTERN_C_BEGIN
203: int MatISGetLocalMat_IS(Mat mat,Mat *local)
204: {
205:   Mat_IS *is = (Mat_IS *)mat->data;
206: 
208:   *local = is->A;
209:   return(0);
210: }
211: EXTERN_C_END

215: /*@
216:     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.

218:   Input Parameter:
219: .  mat - the matrix

221:   Output Parameter:
222: .  local - the local matrix usually MATSEQAIJ

224:   Level: advanced

226:   Notes:
227:     This can be called if you have precomputed the nonzero structure of the 
228:   matrix and want to provide it to the inner matrix object to improve the performance
229:   of the MatSetValues() operation.

231: .seealso: MATIS
232: @*/
233: int MatISGetLocalMat(Mat mat,Mat *local)
234: {
235:   int ierr,(*f)(Mat,Mat *);

240:   PetscObjectQueryFunction((PetscObject)mat,"MatISGetLocalMat_C",(void (**)(void))&f);
241:   if (f) {
242:     (*f)(mat,local);
243:   } else {
244:     local = 0;
245:   }
246:   return(0);
247: }

249: /*MC
250:    MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners.
251:    This stores the matrices in globally unassembled form. Each processor 
252:    assembles only its local Neumann problem and the parallel matrix vector 
253:    product is handled "implicitly".

255:    Operations Provided:
256: .  MatMult

258:    Options Database Keys:
259: . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()

261:    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
262:     
263:           You must call MatSetLocalToGlobalMapping() before using this matrix type.

265:           You can do matrix preallocation on the local matrix after you obtain it with 
266:           MatISGetLocalMat()

268:   Level: advanced

270: .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping()

272: M*/

274: EXTERN_C_BEGIN
277: int MatCreate_IS(Mat A)
278: {
279:   int    ierr;
280:   Mat_IS *b;

283:   PetscNew(Mat_IS,&b);
284:   A->data             = (void*)b;
285:   PetscMemzero(b,sizeof(Mat_IS));
286:   PetscMemzero(A->ops,sizeof(struct _MatOps));
287:   A->factor           = 0;
288:   A->mapping          = 0;

290:   A->ops->mult                    = MatMult_IS;
291:   A->ops->destroy                 = MatDestroy_IS;
292:   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
293:   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
294:   A->ops->zerorowslocal           = MatZeroRowsLocal_IS;
295:   A->ops->assemblybegin           = MatAssemblyBegin_IS;
296:   A->ops->assemblyend             = MatAssemblyEnd_IS;
297:   A->ops->view                    = MatView_IS;

299:   PetscSplitOwnership(A->comm,&A->m,&A->M);
300:   PetscSplitOwnership(A->comm,&A->n,&A->N);
301:   MPI_Scan(&A->m,&b->rend,1,MPI_INT,MPI_SUM,A->comm);
302:   b->rstart = b->rend - A->m;

304:   b->A          = 0;
305:   b->ctx        = 0;
306:   b->x          = 0;
307:   b->y          = 0;
308:   PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISGetLocalMat_C","MatISGetLocalMat_IS",MatISGetLocalMat_IS);

310:   return(0);
311: }
312: EXTERN_C_END