PetIBM 0.5.4
Toolbox and applications of the immersed-boundary method for distributed-memory architectures
createdivergence.cpp
Go to the documentation of this file.
1
8// STL
9#include <functional>
10
11// here goes PETSc headers
12#include <petscmat.h>
13
14// here goes headers from our PetIBM
15#include <petibm/boundary.h>
16#include <petibm/mesh.h>
17#include <petibm/type.h>
18
19// private functions
20#include "../private/private.h"
21
22namespace // anonymous namespace for internal linkage
23{
24// a private struct for matrix-free constraint mat
25struct DivergenceCtx
26{
29
30 DivergenceCtx(const petibm::type::Boundary &_bc)
31 : bc(_bc), modifier(bc->dim){};
32};
33
34// a function type for functions returning neighbor's stencil
35typedef std::function<MatStencil(const PetscInt &, const PetscInt &,
36 const PetscInt &)>
38
39// a function type for functions returning the value of a matrix entry
40typedef std::function<PetscReal(const PetscInt &, const PetscInt &,
41 const PetscInt &)>
42 Kernel;
43
44// a user-defined MatMult for constraint mat
45PetscErrorCode DCorrectionMult(Mat mat, Vec x, Vec y)
46{
47 PetscFunctionBeginUser;
48
49 PetscErrorCode ierr;
50
51 DivergenceCtx *ctx;
52
53 // get the context
54 ierr = MatShellGetContext(mat, (void *)&ctx); CHKERRQ(ierr);
55
56 // zero the output vector
57 ierr = VecSet(y, 0.0); CHKERRQ(ierr);
58
59 // set the correction values to corresponding rows
60 for (PetscInt f = 0; f < ctx->bc->dim; ++f)
61 for (auto &bd : ctx->bc->bds[f])
62 if (bd->onThisProc)
63 for (auto &pt : bd->points)
64 {
65 ierr = VecSetValue(
66 y, ctx->modifier[f][pt.first].row,
67 ctx->modifier[f][pt.first].coeff * pt.second.a1,
68 ADD_VALUES); CHKERRQ(ierr);
69 }
70
71 // assembly (not sure if this is necessary and if this causes overhead)
72 // but there is an implicit MPI barrier in assembly, which we definitely
73 // need
74 ierr = VecAssemblyBegin(y); CHKERRQ(ierr);
75 ierr = VecAssemblyEnd(y); CHKERRQ(ierr);
76
77 PetscFunctionReturn(0);
78} // DCorrectionMult
79
80// a user-defined MatDestroy for constraint mat
81PetscErrorCode DCorrectionDestroy(Mat mat)
82{
83 PetscFunctionBeginUser;
84
85 PetscErrorCode ierr;
86 DivergenceCtx *ctx;
87
88 // get the context
89 ierr = MatShellGetContext(mat, (void *)&ctx); CHKERRQ(ierr);
90
91 // deallocate the context
92 delete ctx;
93
94 PetscFunctionReturn(0);
95} // DCorrectionDestroy
96} // end of anonymous namespace
97
98namespace petibm
99{
100namespace operators
101{
102// implementation of petibm::operators::createDivergence
103PetscErrorCode createDivergence(const type::Mesh &mesh,
104 const type::Boundary &bc, Mat &D,
105 Mat &DCorrection, const PetscBool &normalize)
106{
107 PetscFunctionBeginUser;
108
109 PetscErrorCode ierr;
110
111 std::vector<GetNeighborFunc> getNeighbor(3);
112
113 std::vector<Kernel> kernel(3);
114
115 DivergenceCtx *ctx;
116
117 // initialize modifier, regardless what's inside it now
118 ctx = new DivergenceCtx(bc);
119
120 // set up getNeighbor
121 getNeighbor[0] = [](const PetscInt &i, const PetscInt &j,
122 const PetscInt &k) -> MatStencil {
123 return {k, j, i - 1};
124 };
125 getNeighbor[1] = [](const PetscInt &i, const PetscInt &j,
126 const PetscInt &k) -> MatStencil {
127 return {k, j - 1, i};
128 };
129 getNeighbor[2] = [](const PetscInt &i, const PetscInt &j,
130 const PetscInt &k) -> MatStencil {
131 return {k - 1, j, i};
132 };
133
134 // set up kernel
135 if (normalize)
136 kernel[0] = kernel[1] = kernel[2] =
137 std::bind([]() -> PetscReal { return 1.0; });
138 else
139 {
140 kernel[0] = [&mesh](const PetscInt &i, const PetscInt &j,
141 const PetscInt &k) -> PetscReal {
142 return mesh->dL[0][1][j] * mesh->dL[0][2][k];
143 };
144 kernel[1] = [&mesh](const PetscInt &i, const PetscInt &j,
145 const PetscInt &k) -> PetscReal {
146 return mesh->dL[1][0][i] * mesh->dL[1][2][k];
147 };
148 kernel[2] = [&mesh](const PetscInt &i, const PetscInt &j,
149 const PetscInt &k) -> PetscReal {
150 return mesh->dL[2][0][i] * mesh->dL[2][1][j];
151 };
152 }
153
154 // create matrix
155 ierr = MatCreate(mesh->comm, &D); CHKERRQ(ierr);
156 ierr = MatSetSizes(D, mesh->pNLocal, mesh->UNLocal, PETSC_DETERMINE,
157 PETSC_DETERMINE); CHKERRQ(ierr);
158 ierr = MatSetFromOptions(D); CHKERRQ(ierr);
159 ierr = MatSeqAIJSetPreallocation(D, mesh->dim * 2, nullptr); CHKERRQ(ierr);
160
161 // TODO: a better guess for allocation in MPIAIJ
162 ierr = MatMPIAIJSetPreallocation(D, mesh->dim * 2, nullptr, 3, nullptr);
163 CHKERRQ(ierr);
164
165 ierr = MatSetUp(D); CHKERRQ(ierr);
166 ierr = MatSetOption(D, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE);
167 CHKERRQ(ierr);
168 ierr = MatSetOption(D, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE); CHKERRQ(ierr);
169
170 // set values to matrix
171 for (PetscInt k = mesh->bg[3][2]; k < mesh->ed[3][2]; ++k)
172 for (PetscInt j = mesh->bg[3][1]; j < mesh->ed[3][1]; ++j)
173 for (PetscInt i = mesh->bg[3][0]; i < mesh->ed[3][0]; ++i)
174 {
175 PetscInt self;
176
177 // row index is based on pressure grid
178 ierr = mesh->getGlobalIndex(3, {k, j, i, 0}, self);
179 CHKERRQ(ierr);
180
181 // calculate and set values of the two surfaces in each
182 // direction
183 for (PetscInt field = 0; field < mesh->dim; ++field)
184 {
185 // the stencil of target surface
186 MatStencil target;
187
188 // index of target surface in packed Vec
189 PetscInt targetIdx;
190
191 // the absolute value of coefficient
192 PetscReal value = kernel[field](i, j, k);
193
194 // the surface toward positive direction
195 target = {k, j, i, 0};
196
197 ierr = mesh->getPackedGlobalIndex(field, target, targetIdx);
198 CHKERRQ(ierr);
199
200 ierr =
201 MatSetValue(D, self, targetIdx, value, INSERT_VALUES);
202 CHKERRQ(ierr);
203
204 // store the coefficient of ghost points for future use
205 if (targetIdx == -1)
206 ctx->modifier[field][target] = {self, value};
207
208 // the surface toward negative direction
209 target = getNeighbor[field](i, j, k);
210
211 ierr = mesh->getPackedGlobalIndex(field, target, targetIdx);
212 CHKERRQ(ierr);
213
214 // note the value for this face is just a negative version
215 ierr =
216 MatSetValue(D, self, targetIdx, -value, INSERT_VALUES);
217 CHKERRQ(ierr);
218
219 // store the coefficient of ghost points for future use
220 if (targetIdx == -1)
221 ctx->modifier[field][target] = {self, -value};
222 }
223 }
224
225 // temporarily assemble matrix
226 ierr = MatAssemblyBegin(D, MAT_FLUSH_ASSEMBLY); CHKERRQ(ierr);
227 ierr = MatAssemblyEnd(D, MAT_FLUSH_ASSEMBLY); CHKERRQ(ierr);
228
229 // modify the column of the neighbors of ghost points
230 // Only ghost points on Neumann BC will modify Divergence operator
231 for (PetscInt f = 0; f < mesh->dim; ++f)
232 for (auto &bd : bc->bds[f])
233 if (bd->onThisProc)
234 for (auto &pt : bd->points)
235 {
236 PetscInt col = pt.second.targetPackedId;
237 PetscReal value =
238 ctx->modifier[f][pt.first].coeff * pt.second.a0;
239
240 ierr = MatSetValue(D, ctx->modifier[f][pt.first].row, col,
241 value, ADD_VALUES); CHKERRQ(ierr);
242 }
243
244 // assemble matrix, an implicit MPI barrier is applied
245 ierr = MatAssemblyBegin(D, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
246 ierr = MatAssemblyEnd(D, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
247
248 // create a matrix-free constraint matrix for boundary correction
249 ierr = MatCreateShell(mesh->comm, mesh->pNLocal, mesh->UNLocal,
250 PETSC_DETERMINE, PETSC_DETERMINE, (void *)ctx,
251 &DCorrection); CHKERRQ(ierr);
252
253 ierr = MatShellSetOperation(DCorrection, MATOP_MULT,
254 (void (*)(void))DCorrectionMult);
255 CHKERRQ(ierr);
256
257 ierr = MatShellSetOperation(DCorrection, MATOP_DESTROY,
258 (void (*)(void))DCorrectionDestroy);
259 CHKERRQ(ierr);
260
261 PetscFunctionReturn(0);
262} // createDivergence
263
264} // end of namespace operators
265} // end of namespace petibm
boundary::BoundaryBase, type::Boundary, and factory function.
std::shared_ptr< boundary::BoundaryBase > Boundary
Type definition of petibm::type::Boundary.
Definition: boundary.h:175
std::shared_ptr< mesh::MeshBase > Mesh
Type definition of Mesh.
Definition: mesh.h:348
PetscErrorCode createDivergence(const type::Mesh &mesh, const type::Boundary &bc, Mat &D, Mat &DCorrection, const PetscBool &normalize=PETSC_TRUE)
Create a divergence operator, , and corresponding boundary correction, , for velocity fields.
std::vector< std::map< MatStencil, RowModifier > > MatrixModifier
A type that holds necessary info for a matrix modifier that modifies matrix coefficient based on BCs.
Definition: type.h:195
Prototype of mesh::MeshBase, type::Mesh, and factory function.
std::function< StencilVec(const PetscInt &, const PetscInt &, const PetscInt &)> GetNeighborFunc
a function type for functions returning neighbors' stencils.
std::function< type::RealVec1D(const PetscInt &, const PetscInt &, const PetscInt &)> Kernel
a function type for functions computing matrix entries' values.
A toolbox for building flow solvers.
Definition: bodypack.h:52
Definition of user-defined types for convenience.