PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) { PetscErrorCode ierr; Mat_IS *matis = (Mat_IS*)(mat->data); PetscInt bs,m,n,M,N; Mat B,localmat; PetscFunctionBegin; ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,matis->mapping,&B);CHKERRQ(ierr); ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); *newmat = B; PetscFunctionReturn(0); }
static PetscErrorCode ComputeMatrix(DomainData dd, Mat *A) { PetscErrorCode ierr; GLLData gll; Mat local_mat =0,temp_A=0; ISLocalToGlobalMapping matis_map =0; IS dirichletIS=0; PetscFunctionBeginUser; /* Compute some stuff of Gauss-Legendre-Lobatto quadrature rule */ ierr = GLLStuffs(dd,&gll);CHKERRQ(ierr); /* Compute matrix of subdomain Neumann problem */ ierr = ComputeSubdomainMatrix(dd,gll,&local_mat);CHKERRQ(ierr); /* Compute global mapping of local dofs */ ierr = ComputeMapping(dd,&matis_map);CHKERRQ(ierr); /* Create MATIS object needed by BDDC */ ierr = MatCreateIS(dd.gcomm,1,PETSC_DECIDE,PETSC_DECIDE,dd.xm*dd.ym*dd.zm,dd.xm*dd.ym*dd.zm,matis_map,NULL,&temp_A);CHKERRQ(ierr); /* Set local subdomain matrices into MATIS object */ ierr = MatScale(local_mat,dd.scalingfactor);CHKERRQ(ierr); ierr = MatISSetLocalMat(temp_A,local_mat);CHKERRQ(ierr); /* Call assembly functions */ ierr = MatAssemblyBegin(temp_A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(temp_A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (dd.DBC_zerorows) { PetscInt dirsize; ierr = ComputeSpecialBoundaryIndices(dd,&dirichletIS,NULL);CHKERRQ(ierr); ierr = MatSetOption(local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr); ierr = MatZeroRowsLocalIS(temp_A,dirichletIS,1.0,NULL,NULL);CHKERRQ(ierr); ierr = ISGetLocalSize(dirichletIS,&dirsize);CHKERRQ(ierr); /* giving hints to local and global matrices could be useful for the BDDC */ if (!dirsize) { ierr = MatSetOption(local_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(local_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr); } else { ierr = MatSetOption(local_mat,MAT_SYMMETRIC,PETSC_FALSE);CHKERRQ(ierr); ierr = MatSetOption(local_mat,MAT_SPD,PETSC_FALSE);CHKERRQ(ierr); } ierr = ISDestroy(&dirichletIS);CHKERRQ(ierr); } else { /* safe to set the options for the global matrices (they will be communicated to the matis local matrices) */ ierr = MatSetOption(temp_A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(temp_A,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr); } #if DEBUG { Vec lvec,rvec; PetscReal norm; ierr = MatCreateVecs(temp_A,&lvec,&rvec);CHKERRQ(ierr); ierr = VecSet(lvec,1.0);CHKERRQ(ierr); ierr = MatMult(temp_A,lvec,rvec);CHKERRQ(ierr); ierr = VecNorm(rvec,NORM_INFINITY,&norm);CHKERRQ(ierr); printf("Test null space of global mat % 1.14e\n",norm); ierr = VecDestroy(&lvec);CHKERRQ(ierr); ierr = VecDestroy(&rvec);CHKERRQ(ierr); } #endif /* free allocated workspace */ ierr = PetscFree(gll.zGL);CHKERRQ(ierr); ierr = PetscFree(gll.rhoGL);CHKERRQ(ierr); ierr = PetscFree(gll.A[0]);CHKERRQ(ierr); ierr = PetscFree(gll.A);CHKERRQ(ierr); ierr = MatDestroy(&gll.elem_mat);CHKERRQ(ierr); ierr = MatDestroy(&local_mat);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingDestroy(&matis_map);CHKERRQ(ierr); /* give back the pointer to te MATIS object */ *A = temp_A; PetscFunctionReturn(0); }