MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
geometryroot.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "geometryroot.h"
8#include <climits>
9#include <iostream>
11#include "IO/context.h"
12#include "MEMORY/alloc.h"
13#include "UTIL/functions.h"
14#include "enums.h"
15#include "geometry2d.h"
16#include "geometry3d.h"
17#include "geometryadt.h"
18#include "geometryanalytic.h"
19#include "property.h"
20
21using namespace std;
22
23
24// implementations of various SolverXXXSurface
25
26template <MInt nDim>
27SolverSTLSurface<nDim>::SolverSTLSurface(const MPI_Comm comm, const MInt solver) {
28 m_stlGeometry = new typename GeometryXD<nDim>::type(solver, comm);
29}
30
31template <MInt nDim>
33 return m_stlGeometry->geometryContext().getNoSegments();
34}
35
36template <MInt nDim>
38 m_stlGeometry->getBoundingBox(bbox);
39}
40
41template <MInt nDim>
43 MBool* const cutInfo) {
44 std::vector<MInt> nodeList;
45 MFloat targetRegion[2 * nDim];
46 for(MInt dim = 0; dim < nDim; dim++) {
47 targetRegion[dim] = coords[dim] - cellHalfLength;
48 targetRegion[dim + nDim] = coords[dim] + cellHalfLength;
49 }
50
51 // reset cutInfo
52 for(MInt seg = 0; seg < noSegments(); seg++) {
53 cutInfo[seg] = false;
54 }
55
56 // call geometry
57 m_stlGeometry->getIntersectionElements(targetRegion, nodeList, cellHalfLength, coords);
58 const MInt noNodes = nodeList.size();
59
60 // translate from nodes to segments/elements/partialsurfaces (no unique nomenclature)
61 for(MInt n = 0; n < noNodes; n++) {
62 cutInfo[m_stlGeometry->elements[nodeList[n]].m_segmentId] = true;
63 }
64 return (MBool)noNodes;
65}
66
67template <MInt nDim>
69 std::vector<MInt> nodeList;
70 MFloat tmp_line[2 * nDim];
71
72 for(MInt dim = 0; dim < nDim; dim++) {
73 tmp_line[dim] = line[dim];
74 tmp_line[dim + nDim] = line[dim + nDim];
75 }
76
77 // call geometry
78 m_stlGeometry->getLineIntersectionElements(tmp_line, nodeList);
79
80 return nodeList.size();
81}
82
83// analytic box
84
85template <MInt nDim>
87 for(MInt i = 0; i < nDim; i++) {
88 if(bbox[i + nDim] < bbox[i]) mTerm(1, AT_, "invalid bounding box");
89 m_bbox[i] = bbox[i];
90 m_bbox[i + nDim] = bbox[i + nDim];
91 }
92}
93
94template <MInt nDim>
96 return 1;
97}
98
99template <MInt nDim>
101 for(MInt dim = 0; dim < nDim; dim++) {
102 bbox[dim] = m_bbox[dim];
103 bbox[dim + nDim] = m_bbox[dim + nDim];
104 }
105}
106
107template <MInt nDim>
109 const MFloat cellHalfLength,
110 MBool* const cutInfo) {
111 MFloat cell_bbox[2 * nDim];
112 for(MInt dim = 0; dim < nDim; dim++) {
113 cell_bbox[dim] = cell_coords[dim] - cellHalfLength;
114 cell_bbox[dim + nDim] = cell_coords[dim] + cellHalfLength;
115 }
116
117 if(maia::geom::doBoxesOverlap<MFloat, nDim>(cell_bbox, m_bbox)
118 && !maia::geom::isBoxInsideBox<MFloat, nDim>(cell_bbox, m_bbox)) {
119 cutInfo[0] = true;
120 } else {
121 cutInfo[0] = false;
122 }
123 return cutInfo[0];
124}
125
126template <MInt nDim>
128 // check both ends of the line
129 const MBool p1_inside = maia::geom::isPointInsideBox<MFloat, nDim>(line, m_bbox);
130 const MBool p2_inside = maia::geom::isPointInsideBox<MFloat, nDim>(line + nDim, m_bbox);
131
132 if(p1_inside && p2_inside) return 0;
133
134 if(p1_inside != p2_inside) return 1;
135
136 // in case both end are outside we need to take a look
137 if(maia::geom::doesLinePenetrateBox<nDim>(line, m_bbox))
138 return 2;
139 else
140 return 0;
141}
142
143// analytic sphere
144
145template <MInt nDim>
147 for(MInt i = 0; i < nDim; i++) {
148 m_center[i] = c[i];
149 }
150 m_radius = R;
151}
152
153template <MInt nDim>
155 return 1;
156}
157
158template <MInt nDim>
160 for(MInt dim = 0; dim < nDim; dim++) {
161 bbox[dim] = m_center[dim] - m_radius;
162 bbox[dim + nDim] = m_center[dim] + m_radius;
163 }
164}
165
166template <MInt nDim>
168 const MFloat cellHalfLength,
169 MBool* const cutInfo) {
170 MFloat cell_bbox[2 * nDim];
171 for(MInt dim = 0; dim < nDim; dim++) {
172 cell_bbox[dim] = cell_coords[dim] - cellHalfLength;
173 cell_bbox[dim + nDim] = cell_coords[dim] + cellHalfLength;
174 }
175
176 if(maia::geom::doBoxAndSphereOverlap<nDim>(cell_bbox, m_center, m_radius)
177 && !maia::geom::isBoxInsideSphere<nDim>(cell_bbox, m_center, m_radius)) {
178 cutInfo[0] = true;
179 } else {
180 cutInfo[0] = false;
181 }
182 return cutInfo[0];
183}
184
185template <MInt nDim>
187 if(!maia::geom::doesLinePenetrateSphere<nDim>(line, m_center, m_radius)) return 0;
188
189 // check start of line
190 const MBool p1_inside = maia::geom::isPointInsideSphere<nDim>(line, m_center, m_radius);
191
192 if(p1_inside) return 1;
193
194 // check end of line
195 const MBool p2_inside = maia::geom::isPointInsideSphere<nDim>(line + nDim, m_center, m_radius);
196
197 if(p2_inside)
198 return 1;
199 else
200 return 2;
201}
202
203// GeometryRoot functions
204
205GeometryRoot::GeometryRoot(const MInt noSolvers, const MInt nDim_, const MPI_Comm comm)
206 : GeometryBase(comm), m_nDim(nDim_) {
207 if(nDim_ == 2)
208 initGeometry<2>(noSolvers);
209 else
210 initGeometry<3>(noSolvers);
211}
212
213template <MInt nDim>
215 // how are the surfaces distributed among the nodes
216 // right now, every node has one surface
218 mAlloc(m_distribution.noSurfacesPerNode, m_distribution.noNodes, AT_, 1, "noSurfacesPerSolver");
220 "noSurfacesPerNode");
222 for(MInt node = 0; node < m_distribution.noNodes; node++) {
223 for(MInt srfc = 0; srfc < m_distribution.noSurfacesPerNode[node]; srfc++) {
224 m_distribution.nodeSurfaceIds[node][srfc] = node;
226 }
227 }
228
229 // what kind of geometry/surface to expect
230 mAlloc(m_solverSurfaceType, m_noSolverSurfaces, AT_, 0, "solverSurfaceType");
231 for(MInt node = 0; node < m_distribution.noNodes; node++) {
232 for(MInt srfc = 0; srfc < m_distribution.noSurfacesPerNode[node]; srfc++) {
233 const MInt srfcId = m_distribution.nodeSurfaceIds[node][srfc];
234 MString surfaceType = "STL";
235 surfaceType = Context::getSolverProperty<MString>("solverSurfaceType", node, AT_, &surfaceType, srfc);
236 m_solverSurfaceType[srfcId] = string2enum(surfaceType);
237 }
238 }
239
240 // init
242 for(MInt i = 0; i < m_noSolverSurfaces; i++) {
243 switch(m_solverSurfaceType[i]) {
244 case STL: {
246 break;
247 }
248 case ANALYTIC_BOX: {
249 // here we hardcode the box, just a usefull example
250 MFloat bbox[2 * nDim];
251 for(MInt dir = 0; dir < 2 * nDim; dir++) {
252 bbox[dir] = Context::getSolverProperty<MFloat>("analyticSolverBoundingBox", i, AT_, dir);
253 }
255 break;
256 }
257 case ANALYTIC_SPHERE: {
258 // here we hardcode the sphere, just a usefull example
259 MFloat center[nDim];
260 for(MInt dir = 0; dir < nDim; dir++) {
261 center[dir] = Context::getSolverProperty<MFloat>("analyticSolverBoundingSphere", i, AT_, dir);
262 }
263 const MFloat radius = Context::getSolverProperty<MFloat>("analyticSolverBoundingSphere", i, AT_, nDim);
264 m_solverSurface[i] = new SolverAnalyticSphereSurface<nDim>(center, radius);
265 break;
266 }
267 default: {
268 mTerm(1, AT_, "unknown surface type");
269 }
270 }
271 }
272}
273
275 return m_solverSurface[node]->noSegments(); // temporary since there wil be several surfaces per node
276}
277
279 // init temporary bounding box
280 MFloat tmpBB[6];
281 // init bounding box
282 for(MInt dim = 0; dim < m_nDim; dim++) {
283 bBox[dim] = numeric_limits<MFloat>::max();
284 bBox[dim + m_nDim] = numeric_limits<MFloat>::lowest();
285 }
286 // check all surfaces for their extend
287 for(MInt i = 0; i < m_noSolverSurfaces; i++) {
288 // init temporary bounding box
289 for(MInt dim = 0; dim < m_nDim; dim++) {
290 tmpBB[dim] = numeric_limits<MFloat>::max();
291 tmpBB[dim + m_nDim] = numeric_limits<MFloat>::lowest();
292 }
293 // get bounding box of surface
294 m_solverSurface[i]->boundingBox(tmpBB);
295 // get extrem values
296 for(MInt dim = 0; dim < m_nDim; dim++) {
297 bBox[dim] = mMin(bBox[dim], tmpBB[dim]);
298 bBox[dim + m_nDim] = mMax(bBox[dim + m_nDim], tmpBB[dim + m_nDim]);
299 }
300 }
301}
302
303void GeometryRoot::boundingBoxOfNode(MFloat* const bBox, const MInt node) {
304 // init temporary bounding box
305 MFloat tmpBB[6];
306 // init bounding box
307 for(MInt dim = 0; dim < m_nDim; dim++) {
308 bBox[dim] = numeric_limits<MFloat>::max();
309 bBox[dim + m_nDim] = numeric_limits<MFloat>::lowest();
310 }
311 // check all surfaces for their extend
312 for(MInt i = 0; i < m_distribution.noSurfacesPerNode[node]; i++) {
313 const MInt srfcId = m_distribution.nodeSurfaceIds[node][i];
314 // init temporary bounding box
315 for(MInt dim = 0; dim < m_nDim; dim++) {
316 tmpBB[dim] = numeric_limits<MFloat>::max();
317 tmpBB[dim + m_nDim] = numeric_limits<MFloat>::lowest();
318 }
319 // get bounding box of surface
320 m_solverSurface[srfcId]->boundingBox(tmpBB);
321 // get extrem values
322 for(MInt dim = 0; dim < m_nDim; dim++) {
323 bBox[dim] = mMin(bBox[dim], tmpBB[dim]);
324 bBox[dim + m_nDim] = mMax(bBox[dim + m_nDim], tmpBB[dim + m_nDim]);
325 }
326 }
327}
328
330 for(MInt node = 0; node < m_distribution.noNodes; node++) {
331 if(isPointInsideNode(point, node)) {
332 return true;
333 }
334 }
335 return false;
336}
337
338MBool GeometryRoot::isPointInsideNode(const MFloat* const point, const MInt node) {
339 MFloat bbox[2 * MAX_SPACE_DIMENSIONS];
340 MFloat line[2 * MAX_SPACE_DIMENSIONS];
341 MFloat bbExtend[MAX_SPACE_DIMENSIONS];
342
343 boundingBoxOfNode(bbox, node);
344
345 for(MInt dim = 0; dim < m_nDim; dim++) {
346 line[dim] = point[dim];
347 bbExtend[dim] = bbox[dim + m_nDim] - bbox[dim];
348 }
349
350 MBool retVal = true;
351 for(MInt rayDim = 0; rayDim < m_nDim; rayDim++) { // why in all dimensions?
352 for(MInt dim = 0; dim < m_nDim; dim++) {
353 line[dim + m_nDim] = point[dim];
354 }
355 line[rayDim + m_nDim] += 2 * bbExtend[rayDim];
356 MInt noIntersec = 0;
357 for(MInt i = 0; i < m_distribution.noSurfacesPerNode[node]; i++) {
358 MInt srfcId = m_distribution.nodeSurfaceIds[node][i];
359 noIntersec += m_solverSurface[srfcId]->countLineIntersectingElements(line);
360 }
361 retVal = retVal && ((noIntersec % 2) == 1);
362 if(!retVal) return false;
363 }
364 return true;
365}
366
367MBool GeometryRoot::getCellIntersectingSurfaces(const MFloat* const coords, const MFloat cellHalfLength,
368 MBool* const* const cutInfo) {
369 MBool retVal = false;
370 for(MInt node = 0; node < m_distribution.noNodes; node++) {
371 const MBool newCut = getCellIntersectingSurfacesOfNode(coords, cellHalfLength, cutInfo[node], node);
372 retVal = retVal || newCut;
373 }
374
375 return retVal;
376}
377
378MBool GeometryRoot::getCellIntersectingSurfacesOfNode(const MFloat* const coords, const MFloat cellHalfLength,
379 MBool* const cutInfo, const MInt node) {
380 MBool retVal = false;
381 for(MInt i = 0; i < m_distribution.noSurfacesPerNode[node]; i++) {
382 const MInt srfcId = m_distribution.nodeSurfaceIds[node][i];
383 const MInt cutOffset = 0; // needs to be set for the m_solverSurface to know where to set intersections
384 // but this depends on the concept: How many elements, i.e., different STL surfaces,
385 // can an adt contain?
386 retVal =
387 retVal || m_solverSurface[srfcId]->getCellIntersectingElements(coords, cellHalfLength, cutInfo + cutOffset);
388 }
389
390 return retVal;
391}
392
393template <MInt nDim>
394void GeometryRoot::setGeometryPointerToNode(Geometry<nDim>*& geometryPointer, const MInt node) {
395 m_solverSurface[node]->setGeometryPointer(geometryPointer);
396}
397
398// geometry node
399
400GeometryNode::GeometryNode(GeometryBase* geometryManager, MInt node, MPI_Comm comm) {
401 cout << "SolverGeometry constructor" << endl;
402 m_geometry = geometryManager;
403 m_node = node;
404 m_mpiComm = comm;
405}
406
407// Explicit instantiations for 2D and 3D
408template class SolverSTLSurface<2>;
409template class SolverSTLSurface<3>;
410template class SolverAnalyticBoxSurface<2>;
411template class SolverAnalyticBoxSurface<3>;
412template void GeometryRoot::initGeometry<2>(MInt noSolvers);
413template void GeometryRoot::initGeometry<3>(MInt noSolvers);
414template void GeometryRoot::setGeometryPointerToNode<2>(Geometry<2>*& geometryPointer, MInt noSolvers);
415template void GeometryRoot::setGeometryPointerToNode<3>(Geometry<3>*& geometryPointer, MInt noSolvers);
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
GeometryDistribution m_distribution
Definition: geometryroot.h:119
MPI_Comm m_mpiComm
Definition: geometryroot.h:122
GeometryNode(GeometryBase *geometryRoot, MInt node, MPI_Comm comm)
GeometryBase * m_geometry
Definition: geometryroot.h:164
SolverSurface ** m_solverSurface
Definition: geometryroot.h:155
MBool getCellIntersectingSurfaces(const MFloat *const coords, const MFloat cellHalfLength, MBool *const *const cutInfo)
MBool isPointInside(const MFloat *const point)
MInt m_noSolverSurfaces
Definition: geometryroot.h:153
void initGeometry(const MInt noSolvers)
void boundingBox(MFloat *const bBox)
MInt noSegmentsOfNode(const MInt node)
void setGeometryPointerToNode(Geometry< nDim > *&geometryPointer, const MInt node)
MBool getCellIntersectingSurfacesOfNode(const MFloat *const coords, const MFloat cellHalfLength, MBool *const cutInfo, const MInt node)
MBool isPointInsideNode(const MFloat *const point, const MInt node)
void boundingBoxOfNode(MFloat *const bBox, const MInt node)
MInt * m_solverSurfaceType
Definition: geometryroot.h:154
SolverAnalyticBoxSurface(const MFloat *const bbox)
MInt countLineIntersectingElements(const MFloat *const line)
void boundingBox(MFloat *const bbox)
MBool getCellIntersectingElements(const MFloat *const cell_coords, const MFloat cellHalfLength, MBool *const cutInfo)
SolverAnalyticSphereSurface(const MFloat *const c, const MFloat R)
MInt countLineIntersectingElements(const MFloat *const line)
MBool getCellIntersectingElements(const MFloat *const cell_coords, const MFloat cellHalfLength, MBool *const cutInfo)
void boundingBox(MFloat *const bbox)
MInt countLineIntersectingElements(const MFloat *const line)
MBool getCellIntersectingElements(const MFloat *const coords, const MFloat cellHalfLength, MBool *const cutInfo)
void boundingBox(MFloat *const bbox)
SolverSTLSurface(const MPI_Comm comm, const MInt solver)
virtual void boundingBox(MFloat *const)
Definition: geometryroot.h:30
virtual MInt countLineIntersectingElements(const MFloat *const)
Definition: geometryroot.h:26
virtual MInt noSegments()
Definition: geometryroot.h:31
virtual MBool getCellIntersectingElements(const MFloat *const, const MFloat, MBool *const)
Definition: geometryroot.h:21
virtual void setGeometryPointer(Geometry< 2 > *&)
Definition: geometryroot.h:37
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ STL
Definition: enums.h:365
@ ANALYTIC_BOX
Definition: enums.h:365
@ ANALYTIC_SPHERE
Definition: enums.h:365
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr T mMin(const T &x, const T &y)
Definition: functions.h:90
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
MInt noSolvers
Definition: maiatypes.h:73
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58