PetIBM 0.5.4
Toolbox and applications of the immersed-boundary method for distributed-memory architectures
singlebodypoints.cpp
Go to the documentation of this file.
1
8// STL
9#include <algorithm>
10
11// PetIBM
12#include <petibm/io.h>
14
15namespace petibm
16{
17namespace body
18{
19SingleBodyPoints::SingleBodyPoints(const MPI_Comm &comm, const PetscInt &dim,
20 const std::string &name,
21 const std::string &filePath)
22 : SingleBodyBase(comm, dim, name, filePath)
23{
25} // SingleBodyPoints
26
27PetscErrorCode SingleBodyPoints::init(const MPI_Comm &comm, const PetscInt &dim,
28 const std::string &name,
29 const std::string &filePath)
30{
31 PetscErrorCode ierr;
32
33 PetscFunctionBeginUser;
34
35 // read the body coordinates from the given file
36 ierr = readBody(filePath); CHKERRQ(ierr);
37
38 // check if the dimension of coordinates matches
39 if ((unsigned)dim != coords[0].size())
40 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_FILE_READ,
41 "The dimension of Lagrangian points are different than that "
42 "of the background mesh!\n");
43
44 // record the initial body coordinates
46
47 // create a distributed 1D DMDA with DoF equal to dim; nLclPts, bgPt, edPt,
48 // da, nLclAllProcs, and offsetsAllProcs are set up here
49 ierr = createDMDA(); CHKERRQ(ierr);
50
51 // initialize meshIdx, which only contains background mesh indices of local
52 // Lagrangian points. The indices are defined by pressure cell.
54
55 // create info string
56 ierr = createInfoString(); CHKERRQ(ierr);
57
58 PetscFunctionReturn(0);
59} // init
60
62{
63 PetscErrorCode ierr;
64 DMDALocalInfo lclInfo;
65
66 PetscFunctionBeginUser;
67
68 ierr = DMDACreate1d(comm, DM_BOUNDARY_NONE, nPts, dim, 0, nullptr, &da);
69 CHKERRQ(ierr);
70 ierr = DMSetUp(da); CHKERRQ(ierr);
71
72 ierr = DMDAGetLocalInfo(da, &lclInfo); CHKERRQ(ierr);
73
74 // copy necessary local info
75 bgPt = lclInfo.xs;
76 nLclPts = lclInfo.xm;
77 edPt = bgPt + nLclPts;
78
79 // gather local info from other processes
80 ierr = MPI_Allgather(&nLclPts, 1, MPIU_INT, nLclAllProcs.data(), 1,
81 MPIU_INT, comm); CHKERRQ(ierr);
82
83 // each point has "dim" degree of freedom, so we have to multiply that
84 for (auto &it : nLclAllProcs) it *= dim;
85
86 // calculate the offset of the unpacked DM
87 for (PetscMPIInt r = mpiSize - 1; r > 0; r--)
88 offsetsAllProcs[r] = nLclAllProcs[r - 1];
89 for (PetscMPIInt r = 1; r < mpiSize; r++)
91
92 PetscFunctionReturn(0);
93} // createDMDA
94
96{
97 PetscFunctionBeginUser;
98
99 // loop through points owned locally and find indices
100 for (PetscInt i = bgPt, c = 0; i < edPt; ++i, ++c)
101 {
102 for (PetscInt d = 0; d < dim; ++d)
103 {
104 if (mesh->min[d] >= coords[i][d] || mesh->max[d] <= coords[i][d])
105 {
106 SETERRQ3(PETSC_COMM_WORLD, PETSC_ERR_MAX_VALUE,
107 "body coordinate %g is outside domain [%g, %g] !",
108 coords[i][d], mesh->min[d], mesh->max[d]);
109 }
110
111 meshIdx[c][d] = std::upper_bound(mesh->coord[4][d],
112 mesh->coord[4][d] + mesh->n[4][d],
113 coords[i][d]) -
114 mesh->coord[4][d] - 1;
115 }
116 }
117
118 PetscFunctionReturn(0);
119} // updateMeshIdx
120
122{
123 PetscErrorCode ierr;
124 std::stringstream ss;
125
126 PetscFunctionBeginUser;
127
128 // only rank 0 prepares the header of info string
129 if (mpiRank == 0)
130 {
131 ss << std::string(80, '=') << std::endl;
132 ss << "Body " << name << ":" << std::endl;
133 ss << std::string(80, '=') << std::endl;
134 ss << "\tInput mesh file: " << filePath << std::endl << std::endl;
135 ss << "\tDimension: " << dim << std::endl << std::endl;
136 ss << "\tTotal number of Lagrangian points: " << nPts << std::endl
137 << std::endl;
138 ss << "\tBody is distributed to " << mpiSize << " processes"
139 << std::endl
140 << std::endl;
141 ss << "\tDistribution of Lagrangian points:" << std::endl << std::endl;
142 }
143
144 ss << "\t\tRank " << mpiRank << ":" << std::endl;
145 ss << "\t\t\tNumber of points: " << nLclPts << std::endl;
146 ss << "\t\t\tRange of points: [" << bgPt << ", " << edPt << ")"
147 << std::endl;
148
149 info = ss.str();
150
151 ierr = MPI_Barrier(comm); CHKERRQ(ierr);
152
153 PetscFunctionReturn(0);
154} // createInfoString
155
156PetscErrorCode SingleBodyPoints::findProc(const PetscInt &i,
157 PetscMPIInt &p) const
158{
159 PetscFunctionBeginUser;
160
161 if ((i < 0) || (i >= nPts))
162 SETERRQ2(comm, PETSC_ERR_ARG_SIZ,
163 "Index %d of Lagrangian point on the body %s is out of range.",
164 i, name.c_str());
165
166 // find the process that own THE 1ST DoF OF THE POINT i
167 p = std::upper_bound(offsetsAllProcs.begin(), offsetsAllProcs.end(),
168 i * dim) -
169 offsetsAllProcs.begin() - 1;
170
171 PetscFunctionReturn(0);
172} // findProc
173
174PetscErrorCode SingleBodyPoints::getGlobalIndex(const PetscInt &i,
175 const PetscInt &dof,
176 PetscInt &idx) const
177{
178 PetscFunctionBeginUser;
179
180 if ((i < 0) || (i >= nPts))
181 SETERRQ2(comm, PETSC_ERR_ARG_SIZ,
182 "Index %d of Lagrangian point on the body %s is out of range.",
183 i, name.c_str());
184
185 if ((dof < 0) || (dof >= dim))
186 SETERRQ2(comm, PETSC_ERR_ARG_SIZ,
187 "DoF %d is not correct. The dimension is %d.", dof, dim);
188
189 // for single body DM, the global is simple due to we use 1D DMDA.
190 idx = i * dim + dof;
191
192 PetscFunctionReturn(0);
193} // getGlobalIndex
194
195PetscErrorCode SingleBodyPoints::getGlobalIndex(const MatStencil &s,
196 PetscInt &idx) const
197{
198 PetscErrorCode ierr;
199
200 PetscFunctionBeginUser;
201
202 ierr = getGlobalIndex(s.i, s.c, idx); CHKERRQ(ierr);
203
204 PetscFunctionReturn(0);
205} // getGlobalIndex
206
207PetscErrorCode SingleBodyPoints::calculateAvgForces(const Vec &f,
208 type::RealVec1D &fAvg) const
209{
210 PetscErrorCode ierr;
211
212 PetscFunctionBeginUser;
213
214 PetscReal **fArry;
215
216 type::RealVec1D fAvgLocal(dim, 0.0);
217
218 ierr = DMDAVecGetArrayDOF(da, f, &fArry); CHKERRQ(ierr);
219
220 for (PetscInt i = bgPt; i < edPt; ++i)
221 {
222 for (PetscInt dof = 0; dof < dim; ++dof)
223 {
224 fAvgLocal[dof] -=
225 fArry[i][dof]; // fArray is the force applied to fluid
226 }
227 }
228 ierr = MPI_Barrier(comm); CHKERRQ(ierr);
229
230 ierr = MPI_Allreduce(fAvgLocal.data(), fAvg.data(), dim, MPIU_REAL, MPI_SUM,
231 comm); CHKERRQ(ierr);
232
233 ierr = DMDAVecRestoreArrayDOF(da, f, &fArry); CHKERRQ(ierr);
234
235 PetscFunctionReturn(0);
236} // calculateAvgForces
237
238PetscErrorCode SingleBodyPoints::readBody(const std::string &filepath)
239{
240 PetscErrorCode ierr;
241
242 PetscFunctionBeginUser;
243
244 // read the body coordinates from the given file;
245 // attributes `nPts` and `coords` are set up here
246 ierr = io::readLagrangianPoints(filePath, nPts, coords); CHKERRQ(ierr);
247
248 PetscFunctionReturn(0);
249} // readBody
250
251// write coordinates of the Lagrangian points into ASCII file
252PetscErrorCode SingleBodyPoints::writeBody(const std::string &filepath)
253{
254 PetscErrorCode ierr;
255
256 PetscFunctionBeginUser;
257
258 PetscViewer viewer;
259 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
260 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII); CHKERRQ(ierr);
261 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_WRITE); CHKERRQ(ierr);
262 ierr = PetscViewerFileSetName(viewer, filepath.c_str()); CHKERRQ(ierr);
263 if (dim == 3)
264 {
265 for (PetscInt k = 0; k < nPts; ++k)
266 {
267 ierr = PetscViewerASCIIPrintf(
268 viewer, "%10.8e\t%10.8e\t%10.8e\n",
269 coords[k][0], coords[k][1], coords[k][2]); CHKERRQ(ierr);
270 }
271 }
272 else if (dim == 2)
273 {
274 for (PetscInt k = 0; k < nPts; ++k)
275 {
276 ierr = PetscViewerASCIIPrintf(
277 viewer, "%10.8e\t%10.8e\n",
278 coords[k][0], coords[k][1]); CHKERRQ(ierr);
279 }
280 }
281 else
282 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_FILE_WRITE,
283 "Function only supports 2D and 3D bodies.\n");
284 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
285
286 PetscFunctionReturn(0);
287} // writeBody
288
289} // end of namespace body
290
291} // end of namespace petibm
Base (abstract) class for a single body.
Definition: singlebody.h:33
PetscInt nPts
Total number of Lagrangian points.
Definition: singlebody.h:47
std::string name
Name of the body.
Definition: singlebody.h:41
PetscInt edPt
Global index of the last local Lagrangian point.
Definition: singlebody.h:68
MPI_Comm comm
MPI communicator.
Definition: singlebody.h:180
PetscMPIInt mpiRank
Rank of the local process.
Definition: singlebody.h:186
type::RealVec2D coords0
Initial coordinates of ALL Lagrangian points.
Definition: singlebody.h:53
PetscMPIInt mpiSize
Total number of processes.
Definition: singlebody.h:183
PetscInt bgPt
Global index of the first local Lagrangian point.
Definition: singlebody.h:65
PetscInt dim
Number of dimensions.
Definition: singlebody.h:38
DM da
Parallel layout of the body (as a 1D DMDA object).
Definition: singlebody.h:71
type::IntVec1D offsetsAllProcs
Offset on each process.
Definition: singlebody.h:192
type::IntVec2D meshIdx
Index of the closest Eulerian mesh cell for each local Lagrangian point.
Definition: singlebody.h:62
type::IntVec1D nLclAllProcs
Vector with the number of local unknowns on each process.
Definition: singlebody.h:189
std::string filePath
Path of the file with the body coordinates.
Definition: singlebody.h:44
type::RealVec2D coords
Coordinates of ALL Lagrangian points.
Definition: singlebody.h:50
std::string info
String with information about the body.
Definition: singlebody.h:74
PetscInt nLclPts
Local number of Lagrangian points.
Definition: singlebody.h:56
virtual PetscErrorCode writeBody(const std::string &filepath)
virtual PetscErrorCode updateMeshIdx(const type::Mesh &mesh)
Get the index of closest Eulerian mesh cell for each local Lagrangian point.
PetscErrorCode createInfoString()
Create a string used to print information about the body.
PetscErrorCode init(const MPI_Comm &comm, const PetscInt &dim, const std::string &name, const std::string &filePath)
Initialize the body, reading coordinates from given file.
virtual PetscErrorCode getGlobalIndex(const PetscInt &i, const PetscInt &dof, PetscInt &idx) const
Get the global index of a Lagrangian point in a DMDA object given its degree of freedom.
SingleBodyPoints(const MPI_Comm &comm, const PetscInt &dim, const std::string &name, const std::string &filePath)
Constructor. Initialize a single body.
PetscErrorCode createDMDA()
Create a parallel layout (1D DMDA object) of the body.
virtual PetscErrorCode findProc(const PetscInt &i, PetscMPIInt &p) const
Get the process id owning a given Lagrangian point.
virtual PetscErrorCode readBody(const std::string &filepath)
virtual PetscErrorCode calculateAvgForces(const Vec &f, type::RealVec1D &fAvg) const
Calculate the averaged force of this body.
std::shared_ptr< mesh::MeshBase > Mesh
Type definition of Mesh.
Definition: mesh.h:348
PetscErrorCode readLagrangianPoints(const std::string &file, PetscInt &nPts, type::RealVec2D &coords)
Read the number Lagrangian points and their coordinates from a file.
Definition: io.cpp:23
std::vector< IntVec1D > IntVec2D
2D std::vector holding PetscInt.
Definition: type.h:135
std::vector< PetscInt > IntVec1D
1D std::vector holding PetscInt.
Definition: type.h:133
std::vector< PetscReal > RealVec1D
1D std::vector holding PetscReal.
Definition: type.h:140
Prototypes of I/O functions.
A toolbox for building flow solvers.
Definition: bodypack.h:52
Definition of body::SingleBodyPoints.