PetscErrorCode ef_boundary_apply(ef_boundary *bnd, Mat A, DM da) { PetscErrorCode ierr; int i; PetscInt level; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); for (i = 0; i < bnd->num_bc; i++) { if (bnd->bc[i]->patch->bc_type == EF_NEUMANN) { ierr = ef_bc_apply(bnd->bc[i], A, da);CHKERRQ(ierr); } } for (i = 0; i < bnd->num_bc; i++) { if (bnd->bc[i]->patch->bc_type == EF_DIRICHLET_G || bnd->bc[i]->patch->bc_type == EF_DIRICHLET_P) { ierr = ef_bc_apply(bnd->bc[i], A, da);CHKERRQ(ierr); } } if (level) { // prepare rhs transform. for coarse levels ierr = ef_boundary_apply_rhs(bnd, da);CHKERRQ(ierr); } // temporary symmetric Dirchlet hack ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatMult(A, bnd->levels[level].g, bnd->levels[level].ag);CHKERRQ(ierr); for (i = 0; i < bnd->num_bc; i++) { ierr = ef_bc_symmetric(bnd->bc[i], A, da);CHKERRQ(ierr); } return 0; }
static PetscErrorCode update_dirichlet_sym_3d(ef_bc *bc, Mat A, DM da) { PetscErrorCode ierr; PetscInt i,j,k,cnt; PetscInt ngx, ngy, ngz; PetscScalar v[6]; MatStencil row[6], col; PetscInt level; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &ngx, &ngy, &ngz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); for (i = 0; i < 6; i++) v[i] = 0; for (k = patch->corners[level].is[2]; k <= patch->corners[level].ie[2]; k++) { for (j = patch->corners[level].is[1]; j <= patch->corners[level].ie[1]; j++) { for (i = patch->corners[level].is[0]; i <= patch->corners[level].ie[0]; i++) { col.i = i; col.j = j; col.k = k; cnt = 0; if (i-1 < patch->corners[level].is[0] && i-1 >= 0) { row[cnt].i = i-1; row[cnt].j = j; row[cnt].k = k; cnt++; } if (i+1 > patch->corners[level].ie[0] && i+1 <= ngx-1) { row[cnt].i = i+1; row[cnt].j = j; row[cnt].k = k; cnt++; } if (j-1 < patch->corners[level].is[1] && j-1 >= 0) { row[cnt].i = i; row[cnt].j = j-1; row[cnt].k = k; cnt++; } if (j+1 > patch->corners[level].ie[1] && j+1 <= ngy-1) { row[cnt].i = i; row[cnt].j = j+1; row[cnt].k = k; cnt++; } if (k-1 < patch->corners[level].is[2] && k-1 >= 0) { row[cnt].i = i; row[cnt].j = j; row[cnt].k = k-1; cnt++; } if (k+1 > patch->corners[level].ie[2] && k+1 <= ngz-1) { row[cnt].i = i; row[cnt].j = j; row[cnt].k = k+1; cnt++; } ierr = MatSetValuesStencil(A, cnt, row, 1, &col, v, INSERT_VALUES);CHKERRQ(ierr); } } } return 0; }
static PetscErrorCode apply_dirichlet_3d(ef_bc *bc, Mat A, DM da) { PetscErrorCode ierr; PetscInt i,j,k,cnt; PetscInt ngx, ngy, ngz; PetscScalar v[7]; MatStencil row, col[7]; PetscInt level; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &ngx, &ngy, &ngz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); v[0] = 1.0; for (k = patch->corners[level].is[2]; k <= patch->corners[level].ie[2]; k++) { for (j = patch->corners[level].is[1]; j <= patch->corners[level].ie[1]; j++) { for (i = patch->corners[level].is[0]; i <= patch->corners[level].ie[0]; i++) { row.i = i; row.j = j; row.k = k; col[0].i = i; col[0].j = j; col[0].k = k; cnt = 1; if (i != 0) { col[cnt].i = i-1; col[cnt].j = j; col[cnt].k = k; v[cnt] = 0; cnt++; } if (j != 0) { col[cnt].i = i; col[cnt].j = j-1; col[cnt].k = k; v[cnt] = 0; cnt++; } if (k != 0) { col[cnt].i = i; col[cnt].j = j; col[cnt].k = k-1; v[cnt] = 0; cnt++; } if (i != ngx - 1) { col[cnt].i = i+1; col[cnt].j = j; col[cnt].k = k; v[cnt] = 0; cnt++; } if (j != ngy - 1) { col[cnt].i = i; col[cnt].j = j+1; col[cnt].k = k; v[cnt] = 0; cnt++; } if (k != ngz - 1) { col[cnt].i = i; col[cnt].j = j; col[cnt].k = k+1; v[cnt] = 0; cnt++; } ierr = MatSetValuesStencil(A, 1, &row, cnt, col, v, INSERT_VALUES);CHKERRQ(ierr); } } } return 0; }
/*@ DMDAGetReducedDMDA - Gets the DMDA with the same layout but with fewer or more fields Collective on DMDA Input Parameters: + da - the distributed array - nfields - number of fields in new DMDA Output Parameter: . nda - the new DMDA Level: intermediate .keywords: distributed array, get, corners, nodes, local indices, coordinates .seealso: DMDAGetGhostCorners(), DMSetCoordinates(), DMDASetUniformCoordinates(), DMGetCoordinates(), DMDAGetGhostedCoordinates() @*/ PetscErrorCode DMDAGetReducedDMDA(DM da,PetscInt nfields,DM *nda) { PetscErrorCode ierr; DM_DA *dd = (DM_DA*)da->data; PetscInt s,m,n,p,M,N,P,dim,Mo,No,Po; const PetscInt *lx,*ly,*lz; DMBoundaryType bx,by,bz; DMDAStencilType stencil_type; PetscInt ox,oy,oz; PetscInt cl,rl; PetscFunctionBegin; dim = da->dim; M = dd->M; N = dd->N; P = dd->P; m = dd->m; n = dd->n; p = dd->p; s = dd->s; bx = dd->bx; by = dd->by; bz = dd->bz; stencil_type = dd->stencil_type; ierr = DMDAGetOwnershipRanges(da,&lx,&ly,&lz);CHKERRQ(ierr); if (dim == 1) { ierr = DMDACreate1d(PetscObjectComm((PetscObject)da),bx,M,nfields,s,dd->lx,nda);CHKERRQ(ierr); } else if (dim == 2) { ierr = DMDACreate2d(PetscObjectComm((PetscObject)da),bx,by,stencil_type,M,N,m,n,nfields,s,lx,ly,nda);CHKERRQ(ierr); } else if (dim == 3) { ierr = DMDACreate3d(PetscObjectComm((PetscObject)da),bx,by,bz,stencil_type,M,N,P,m,n,p,nfields,s,lx,ly,lz,nda);CHKERRQ(ierr); } ierr = DMSetUp(*nda);CHKERRQ(ierr); if (da->coordinates) { ierr = PetscObjectReference((PetscObject)da->coordinates);CHKERRQ(ierr); (*nda)->coordinates = da->coordinates; } /* allow for getting a reduced DA corresponding to a domain decomposition */ ierr = DMDAGetOffset(da,&ox,&oy,&oz,&Mo,&No,&Po);CHKERRQ(ierr); ierr = DMDASetOffset(*nda,ox,oy,oz,Mo,No,Po);CHKERRQ(ierr); /* allow for getting a reduced DA corresponding to a coarsened DA */ ierr = DMGetCoarsenLevel(da,&cl);CHKERRQ(ierr); ierr = DMGetRefineLevel(da,&rl);CHKERRQ(ierr); (*nda)->levelup = rl; (*nda)->leveldown = cl; PetscFunctionReturn(0); }
static PetscErrorCode apply_rhs(ef_bc *bc, DM da) { PetscErrorCode ierr; PetscInt dim; PetscInt level; ierr = DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); if (!level) { if (dim == 2) { ierr = apply_dirichlet_rhs(bc, da);CHKERRQ(ierr); } else if (dim == 3) { ierr = apply_dirichlet_rhs_3d(bc, da);CHKERRQ(ierr); } } return 0; }
static PetscErrorCode apply_dirichlet_rhs_3d(ef_bc *bc, DM da) { PetscErrorCode ierr; PetscInt i,j,k,xs,ys,zs,xe,ye,ze,ym,xm,zm; PetscInt level; PetscScalar ***gvec, ***gcomp; double ***dirichlet; ef_dmap *dmap; int stride[3]; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ys = patch->gis[1]-1; xs = patch->gis[0]-1; zs = patch->gis[2]-1; ye = patch->gie[1]; xe = patch->gie[0]; ze = patch->gie[2]; ym = patch->gie[1] - patch->gis[1] + 1; xm = patch->gie[0] - patch->gis[0] + 1; zm = patch->gie[2] - patch->gis[2] + 1; stride[0] = xm; stride[1] = ym; stride[2] = zm; dmap = ef_dmap_create_3d(xs, ys, zs, xm, ym, zm, stride); ierr = ef_dmap_get(dmap, patch->dirichlet, &dirichlet);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, bc->levels[level].g, &gvec);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, bc->levels[level].gcomp, &gcomp);CHKERRQ(ierr); for (k = zs; k < ze; k++) { for (j = ys; j < ye; j++) { for (i = xs; i < xe; i++) { gvec[k][j][i] = dirichlet[k][j][i]; gcomp[k][j][i] = 0.0; } } } ierr = ef_dmap_restore(dmap, &dirichlet);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da, bc->levels[level].g, &gvec);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da, bc->levels[level].gcomp, &gcomp);CHKERRQ(ierr); ef_dmap_destroy(dmap); free(dmap); return 0; }