DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
Mesh_WallDist.cpp
Go to the documentation of this file.
1#include "Mesh.hpp"
2#include "Geom/Quadrature.hpp"
3
4#define CGAL_DISABLE_ROUNDING_MATH_CHECK // for valgrind
5#include <CGAL/Simple_cartesian.h>
6#include <CGAL/AABB_tree.h>
7#include <CGAL/AABB_traits_3.h>
8#include <CGAL/AABB_triangle_primitive_3.h>
9#undef CGAL_DISABLE_ROUNDING_MATH_CHECK
10namespace DNDS::Geom
11{
13 {
14 /* ************************** */
15 // Here implements direct search method
18 TrianglesLocal = make_ssp<decltype(TrianglesLocal)::element_type>(ObjName{"BuildNodeWallDist::TrianglesLocal"}, getMPI());
19 TrianglesFull = make_ssp<decltype(TrianglesFull)::element_type>(ObjName{"BuildNodeWallDist::TrianglesFull"}, getMPI());
20 std::vector<Eigen::Matrix<real, 3, 3>> Triangles;
21
22 nodeWallDist.InitPair("BuildNodeWallDist::nodeWallDist", mpi);
23 nodeWallDist.father->Resize(NumNode());
24 for (index iNode = 0; iNode < NumNode(); iNode++)
25 nodeWallDist[iNode] = tPoint{std::pow(veryLargeReal, 1. / 4.), 0, 0};
26
27 for (index iBnd = 0; iBnd < NumBnd(); iBnd++)
28 {
29 // skip if not wall
31 continue;
32
34 auto elem = GetFaceElement(iFace);
35 auto quad = Geom::Elem::Quadrature{elem, options.subdivide_quad};
36
37 // set all wall dist on wall nodes to be exactly 0.0
38 for (auto iNode : bnd2node[iBnd])
39 if (iNode < NumNode()) // && iNode >= 0; guaranteed for we assume all NumBnd() bnd faces have valid local position
40 {
41 DNDS_assert(iNode >= 0);
42 nodeWallDist[iNode].setConstant(0.0);
43 }
44
45 if (options.method == 0 || options.method == 20)
46 {
47 if (elem.type == Geom::Elem::ElemType::Line2 || elem.type == Geom::Elem::ElemType::Line3) //!
48 {
51 Eigen::Matrix<real, 3, 3> tri;
53 tri(EigenAll, 0) = coords(EigenAll, 0);
54 tri(EigenAll, 1) = coords(EigenAll, 1);
55 tri(EigenAll, 2) = coords(EigenAll, 1) + Geom::tPoint{0., 0., 1.0};
56 Triangles.push_back(tri);
57 }
58 else if (elem.type == Geom::Elem::ElemType::Tri3 || elem.type == Geom::Elem::ElemType::Tri6) //! TODO
59 {
62 Eigen::Matrix<real, 3, 3> tri;
63 tri(EigenAll, 0) = coords(EigenAll, 0);
64 tri(EigenAll, 1) = coords(EigenAll, 1);
65 tri(EigenAll, 2) = coords(EigenAll, 2);
66 Triangles.push_back(tri);
67 }
68 else if (elem.type == Geom::Elem::ElemType::Quad4 || elem.type == Geom::Elem::ElemType::Quad9)
69 {
72 Eigen::Matrix<real, 3, 3> tri;
73 tri(EigenAll, 0) = coords(EigenAll, 0);
74 tri(EigenAll, 1) = coords(EigenAll, 1);
75 tri(EigenAll, 2) = coords(EigenAll, 2);
76 Triangles.push_back(tri);
77 tri(EigenAll, 0) = coords(EigenAll, 0);
78 tri(EigenAll, 1) = coords(EigenAll, 2);
79 tri(EigenAll, 2) = coords(EigenAll, 3);
80 Triangles.push_back(tri);
81 }
82 else
83 {
84 DNDS_assert_info(false, "This elem not implemented yet for BuildNodeWallDist()");
85 }
86 }
87 else if (options.method == 1)
88 {
91 std::vector<tPoint> faceQuadraturePPhysics;
92 faceQuadraturePPhysics.reserve(quad.GetNumPoints());
93 real v{0};
94 quad.Integration(
95 v,
96 [&](auto &vInc, int iG, const tPoint &pParam, const Elem::tD01Nj &DiNj)
97 {
99 faceQuadraturePPhysics.emplace_back(pPhy);
100 });
101
103 for (auto &qPatch : qPatches)
104 {
105 Eigen::Matrix<real, 3, 3> tri;
106
107 for (int iV = 0; iV < 3; iV++)
108 if (qPatch[iV] > 0)
109 tri(EigenAll, iV) = coords(EigenAll, qPatch[iV] - 1);
110 else if (qPatch[iV] < 0)
111 tri(EigenAll, iV) = faceQuadraturePPhysics.at(-qPatch[iV] - 1);
112 else
113 tri(EigenAll, iV) = coords(EigenAll, 1) + Geom::tPoint{0., 0., 1.0};
114 Triangles.push_back(tri);
115 }
116 }
117 }
118 TrianglesLocal->Resize(Triangles.size(), 3, 3);
119 for (index i = 0; i < TrianglesLocal->Size(); i++)
120 (*TrianglesLocal)[i] = Triangles[i];
121 Triangles.clear();
124 TrianglesTransformer.createFatherGlobalMapping();
125
126 std::vector<index> pullingSet;
127 pullingSet.resize(TrianglesTransformer.pLGlobalMapping->globalSize());
128 for (index i = 0; i < pullingSet.size(); i++)
129 pullingSet[i] = i;
130 TrianglesTransformer.createGhostMapping(pullingSet);
131 TrianglesTransformer.createMPITypes();
132 TrianglesTransformer.pullOnce();
133 if (options.verbose >= 1)
134 if (coords.father->getMPI().rank == 0)
135 log() << fmt::format("=== UnstructuredMesh::BuildNodeWallDist() with minWallDist = {:.4e}, ", options.minWallDist)
136 << " To search in " << TrianglesFull->Size() << std::endl;
137
138 auto executeSearch = [&]()
139 {
140 if (options.verbose >= 3)
141 log() << fmt::format("Start search rank [{}]", getMPI().rank) << std::endl;
142 using K = CGAL::Simple_cartesian<double>;
143 // using FT = K::FT;
144 // typedef K::Ray_3 Ray;
145 // typedef K::Line_3 Line;
146 using Point = K::Point_3;
147 using Triangle = K::Triangle_3;
148 using Iterator = std::vector<Triangle>::iterator;
149 using Primitive = CGAL::AABB_triangle_primitive_3<K, Iterator>;
150 using AABB_triangle_traits = CGAL::AABB_traits_3<K, Primitive>;
151 using Tree = CGAL::AABB_tree<AABB_triangle_traits>;
152
153 std::vector<Triangle> triangles;
154 triangles.reserve(TrianglesFull->Size());
155
156 for (index i = 0; i < TrianglesFull->Size(); i++)
157 {
158 Point p0((*TrianglesFull)[i](0, 0), (*TrianglesFull)[i](1, 0), (*TrianglesFull)[i](2, 0));
159 Point p1((*TrianglesFull)[i](0, 1), (*TrianglesFull)[i](1, 1), (*TrianglesFull)[i](2, 1));
160 Point p2((*TrianglesFull)[i](0, 2), (*TrianglesFull)[i](1, 2), (*TrianglesFull)[i](2, 2));
161 triangles.emplace_back(p0, p1, p2);
162 }
163 TrianglesLocal->Resize(0, 3, 3);
164 TrianglesFull->Resize(0, 3, 3);
165 double minDist = veryLargeReal;
166
167 if (!triangles.empty())
168 {
169 // std::cout << "tree building" << std::endl;
170 Tree tree(triangles.begin(), triangles.end());
171 // std::cout << "tree built" << std::endl;
172 // search
173 for (index iNode = 0; iNode < NumNode(); iNode++)
174 {
175 // skip already on-wall data
176 if (nodeWallDist[iNode].squaredNorm() == 0.0)
177 continue;
178 // std::cout << "iCell " << iCell << std::endl;
179 // std::cout << "iG " << ig << std::endl;
180 auto p = coords[iNode];
181 Point pQ(p[0], p[1], p[2]);
182 // std::cout << "pQ " << pQ << std::endl;
183 // Point closest_point = tree.closest_point(pQ);
184 // FT sqd = tree.squared_distance(pQ);
185 auto closest_point = tree.closest_point_and_primitive(pQ);
186 // std::cout << "sqd" << sqd << std::endl;
187 auto cp = tPoint{closest_point.first.x(), closest_point.first.y(), closest_point.first.z()};
188
189 real dist = (p - cp).norm();
190 minDist = std::min(dist, minDist);
191 dist = std::max(options.minWallDist, dist);
192
193 nodeWallDist[iNode] = dist * (p - cp).stableNormalized();
194 }
195 }
196 else
197 {
198 for (index iNode = 0; iNode < NumNode(); iNode++)
199 {
200 nodeWallDist[iNode] = tPoint{std::pow(veryLargeReal, 1. / 4.), 0, 0};
201 }
202 }
203 if (options.verbose >= 2)
204 log() << fmt::format("[{}] MinDist: ", getMPI().rank) << minDist << std::endl;
205 };
206 if (options.wallDistExecution == 1)
207 MPISerialDo(getMPI(), [&]()
208 { executeSearch(); });
209 else if (options.wallDistExecution > 1)
210 for (int i = 0; i < options.wallDistExecution; i++)
211 {
212 if (getMPI().rank % options.wallDistExecution == i)
214 MPI::Barrier(getMPI().comm);
215 }
216 else
218
220 nodeWallDist.trans.BorrowGGIndexing(coords.trans);
221 nodeWallDist.trans.createMPITypes();
222 nodeWallDist.trans.pullOnce();
223 }
224}
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
Ghost-communication engine for a father / son ParArray pair.
Eigen::Matrix< t_real, 4, Eigen::Dynamic > tD01Nj
Definition Elements.hpp:183
tPoint PPhysicsCoordD01Nj(const tCoordsIn &cs, Eigen::Ref< const tD01Nj > DiNj)
Definition Elements.hpp:497
auto GetQuadPatches(Quadrature &q)
int32_t t_index
Definition Geometric.hpp:6
Eigen::Vector3d tPoint
Definition Geometric.hpp:9
Eigen::Matrix< real, 3, Eigen::Dynamic > tSmallCoords
Definition Geometric.hpp:50
MPI_int Barrier(MPI_Comm comm)
Wrapper over MPI_Barrier.
Definition MPI.cpp:248
void MPISerialDo(const MPIInfo &mpi, F f)
Execute f on each rank serially, in rank order.
Definition MPI.hpp:698
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105
std::ostream & log()
Return the current DNDSR log stream (either std::cout or the installed file).
Definition Defines.cpp:49
DNDS_CONSTANT const real veryLargeReal
Catch-all upper bound ("practically infinity") for physical scalars.
Definition Defines.hpp:190
void TransAttach()
Bind the transformer to the current father / son pointers.
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
void InitPair(const std::string &name, Args &&...args)
Allocate both father and son arrays, forwarding all args to TArray constructor.
TTrans trans
Ghost-communication engine bound to father and son.
tCoordPair nodeWallDist
wall dist:
Definition Mesh.hpp:174
UnstructuredMeshDeviceView< B > t_deviceView
Definition Mesh.hpp:777
tCoordPair coords
reader
Definition Mesh.hpp:54
void GetCoordsOnFace(index iFace, tSmallCoords &cs)
Definition Mesh.hpp:582
std::vector< index > bnd2faceV
Definition Mesh.hpp:101
Elem::Element GetFaceElement(index iF)
Definition Mesh.hpp:481
t_index GetBndZone(index iB)
Definition Mesh.hpp:486
void BuildNodeWallDist(const std::function< bool(Geom::t_index)> &fBndIsWall, WallDistOptions options=WallDistOptions{})
int rank
This rank's 0-based index within comm (-1 until initialised).
Definition MPI.hpp:219
Tag type for naming objects created via make_ssp.
Definition Defines.hpp:249
Eigen::Matrix< real, 5, 1 > v