1 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". 7 8 We provide: 9 MatMult() 10 11 Currently this allows for only one subdomain per processor. 12 13 */ 14 15 #include <../src/mat/impls/is/matis.h> /*I "petscmat.h" I*/ 16 17 static PetscErrorCode MatISComputeSF_Private(Mat); 18 19 #undef __FUNCT__ 20 #define __FUNCT__ "MatISComputeSF_Private" 21 static PetscErrorCode MatISComputeSF_Private(Mat B) 22 { 23 Mat_IS *matis = (Mat_IS*)(B->data); 24 const PetscInt *gidxs; 25 PetscErrorCode ierr; 26 27 PetscFunctionBegin; 28 ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr); 29 ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr); 30 ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 31 ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,&gidxs);CHKERRQ(ierr); 32 /* PETSC_OWN_POINTER refers to ilocal which is NULL */ 33 ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 34 ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,&gidxs);CHKERRQ(ierr); 35 ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "MatISSetPreallocation" 41 /* 42 MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 43 44 Collective on MPI_Comm 45 46 Input Parameters: 47 + B - the matrix 48 . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 49 (same value is used for all local rows) 50 . d_nnz - array containing the number of nonzeros in the various rows of the 51 DIAGONAL portion of the local submatrix (possibly different for each row) 52 or NULL, if d_nz is used to specify the nonzero structure. 53 The size of this array is equal to the number of local rows, i.e 'm'. 54 For matrices that will be factored, you must leave room for (and set) 55 the diagonal entry even if it is zero. 56 . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 57 submatrix (same value is used for all local rows). 58 - o_nnz - array containing the number of nonzeros in the various rows of the 59 OFF-DIAGONAL portion of the local submatrix (possibly different for 60 each row) or NULL, if o_nz is used to specify the nonzero 61 structure. The size of this array is equal to the number 62 of local rows, i.e 'm'. 63 64 If the *_nnz parameter is given then the *_nz parameter is ignored 65 66 Level: intermediate 67 68 Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 69 from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 70 matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 71 72 .keywords: matrix 73 74 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat() 75 @*/ 76 PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 77 { 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 82 PetscValidType(B,1); 83 ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 84 PetscFunctionReturn(0); 85 } 86 87 #undef __FUNCT__ 88 #define __FUNCT__ "MatISSetPreallocation_IS" 89 PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 90 { 91 Mat_IS *matis = (Mat_IS*)(B->data); 92 PetscInt bs,i,nlocalcols; 93 PetscErrorCode ierr; 94 95 PetscFunctionBegin; 96 if (!matis->A) { 97 SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 98 } 99 if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 100 ierr = MatISComputeSF_Private(B);CHKERRQ(ierr); 101 } 102 if (!d_nnz) { 103 for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz; 104 } else { 105 for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 106 } 107 if (!o_nnz) { 108 for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz; 109 } else { 110 for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 111 } 112 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 113 ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 114 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 115 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 116 for (i=0;i<matis->sf_nleaves;i++) { 117 matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 118 } 119 ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 120 for (i=0;i<matis->sf_nleaves/bs;i++) { 121 matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 122 } 123 ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 124 for (i=0;i<matis->sf_nleaves/bs;i++) { 125 matis->sf_leafdata[i] = matis->sf_leafdata[i]-i; 126 } 127 ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 128 PetscFunctionReturn(0); 129 } 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private" 133 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 134 { 135 Mat_IS *matis = (Mat_IS*)(A->data); 136 PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 137 const PetscInt* global_indices; 138 PetscInt i,j,bs,rows,cols; 139 PetscInt lrows,lcols; 140 PetscInt local_rows,local_cols; 141 PetscMPIInt nsubdomains; 142 PetscBool isdense,issbaij; 143 PetscErrorCode ierr; 144 145 PetscFunctionBegin; 146 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr); 147 ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 148 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 149 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 150 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 151 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 152 ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,&global_indices);CHKERRQ(ierr); 153 if (issbaij) { 154 ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 155 } 156 /* 157 An SF reduce is needed to sum up properly on shared interface dofs. 158 Note that generally preallocation is not exact, since it overestimates nonzeros 159 */ 160 if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */ 161 ierr = MatISComputeSF_Private(A);CHKERRQ(ierr); 162 } 163 ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 164 ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 165 /* All processes need to compute entire row ownership */ 166 ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 167 ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 168 for (i=0;i<nsubdomains;i++) { 169 for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 170 row_ownership[j]=i; 171 } 172 } 173 174 /* 175 my_dnz and my_onz contains exact contribution to preallocation from each local mat 176 then, they will be summed up properly. This way, preallocation is always sufficient 177 */ 178 ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 179 /* preallocation as a MATAIJ */ 180 if (isdense) { /* special case for dense local matrices */ 181 for (i=0;i<local_rows;i++) { 182 PetscInt index_row = global_indices[i]; 183 for (j=i;j<local_rows;j++) { 184 PetscInt owner = row_ownership[index_row]; 185 PetscInt index_col = global_indices[j]; 186 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 187 my_dnz[i] += 1; 188 } else { /* offdiag block */ 189 my_onz[i] += 1; 190 } 191 /* same as before, interchanging rows and cols */ 192 if (i != j) { 193 owner = row_ownership[index_col]; 194 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 195 my_dnz[j] += 1; 196 } else { 197 my_onz[j] += 1; 198 } 199 } 200 } 201 } 202 } else { 203 for (i=0;i<local_rows;i++) { 204 const PetscInt *cols; 205 PetscInt ncols,index_row = global_indices[i]; 206 ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 207 for (j=0;j<ncols;j++) { 208 PetscInt owner = row_ownership[index_row]; 209 PetscInt index_col = global_indices[cols[j]]; 210 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 211 my_dnz[i] += 1; 212 } else { /* offdiag block */ 213 my_onz[i] += 1; 214 } 215 /* same as before, interchanging rows and cols */ 216 if (issbaij) { 217 owner = row_ownership[index_col]; 218 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 219 my_dnz[j] += 1; 220 } else { 221 my_onz[j] += 1; 222 } 223 } 224 } 225 ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 226 } 227 } 228 ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,&global_indices);CHKERRQ(ierr); 229 ierr = PetscFree(row_ownership);CHKERRQ(ierr); 230 if (maxreduce) { 231 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 232 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 233 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 234 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 235 } else { 236 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 237 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 238 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 239 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 240 } 241 ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 242 243 /* Resize preallocation if overestimated */ 244 for (i=0;i<lrows;i++) { 245 dnz[i] = PetscMin(dnz[i],lcols); 246 onz[i] = PetscMin(onz[i],cols-lcols); 247 } 248 /* set preallocation */ 249 ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 250 for (i=0;i<lrows/bs;i++) { 251 dnz[i] = dnz[i*bs]/bs; 252 onz[i] = onz[i*bs]/bs; 253 } 254 ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 255 for (i=0;i<lrows/bs;i++) { 256 dnz[i] = dnz[i]-i; 257 } 258 ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 259 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 260 if (issbaij) { 261 ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 262 } 263 PetscFunctionReturn(0); 264 } 265 266 #undef __FUNCT__ 267 #define __FUNCT__ "MatISGetMPIXAIJ_IS" 268 PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) 269 { 270 Mat_IS *matis = (Mat_IS*)(mat->data); 271 /* info on mat */ 272 /* ISLocalToGlobalMapping rmapping,cmapping; */ 273 PetscInt bs,rows,cols,lrows,lcols; 274 PetscInt local_rows,local_cols; 275 PetscBool isdense,issbaij,isseqaij; 276 const PetscInt *global_indices_rows; 277 PetscMPIInt nsubdomains; 278 /* values insertion */ 279 PetscScalar *array; 280 /* work */ 281 PetscErrorCode ierr; 282 283 PetscFunctionBegin; 284 /* MISSING CHECKS 285 - rectangular case not covered (it is not allowed by MATIS) 286 */ 287 /* get info from mat */ 288 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); 289 if (nsubdomains == 1) { 290 if (reuse == MAT_INITIAL_MATRIX) { 291 ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr); 292 } else { 293 ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 294 } 295 PetscFunctionReturn(0); 296 } 297 /* ierr = MatGetLocalToGlobalMapping(mat,&rmapping,&cmapping);CHKERRQ(ierr); */ 298 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 299 ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 300 ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 301 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 302 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 303 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 304 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 305 306 /* map indices of local mat rows to global values */ 307 ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,&global_indices_rows);CHKERRQ(ierr); 308 309 if (issbaij) { 310 ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 311 } 312 313 if (reuse == MAT_INITIAL_MATRIX) { 314 MatType new_mat_type; 315 PetscBool issbaij_red; 316 317 /* determining new matrix type */ 318 ierr = MPI_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 319 if (issbaij_red) { 320 new_mat_type = MATSBAIJ; 321 } else { 322 if (bs>1) { 323 new_mat_type = MATBAIJ; 324 } else { 325 new_mat_type = MATAIJ; 326 } 327 } 328 329 ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); 330 ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); 331 ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); 332 ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr); 333 ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); 334 } else { 335 PetscInt mbs,mrows,mcols,mlrows,mlcols; 336 /* some checks */ 337 ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); 338 ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); 339 ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); 340 if (mrows != rows) { 341 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 342 } 343 if (mcols != cols) { 344 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 345 } 346 if (mlrows != lrows) { 347 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 348 } 349 if (mlcols != lcols) { 350 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 351 } 352 if (mbs != bs) { 353 SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); 354 } 355 ierr = MatZeroEntries(*M);CHKERRQ(ierr); 356 } 357 /* set local to global mappings */ 358 /* ierr = MatSetLocalToGlobalMapping(*M,matis->mapping,matis->mapping);CHKERRQ(ierr); */ 359 360 /* Set values */ 361 if (isdense) { /* special case for dense local matrices */ 362 ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 363 ierr = MatDenseGetArray(matis->A,&array);CHKERRQ(ierr); 364 ierr = MatSetValues(*M,local_rows,global_indices_rows,local_cols,global_indices_rows,array,ADD_VALUES);CHKERRQ(ierr); 365 ierr = MatDenseRestoreArray(matis->A,&array);CHKERRQ(ierr); 366 } else if (isseqaij) { 367 PetscInt i,nvtxs,*xadj,*adjncy,*global_indices_cols; 368 PetscBool done; 369 370 ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 371 if (!done) { 372 SETERRQ1(PetscObjectComm((PetscObject)matis->A),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__); 373 } 374 ierr = MatSeqAIJGetArray(matis->A,&array);CHKERRQ(ierr); 375 ierr = PetscMalloc1(xadj[nvtxs],&global_indices_cols);CHKERRQ(ierr); 376 ierr = ISLocalToGlobalMappingApply(matis->mapping,xadj[nvtxs],adjncy,global_indices_cols);CHKERRQ(ierr); 377 for (i=0;i<nvtxs;i++) { 378 PetscInt row,*cols,ncols; 379 PetscScalar *mat_vals; 380 381 row = global_indices_rows[i]; 382 ncols = xadj[i+1]-xadj[i]; 383 cols = global_indices_cols+xadj[i]; 384 mat_vals = array+xadj[i]; 385 ierr = MatSetValues(*M,1,&row,ncols,cols,mat_vals,ADD_VALUES);CHKERRQ(ierr); 386 } 387 ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 388 if (!done) { 389 SETERRQ1(PetscObjectComm((PetscObject)matis->A),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__); 390 } 391 ierr = MatSeqAIJRestoreArray(matis->A,&array);CHKERRQ(ierr); 392 ierr = PetscFree(global_indices_cols);CHKERRQ(ierr); 393 } else { /* very basic values insertion for all other matrix types */ 394 PetscInt i,*global_indices_cols; 395 396 ierr = PetscMalloc1(local_cols,&global_indices_cols);CHKERRQ(ierr); 397 for (i=0;i<local_rows;i++) { 398 PetscInt j; 399 const PetscInt *local_indices; 400 401 ierr = MatGetRow(matis->A,i,&j,&local_indices,(const PetscScalar**)&array);CHKERRQ(ierr); 402 ierr = ISLocalToGlobalMappingApply(matis->mapping,j,local_indices,global_indices_cols);CHKERRQ(ierr); 403 ierr = MatSetValues(*M,1,&global_indices_rows[i],j,global_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 404 ierr = MatRestoreRow(matis->A,i,&j,&local_indices,(const PetscScalar**)&array);CHKERRQ(ierr); 405 } 406 ierr = PetscFree(global_indices_cols);CHKERRQ(ierr); 407 } 408 ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 409 ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 410 if (isdense) { 411 ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 412 } 413 if (issbaij) { 414 ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 415 } 416 ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,&global_indices_rows);CHKERRQ(ierr); 417 PetscFunctionReturn(0); 418 } 419 420 #undef __FUNCT__ 421 #define __FUNCT__ "MatISGetMPIXAIJ" 422 /*@ 423 MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 424 425 Input Parameter: 426 . mat - the matrix (should be of type MATIS) 427 . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 428 429 Output Parameter: 430 . newmat - the matrix in AIJ format 431 432 Level: developer 433 434 Notes: 435 436 .seealso: MATIS 437 @*/ 438 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 439 { 440 PetscErrorCode ierr; 441 442 PetscFunctionBegin; 443 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 444 PetscValidLogicalCollectiveEnum(mat,reuse,2); 445 PetscValidPointer(newmat,3); 446 if (reuse != MAT_INITIAL_MATRIX) { 447 PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 448 PetscCheckSameComm(mat,1,*newmat,3); 449 } 450 ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr); 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNCT__ 455 #define __FUNCT__ "MatDuplicate_IS" 456 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 457 { 458 PetscErrorCode ierr; 459 Mat_IS *matis = (Mat_IS*)(mat->data); 460 PetscInt bs,m,n,M,N; 461 Mat B,localmat; 462 463 PetscFunctionBegin; 464 ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 465 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 466 ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 467 ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,matis->mapping,&B);CHKERRQ(ierr); 468 ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 469 ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 470 ierr = MatDestroy(&localmat);CHKERRQ(ierr); 471 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 472 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 473 *newmat = B; 474 PetscFunctionReturn(0); 475 } 476 477 #undef __FUNCT__ 478 #define __FUNCT__ "MatIsHermitian_IS" 479 PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 480 { 481 PetscErrorCode ierr; 482 Mat_IS *matis = (Mat_IS*)A->data; 483 PetscBool local_sym; 484 485 PetscFunctionBegin; 486 ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 487 ierr = MPI_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 488 PetscFunctionReturn(0); 489 } 490 491 #undef __FUNCT__ 492 #define __FUNCT__ "MatIsSymmetric_IS" 493 PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 494 { 495 PetscErrorCode ierr; 496 Mat_IS *matis = (Mat_IS*)A->data; 497 PetscBool local_sym; 498 499 PetscFunctionBegin; 500 ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 501 ierr = MPI_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 502 PetscFunctionReturn(0); 503 } 504 505 #undef __FUNCT__ 506 #define __FUNCT__ "MatDestroy_IS" 507 PetscErrorCode MatDestroy_IS(Mat A) 508 { 509 PetscErrorCode ierr; 510 Mat_IS *b = (Mat_IS*)A->data; 511 512 PetscFunctionBegin; 513 ierr = MatDestroy(&b->A);CHKERRQ(ierr); 514 ierr = VecScatterDestroy(&b->ctx);CHKERRQ(ierr); 515 ierr = VecDestroy(&b->x);CHKERRQ(ierr); 516 ierr = VecDestroy(&b->y);CHKERRQ(ierr); 517 ierr = ISLocalToGlobalMappingDestroy(&b->mapping);CHKERRQ(ierr); 518 ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 519 ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 520 ierr = PetscFree(A->data);CHKERRQ(ierr); 521 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 522 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 523 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 524 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 525 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 526 PetscFunctionReturn(0); 527 } 528 529 #undef __FUNCT__ 530 #define __FUNCT__ "MatMult_IS" 531 PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 532 { 533 PetscErrorCode ierr; 534 Mat_IS *is = (Mat_IS*)A->data; 535 PetscScalar zero = 0.0; 536 537 PetscFunctionBegin; 538 /* scatter the global vector x into the local work vector */ 539 ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 540 ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 541 542 /* multiply the local matrix */ 543 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 544 545 /* scatter product back into global memory */ 546 ierr = VecSet(y,zero);CHKERRQ(ierr); 547 ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 548 ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 549 PetscFunctionReturn(0); 550 } 551 552 #undef __FUNCT__ 553 #define __FUNCT__ "MatMultAdd_IS" 554 PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 555 { 556 Vec temp_vec; 557 PetscErrorCode ierr; 558 559 PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 560 if (v3 != v2) { 561 ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 562 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 563 } else { 564 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 565 ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 566 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 567 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 568 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 569 } 570 PetscFunctionReturn(0); 571 } 572 573 #undef __FUNCT__ 574 #define __FUNCT__ "MatMultTranspose_IS" 575 PetscErrorCode MatMultTranspose_IS(Mat A,Vec x,Vec y) 576 { 577 Mat_IS *is = (Mat_IS*)A->data; 578 PetscErrorCode ierr; 579 580 PetscFunctionBegin; /* y = A' * x */ 581 /* scatter the global vector x into the local work vector */ 582 ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 583 ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 584 585 /* multiply the local matrix */ 586 ierr = MatMultTranspose(is->A,is->x,is->y);CHKERRQ(ierr); 587 588 /* scatter product back into global vector */ 589 ierr = VecSet(y,0);CHKERRQ(ierr); 590 ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 591 ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 592 PetscFunctionReturn(0); 593 } 594 595 #undef __FUNCT__ 596 #define __FUNCT__ "MatMultTransposeAdd_IS" 597 PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 598 { 599 Vec temp_vec; 600 PetscErrorCode ierr; 601 602 PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 603 if (v3 != v2) { 604 ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 605 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 606 } else { 607 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 608 ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 609 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 610 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 611 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 612 } 613 PetscFunctionReturn(0); 614 } 615 616 #undef __FUNCT__ 617 #define __FUNCT__ "MatView_IS" 618 PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 619 { 620 Mat_IS *a = (Mat_IS*)A->data; 621 PetscErrorCode ierr; 622 PetscViewer sviewer; 623 624 PetscFunctionBegin; 625 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 626 ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 627 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 628 ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 629 PetscFunctionReturn(0); 630 } 631 632 #undef __FUNCT__ 633 #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 634 PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 635 { 636 PetscErrorCode ierr; 637 PetscInt n,bs; 638 Mat_IS *is = (Mat_IS*)A->data; 639 IS from,to; 640 Vec global; 641 642 PetscFunctionBegin; 643 PetscCheckSameComm(A,1,rmapping,2); 644 if (rmapping != cmapping) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MATIS requires the row and column mappings to be identical"); 645 if (is->mapping) { /* Currenly destroys the objects that will be created by this routine. Is there anything else that should be checked? */ 646 ierr = ISLocalToGlobalMappingDestroy(&is->mapping);CHKERRQ(ierr); 647 ierr = VecDestroy(&is->x);CHKERRQ(ierr); 648 ierr = VecDestroy(&is->y);CHKERRQ(ierr); 649 ierr = VecScatterDestroy(&is->ctx);CHKERRQ(ierr); 650 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 651 ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 652 ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 653 } 654 ierr = PetscObjectReference((PetscObject)rmapping);CHKERRQ(ierr); 655 ierr = ISLocalToGlobalMappingDestroy(&is->mapping);CHKERRQ(ierr); 656 is->mapping = rmapping; 657 /* 658 ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 659 ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 660 */ 661 662 /* Create the local matrix A */ 663 ierr = ISLocalToGlobalMappingGetSize(rmapping,&n);CHKERRQ(ierr); 664 ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&bs);CHKERRQ(ierr); 665 ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 666 if (bs > 1) { 667 ierr = MatSetType(is->A,MATSEQBAIJ);CHKERRQ(ierr); 668 } else { 669 ierr = MatSetType(is->A,MATSEQAIJ);CHKERRQ(ierr); 670 } 671 ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr); 672 ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr); 673 ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 674 ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 675 ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 676 677 /* Create the local work vectors */ 678 ierr = VecCreate(PETSC_COMM_SELF,&is->x);CHKERRQ(ierr); 679 ierr = VecSetBlockSize(is->x,bs);CHKERRQ(ierr); 680 ierr = VecSetSizes(is->x,n,n);CHKERRQ(ierr); 681 ierr = VecSetOptionsPrefix(is->x,((PetscObject)A)->prefix);CHKERRQ(ierr); 682 ierr = VecAppendOptionsPrefix(is->x,"is_");CHKERRQ(ierr); 683 ierr = VecSetFromOptions(is->x);CHKERRQ(ierr); 684 ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr); 685 686 /* setup the global to local scatter */ 687 ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr); 688 ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 689 ierr = MatCreateVecs(A,&global,NULL);CHKERRQ(ierr); 690 ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr); 691 ierr = VecDestroy(&global);CHKERRQ(ierr); 692 ierr = ISDestroy(&to);CHKERRQ(ierr); 693 ierr = ISDestroy(&from);CHKERRQ(ierr); 694 PetscFunctionReturn(0); 695 } 696 697 #undef __FUNCT__ 698 #define __FUNCT__ "MatSetValues_IS" 699 PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 700 { 701 Mat_IS *is = (Mat_IS*)mat->data; 702 PetscInt rows_l[2048],cols_l[2048]; 703 PetscErrorCode ierr; 704 705 PetscFunctionBegin; 706 #if defined(PETSC_USE_DEBUG) 707 if (m > 2048 || n > 2048) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= 2048: they are %D %D",m,n); 708 #endif 709 ierr = ISG2LMapApply(is->mapping,m,rows,rows_l);CHKERRQ(ierr); 710 ierr = ISG2LMapApply(is->mapping,n,cols,cols_l);CHKERRQ(ierr); 711 ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 712 PetscFunctionReturn(0); 713 } 714 715 #undef ISG2LMapSetUp 716 #undef ISG2LMapApply 717 718 #undef __FUNCT__ 719 #define __FUNCT__ "MatSetValuesLocal_IS" 720 PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 721 { 722 PetscErrorCode ierr; 723 Mat_IS *is = (Mat_IS*)A->data; 724 725 PetscFunctionBegin; 726 ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 727 PetscFunctionReturn(0); 728 } 729 730 #undef __FUNCT__ 731 #define __FUNCT__ "MatSetValuesBlockedLocal_IS" 732 PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 733 { 734 PetscErrorCode ierr; 735 Mat_IS *is = (Mat_IS*)A->data; 736 737 PetscFunctionBegin; 738 ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 739 PetscFunctionReturn(0); 740 } 741 742 #undef __FUNCT__ 743 #define __FUNCT__ "MatZeroRows_IS" 744 PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 745 { 746 Mat_IS *is = (Mat_IS*)A->data; 747 PetscInt n_l = 0, *rows_l = NULL; 748 PetscErrorCode ierr; 749 750 PetscFunctionBegin; 751 if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support"); 752 if (n) { 753 ierr = PetscMalloc1(n,&rows_l);CHKERRQ(ierr); 754 ierr = ISGlobalToLocalMappingApply(is->mapping,IS_GTOLM_DROP,n,rows,&n_l,rows_l);CHKERRQ(ierr); 755 } 756 ierr = MatZeroRowsLocal(A,n_l,rows_l,diag,x,b);CHKERRQ(ierr); 757 ierr = PetscFree(rows_l);CHKERRQ(ierr); 758 PetscFunctionReturn(0); 759 } 760 761 #undef __FUNCT__ 762 #define __FUNCT__ "MatZeroRowsLocal_IS" 763 PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 764 { 765 Mat_IS *is = (Mat_IS*)A->data; 766 PetscErrorCode ierr; 767 PetscInt i; 768 PetscScalar *array; 769 770 PetscFunctionBegin; 771 if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support"); 772 { 773 /* 774 Set up is->x as a "counting vector". This is in order to MatMult_IS 775 work properly in the interface nodes. 776 */ 777 Vec counter; 778 PetscScalar one=1.0, zero=0.0; 779 ierr = MatCreateVecs(A,&counter,NULL);CHKERRQ(ierr); 780 ierr = VecSet(counter,zero);CHKERRQ(ierr); 781 ierr = VecSet(is->x,one);CHKERRQ(ierr); 782 ierr = VecScatterBegin(is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 783 ierr = VecScatterEnd (is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 784 ierr = VecScatterBegin(is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 785 ierr = VecScatterEnd (is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 786 ierr = VecDestroy(&counter);CHKERRQ(ierr); 787 } 788 if (!n) { 789 is->pure_neumann = PETSC_TRUE; 790 } else { 791 is->pure_neumann = PETSC_FALSE; 792 793 ierr = VecGetArray(is->x,&array);CHKERRQ(ierr); 794 ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 795 for (i=0; i<n; i++) { 796 ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 797 } 798 ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 799 ierr = MatAssemblyEnd (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 800 ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr); 801 } 802 PetscFunctionReturn(0); 803 } 804 805 #undef __FUNCT__ 806 #define __FUNCT__ "MatAssemblyBegin_IS" 807 PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 808 { 809 Mat_IS *is = (Mat_IS*)A->data; 810 PetscErrorCode ierr; 811 812 PetscFunctionBegin; 813 ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 814 PetscFunctionReturn(0); 815 } 816 817 #undef __FUNCT__ 818 #define __FUNCT__ "MatAssemblyEnd_IS" 819 PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 820 { 821 Mat_IS *is = (Mat_IS*)A->data; 822 PetscErrorCode ierr; 823 824 PetscFunctionBegin; 825 ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 826 PetscFunctionReturn(0); 827 } 828 829 #undef __FUNCT__ 830 #define __FUNCT__ "MatISGetLocalMat_IS" 831 PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 832 { 833 Mat_IS *is = (Mat_IS*)mat->data; 834 835 PetscFunctionBegin; 836 *local = is->A; 837 PetscFunctionReturn(0); 838 } 839 840 #undef __FUNCT__ 841 #define __FUNCT__ "MatISGetLocalMat" 842 /*@ 843 MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 844 845 Input Parameter: 846 . mat - the matrix 847 848 Output Parameter: 849 . local - the local matrix usually MATSEQAIJ 850 851 Level: advanced 852 853 Notes: 854 This can be called if you have precomputed the nonzero structure of the 855 matrix and want to provide it to the inner matrix object to improve the performance 856 of the MatSetValues() operation. 857 858 .seealso: MATIS 859 @*/ 860 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 861 { 862 PetscErrorCode ierr; 863 864 PetscFunctionBegin; 865 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 866 PetscValidPointer(local,2); 867 ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 868 PetscFunctionReturn(0); 869 } 870 871 #undef __FUNCT__ 872 #define __FUNCT__ "MatISSetLocalMat_IS" 873 PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 874 { 875 Mat_IS *is = (Mat_IS*)mat->data; 876 PetscInt nrows,ncols,orows,ocols; 877 PetscErrorCode ierr; 878 879 PetscFunctionBegin; 880 if (is->A) { 881 ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 882 ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 883 if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %dx%d (you passed a %dx%d matrix)\n",orows,ocols,nrows,ncols); 884 } 885 ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 886 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 887 is->A = local; 888 PetscFunctionReturn(0); 889 } 890 891 #undef __FUNCT__ 892 #define __FUNCT__ "MatISSetLocalMat" 893 /*@ 894 MatISSetLocalMat - Set the local matrix stored inside a MATIS matrix. 895 896 Input Parameter: 897 . mat - the matrix 898 . local - the local matrix usually MATSEQAIJ 899 900 Output Parameter: 901 902 Level: advanced 903 904 Notes: 905 This can be called if you have precomputed the local matrix and 906 want to provide it to the matrix object MATIS. 907 908 .seealso: MATIS 909 @*/ 910 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 911 { 912 PetscErrorCode ierr; 913 914 PetscFunctionBegin; 915 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 916 PetscValidHeaderSpecific(local,MAT_CLASSID,2); 917 ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 918 PetscFunctionReturn(0); 919 } 920 921 #undef __FUNCT__ 922 #define __FUNCT__ "MatZeroEntries_IS" 923 PetscErrorCode MatZeroEntries_IS(Mat A) 924 { 925 Mat_IS *a = (Mat_IS*)A->data; 926 PetscErrorCode ierr; 927 928 PetscFunctionBegin; 929 ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 #undef __FUNCT__ 934 #define __FUNCT__ "MatScale_IS" 935 PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 936 { 937 Mat_IS *is = (Mat_IS*)A->data; 938 PetscErrorCode ierr; 939 940 PetscFunctionBegin; 941 ierr = MatScale(is->A,a);CHKERRQ(ierr); 942 PetscFunctionReturn(0); 943 } 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "MatGetDiagonal_IS" 947 PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 948 { 949 Mat_IS *is = (Mat_IS*)A->data; 950 PetscErrorCode ierr; 951 952 PetscFunctionBegin; 953 /* get diagonal of the local matrix */ 954 ierr = MatGetDiagonal(is->A,is->x);CHKERRQ(ierr); 955 956 /* scatter diagonal back into global vector */ 957 ierr = VecSet(v,0);CHKERRQ(ierr); 958 ierr = VecScatterBegin(is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 959 ierr = VecScatterEnd (is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 960 PetscFunctionReturn(0); 961 } 962 963 #undef __FUNCT__ 964 #define __FUNCT__ "MatSetOption_IS" 965 PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 966 { 967 Mat_IS *a = (Mat_IS*)A->data; 968 PetscErrorCode ierr; 969 970 PetscFunctionBegin; 971 ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 972 PetscFunctionReturn(0); 973 } 974 975 #undef __FUNCT__ 976 #define __FUNCT__ "MatCreateIS" 977 /*@ 978 MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each 979 process but not across processes. 980 981 Input Parameters: 982 + comm - MPI communicator that will share the matrix 983 . bs - local and global block size of the matrix 984 . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 985 - map - mapping that defines the global number for each local number 986 987 Output Parameter: 988 . A - the resulting matrix 989 990 Level: advanced 991 992 Notes: See MATIS for more details 993 m and n are NOT related to the size of the map, they are the size of the part of the vector owned 994 by that process. m + nghosts (or n + nghosts) is the length of map since map maps all local points 995 plus the ghost points to global indices. 996 997 .seealso: MATIS, MatSetLocalToGlobalMapping() 998 @*/ 999 PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A) 1000 { 1001 PetscErrorCode ierr; 1002 1003 PetscFunctionBegin; 1004 ierr = MatCreate(comm,A);CHKERRQ(ierr); 1005 ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 1006 ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 1007 ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 1008 ierr = MatSetUp(*A);CHKERRQ(ierr); 1009 ierr = MatSetLocalToGlobalMapping(*A,map,map);CHKERRQ(ierr); 1010 PetscFunctionReturn(0); 1011 } 1012 1013 /*MC 1014 MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners, see PCBDDC. 1015 This stores the matrices in globally unassembled form. Each processor 1016 assembles only its local Neumann problem and the parallel matrix vector 1017 product is handled "implicitly". 1018 1019 Operations Provided: 1020 + MatMult() 1021 . MatMultAdd() 1022 . MatMultTranspose() 1023 . MatMultTransposeAdd() 1024 . MatZeroEntries() 1025 . MatSetOption() 1026 . MatZeroRows() 1027 . MatZeroRowsLocal() 1028 . MatSetValues() 1029 . MatSetValuesLocal() 1030 . MatScale() 1031 . MatGetDiagonal() 1032 - MatSetLocalToGlobalMapping() 1033 1034 Options Database Keys: 1035 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 1036 1037 Notes: Options prefix for the inner matrix are given by -is_mat_xxx 1038 1039 You must call MatSetLocalToGlobalMapping() before using this matrix type. 1040 1041 You can do matrix preallocation on the local matrix after you obtain it with 1042 MatISGetLocalMat() 1043 1044 Level: advanced 1045 1046 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), PCBDDC 1047 1048 M*/ 1049 1050 #undef __FUNCT__ 1051 #define __FUNCT__ "MatCreate_IS" 1052 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 1053 { 1054 PetscErrorCode ierr; 1055 Mat_IS *b; 1056 1057 PetscFunctionBegin; 1058 ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 1059 A->data = (void*)b; 1060 ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 1061 1062 A->ops->mult = MatMult_IS; 1063 A->ops->multadd = MatMultAdd_IS; 1064 A->ops->multtranspose = MatMultTranspose_IS; 1065 A->ops->multtransposeadd = MatMultTransposeAdd_IS; 1066 A->ops->destroy = MatDestroy_IS; 1067 A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 1068 A->ops->setvalues = MatSetValues_IS; 1069 A->ops->setvalueslocal = MatSetValuesLocal_IS; 1070 A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 1071 A->ops->zerorows = MatZeroRows_IS; 1072 A->ops->zerorowslocal = MatZeroRowsLocal_IS; 1073 A->ops->assemblybegin = MatAssemblyBegin_IS; 1074 A->ops->assemblyend = MatAssemblyEnd_IS; 1075 A->ops->view = MatView_IS; 1076 A->ops->zeroentries = MatZeroEntries_IS; 1077 A->ops->scale = MatScale_IS; 1078 A->ops->getdiagonal = MatGetDiagonal_IS; 1079 A->ops->setoption = MatSetOption_IS; 1080 A->ops->ishermitian = MatIsHermitian_IS; 1081 A->ops->issymmetric = MatIsSymmetric_IS; 1082 A->ops->duplicate = MatDuplicate_IS; 1083 1084 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1085 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1086 1087 /* zeros pointer */ 1088 b->A = 0; 1089 b->ctx = 0; 1090 b->x = 0; 1091 b->y = 0; 1092 b->mapping = 0; 1093 b->sf = 0; 1094 b->sf_rootdata = 0; 1095 b->sf_leafdata = 0; 1096 1097 /* special MATIS functions */ 1098 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 1099 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 1100 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr); 1101 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 1102 ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 1103 PetscFunctionReturn(0); 1104 } 1105