1 #define PETSCMAT_DLL 2 3 /* 4 Creates a matrix class for using the Neumann-Neumann type preconditioners. 5 This stores the matrices in globally unassembled form. Each processor 6 assembles only its local Neumann problem and the parallel matrix vector 7 product is handled "implicitly". 8 9 We provide: 10 MatMult() 11 12 Currently this allows for only one subdomain per processor. 13 14 */ 15 16 #include "src/mat/impls/is/matis.h" /*I "petscmat.h" I*/ 17 18 #undef __FUNCT__ 19 #define __FUNCT__ "MatDestroy_IS" 20 PetscErrorCode MatDestroy_IS(Mat A) 21 { 22 PetscErrorCode ierr; 23 Mat_IS *b = (Mat_IS*)A->data; 24 25 PetscFunctionBegin; 26 if (b->A) { 27 ierr = MatDestroy(b->A);CHKERRQ(ierr); 28 } 29 if (b->ctx) { 30 ierr = VecScatterDestroy(b->ctx);CHKERRQ(ierr); 31 } 32 if (b->x) { 33 ierr = VecDestroy(b->x);CHKERRQ(ierr); 34 } 35 if (b->y) { 36 ierr = VecDestroy(b->y);CHKERRQ(ierr); 37 } 38 if (b->mapping) { 39 ierr = ISLocalToGlobalMappingDestroy(b->mapping);CHKERRQ(ierr); 40 } 41 ierr = PetscFree(b);CHKERRQ(ierr); 42 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 43 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C","",PETSC_NULL);CHKERRQ(ierr); 44 PetscFunctionReturn(0); 45 } 46 47 #undef __FUNCT__ 48 #define __FUNCT__ "MatMult_IS" 49 PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 50 { 51 PetscErrorCode ierr; 52 Mat_IS *is = (Mat_IS*)A->data; 53 PetscScalar zero = 0.0; 54 55 PetscFunctionBegin; 56 /* scatter the global vector x into the local work vector */ 57 ierr = VecScatterBegin(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr); 58 ierr = VecScatterEnd(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr); 59 60 /* multiply the local matrix */ 61 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 62 63 /* scatter product back into global memory */ 64 ierr = VecSet(y,zero);CHKERRQ(ierr); 65 ierr = VecScatterBegin(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr); 66 ierr = VecScatterEnd(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr); 67 68 PetscFunctionReturn(0); 69 } 70 71 #undef __FUNCT__ 72 #define __FUNCT__ "MatView_IS" 73 PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 74 { 75 Mat_IS *a = (Mat_IS*)A->data; 76 PetscErrorCode ierr; 77 PetscViewer sviewer; 78 79 PetscFunctionBegin; 80 ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 81 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 82 ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 83 PetscFunctionReturn(0); 84 } 85 86 #undef __FUNCT__ 87 #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 88 PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping mapping) 89 { 90 PetscErrorCode ierr; 91 PetscInt n; 92 Mat_IS *is = (Mat_IS*)A->data; 93 IS from,to; 94 Vec global; 95 96 PetscFunctionBegin; 97 is->mapping = mapping; 98 ierr = PetscObjectReference((PetscObject)mapping);CHKERRQ(ierr); 99 100 /* Create the local matrix A */ 101 ierr = ISLocalToGlobalMappingGetSize(mapping,&n);CHKERRQ(ierr); 102 ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 103 ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr); 104 ierr = PetscObjectSetOptionsPrefix((PetscObject)is->A,"is");CHKERRQ(ierr); 105 ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 106 107 /* Create the local work vectors */ 108 ierr = VecCreateSeq(PETSC_COMM_SELF,n,&is->x);CHKERRQ(ierr); 109 ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr); 110 111 /* setup the global to local scatter */ 112 ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr); 113 ierr = ISLocalToGlobalMappingApplyIS(mapping,to,&from);CHKERRQ(ierr); 114 ierr = VecCreateMPI(A->comm,A->cmap.n,A->cmap.N,&global);CHKERRQ(ierr); 115 ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr); 116 ierr = VecDestroy(global);CHKERRQ(ierr); 117 ierr = ISDestroy(to);CHKERRQ(ierr); 118 ierr = ISDestroy(from);CHKERRQ(ierr); 119 PetscFunctionReturn(0); 120 } 121 122 123 #undef __FUNCT__ 124 #define __FUNCT__ "MatSetValuesLocal_IS" 125 PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 126 { 127 PetscErrorCode ierr; 128 Mat_IS *is = (Mat_IS*)A->data; 129 130 PetscFunctionBegin; 131 ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 132 PetscFunctionReturn(0); 133 } 134 135 #undef __FUNCT__ 136 #define __FUNCT__ "MatZeroRowsLocal_IS" 137 PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag) 138 { 139 Mat_IS *is = (Mat_IS*)A->data; 140 PetscErrorCode ierr; 141 PetscInt i; 142 PetscScalar *array; 143 144 PetscFunctionBegin; 145 { 146 /* 147 Set up is->x as a "counting vector". This is in order to MatMult_IS 148 work properly in the interface nodes. 149 */ 150 Vec counter; 151 PetscScalar one=1.0, zero=0.0; 152 ierr = VecCreateMPI(A->comm,A->cmap.n,A->cmap.N,&counter);CHKERRQ(ierr); 153 ierr = VecSet(counter,zero);CHKERRQ(ierr); 154 ierr = VecSet(is->x,one);CHKERRQ(ierr); 155 ierr = VecScatterBegin(is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr); 156 ierr = VecScatterEnd (is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr); 157 ierr = VecScatterBegin(counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr); 158 ierr = VecScatterEnd (counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr); 159 ierr = VecDestroy(counter);CHKERRQ(ierr); 160 } 161 if (!n) { 162 is->pure_neumann = PETSC_TRUE; 163 } else { 164 is->pure_neumann = PETSC_FALSE; 165 ierr = VecGetArray(is->x,&array);CHKERRQ(ierr); 166 ierr = MatZeroRows(is->A,n,rows,diag);CHKERRQ(ierr); 167 for (i=0; i<n; i++) { 168 ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 169 } 170 ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 171 ierr = MatAssemblyEnd (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 172 ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr); 173 } 174 175 PetscFunctionReturn(0); 176 } 177 178 #undef __FUNCT__ 179 #define __FUNCT__ "MatAssemblyBegin_IS" 180 PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 181 { 182 Mat_IS *is = (Mat_IS*)A->data; 183 PetscErrorCode ierr; 184 185 PetscFunctionBegin; 186 ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 187 PetscFunctionReturn(0); 188 } 189 190 #undef __FUNCT__ 191 #define __FUNCT__ "MatAssemblyEnd_IS" 192 PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 193 { 194 Mat_IS *is = (Mat_IS*)A->data; 195 PetscErrorCode ierr; 196 197 PetscFunctionBegin; 198 ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 199 PetscFunctionReturn(0); 200 } 201 202 EXTERN_C_BEGIN 203 #undef __FUNCT__ 204 #define __FUNCT__ "MatISGetLocalMat_IS" 205 PetscErrorCode PETSCMAT_DLLEXPORT MatISGetLocalMat_IS(Mat mat,Mat *local) 206 { 207 Mat_IS *is = (Mat_IS *)mat->data; 208 209 PetscFunctionBegin; 210 *local = is->A; 211 PetscFunctionReturn(0); 212 } 213 EXTERN_C_END 214 215 #undef __FUNCT__ 216 #define __FUNCT__ "MatISGetLocalMat" 217 /*@ 218 MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 219 220 Input Parameter: 221 . mat - the matrix 222 223 Output Parameter: 224 . local - the local matrix usually MATSEQAIJ 225 226 Level: advanced 227 228 Notes: 229 This can be called if you have precomputed the nonzero structure of the 230 matrix and want to provide it to the inner matrix object to improve the performance 231 of the MatSetValues() operation. 232 233 .seealso: MATIS 234 @*/ 235 PetscErrorCode PETSCMAT_DLLEXPORT MatISGetLocalMat(Mat mat,Mat *local) 236 { 237 PetscErrorCode ierr,(*f)(Mat,Mat *); 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 241 PetscValidPointer(local,2); 242 ierr = PetscObjectQueryFunction((PetscObject)mat,"MatISGetLocalMat_C",(void (**)(void))&f);CHKERRQ(ierr); 243 if (f) { 244 ierr = (*f)(mat,local);CHKERRQ(ierr); 245 } else { 246 local = 0; 247 } 248 PetscFunctionReturn(0); 249 } 250 251 #undef __FUNCT__ 252 #define __FUNCT__ "MatZeroEntries_IS" 253 PetscErrorCode MatZeroEntries_IS(Mat A) 254 { 255 Mat_IS *a = (Mat_IS*)A->data; 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 260 PetscFunctionReturn(0); 261 } 262 263 #undef __FUNCT__ 264 #define __FUNCT__ "MatSetOption_IS" 265 PetscErrorCode MatSetOption_IS(Mat A,MatOption op) 266 { 267 Mat_IS *a = (Mat_IS*)A->data; 268 PetscErrorCode ierr; 269 270 PetscFunctionBegin; 271 ierr = MatSetOption(a->A,op);CHKERRQ(ierr); 272 PetscFunctionReturn(0); 273 } 274 275 #undef __FUNCT__ 276 #define __FUNCT__ "MatCreateIS" 277 /*@ 278 MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each 279 process but not across processes. 280 281 Input Parameters: 282 + comm - MPI communicator that will share the matrix 283 . m,n,M,N - local and/or global sizes of the the left and right vector used in matrix vector products 284 - map - mapping that defines the global number for each local number 285 286 Output Parameter: 287 . A - the resulting matrix 288 289 Level: advanced 290 291 Notes: See MATIS for more details 292 m and n are NOT related to the size of the map 293 294 .seealso: MATIS, MatSetLocalToGlobalMapping() 295 @*/ 296 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateIS(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A) 297 { 298 PetscErrorCode ierr; 299 300 PetscFunctionBegin; 301 ierr = MatCreate(comm,A);CHKERRQ(ierr); 302 ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 303 ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 304 ierr = MatSetLocalToGlobalMapping(*A,map);CHKERRQ(ierr); 305 PetscFunctionReturn(0); 306 } 307 308 /*MC 309 MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners. 310 This stores the matrices in globally unassembled form. Each processor 311 assembles only its local Neumann problem and the parallel matrix vector 312 product is handled "implicitly". 313 314 Operations Provided: 315 + MatMult() 316 . MatZeroEntries() 317 . MatSetOption() 318 . MatZeroRowsLocal() 319 . MatSetValuesLocal() 320 - MatSetLocalToGlobalMapping() 321 322 Options Database Keys: 323 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 324 325 Notes: Options prefix for the inner matrix are given by -is_mat_xxx 326 327 You must call MatSetLocalToGlobalMapping() before using this matrix type. 328 329 You can do matrix preallocation on the local matrix after you obtain it with 330 MatISGetLocalMat() 331 332 Level: advanced 333 334 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping() 335 336 M*/ 337 338 EXTERN_C_BEGIN 339 #undef __FUNCT__ 340 #define __FUNCT__ "MatCreate_IS" 341 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_IS(Mat A) 342 { 343 PetscErrorCode ierr; 344 Mat_IS *b; 345 346 PetscFunctionBegin; 347 ierr = PetscNew(Mat_IS,&b);CHKERRQ(ierr); 348 A->data = (void*)b; 349 ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 350 A->factor = 0; 351 A->mapping = 0; 352 353 A->ops->mult = MatMult_IS; 354 A->ops->destroy = MatDestroy_IS; 355 A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 356 A->ops->setvalueslocal = MatSetValuesLocal_IS; 357 A->ops->zerorowslocal = MatZeroRowsLocal_IS; 358 A->ops->assemblybegin = MatAssemblyBegin_IS; 359 A->ops->assemblyend = MatAssemblyEnd_IS; 360 A->ops->view = MatView_IS; 361 A->ops->zeroentries = MatZeroEntries_IS; 362 A->ops->setoption = MatSetOption_IS; 363 364 ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr); 365 ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr); 366 367 b->A = 0; 368 b->ctx = 0; 369 b->x = 0; 370 b->y = 0; 371 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISGetLocalMat_C","MatISGetLocalMat_IS",MatISGetLocalMat_IS);CHKERRQ(ierr); 372 ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 373 374 PetscFunctionReturn(0); 375 } 376 EXTERN_C_END 377 378 379 380 381 382 383 384 385 386 387 388 389 390