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