66#include < psDomain.hpp>
77#include < rayParticle.hpp>
88
9- #define MAKE_GEO Hole
9+ #define MAKE_GEO Trench
1010#define DEFAULT_GRID_DELTA 0.1
1111#define DEFAULT_STICKING 0.1
12- #define DIM 3
12+ #define DIM 2
13+ #define FIXED_RAYS false
1314
14- constexpr int particleType = 0 ;
15+ constexpr int particleType = 1 ;
1516using TranslatorType = std::unordered_map<unsigned long , unsigned long >;
17+ using namespace viennaps ;
1618
1719template <class NumericType >
1820auto Trench (NumericType gridDelta = DEFAULT_GRID_DELTA ) {
19- NumericType xExtent = 10 .;
20- NumericType yExtent = 10 .;
21- NumericType width = 5 .;
22- NumericType depth = 25 .;
21+ NumericType xExtent = 20 .;
22+ NumericType yExtent = 20 .;
23+ NumericType width = 10 .;
24+ NumericType depth = 50 .;
2325
24- using namespace viennaps ;
2526 auto domain = Domain<NumericType, DIM >::New (
2627 gridDelta, xExtent, yExtent, BoundaryType::REFLECTIVE_BOUNDARY );
27- MakeTrench<NumericType, DIM >(domain, width, depth).apply (). apply () ;
28+ MakeTrench<NumericType, DIM >(domain, width, depth).apply ();
2829 return domain;
2930}
3031
@@ -35,7 +36,6 @@ auto Hole(NumericType gridDelta = DEFAULT_GRID_DELTA) {
3536 NumericType radius = 3.0 ;
3637 NumericType depth = 30 .;
3738
38- using namespace viennaps ;
3939 auto domain = Domain<NumericType, DIM >::New (
4040 gridDelta, xExtent, yExtent, BoundaryType::REFLECTIVE_BOUNDARY );
4141 MakeHole<NumericType, DIM >(domain, radius, depth).apply ();
@@ -159,4 +159,189 @@ auto getDeviceParams() {
159159 deviceParams.redepositionThreshold = params_.redepositionThreshold ;
160160
161161 return deviceParams;
162+ }
163+
164+ template <class NumericType , int D, class TracerType >
165+ void setupTriangleGeometry (
166+ SmartPointer<Domain<NumericType, D>> &domain,
167+ SmartPointer<viennals::Mesh<float >> &surfaceMesh_,
168+ SmartPointer<KDTree<NumericType, Vec3D<NumericType>>> &elementKdTree_,
169+ TracerType &rayTracer_) {
170+ CreateSurfaceMesh<NumericType, float , D>(
171+ domain->getLevelSets ().back (), surfaceMesh_, elementKdTree_, 1e-12 , 0.05 )
172+ .apply ();
173+
174+ viennaray::TriangleMesh triangleMesh;
175+
176+ if constexpr (D == 2 ) {
177+ viennaray::LineMesh lineMesh;
178+ lineMesh.gridDelta = static_cast <float >(domain->getGridDelta ());
179+ lineMesh.lines = surfaceMesh_->lines ;
180+ lineMesh.nodes = surfaceMesh_->nodes ;
181+ lineMesh.minimumExtent = surfaceMesh_->minimumExtent ;
182+ lineMesh.maximumExtent = surfaceMesh_->maximumExtent ;
183+
184+ triangleMesh = convertLinesToTriangles (lineMesh);
185+ assert (triangleMesh.triangles .size () > 0 );
186+
187+ std::vector<Vec3D<NumericType>> triangleCenters;
188+ triangleCenters.reserve (triangleMesh.triangles .size ());
189+ for (const auto &tri : triangleMesh.triangles ) {
190+ Vec3D<NumericType> center = {0 , 0 , 0 };
191+ for (int i = 0 ; i < 3 ; ++i) {
192+ center[0 ] += triangleMesh.nodes [tri[i]][0 ];
193+ center[1 ] += triangleMesh.nodes [tri[i]][1 ];
194+ center[2 ] += triangleMesh.nodes [tri[i]][2 ];
195+ }
196+ triangleCenters.push_back (center / static_cast <NumericType>(3.0 ));
197+ }
198+ assert (triangleCenters.size () > 0 );
199+ elementKdTree_->setPoints (triangleCenters);
200+ elementKdTree_->build ();
201+ } else {
202+ triangleMesh = CreateTriangleMesh (
203+ static_cast <float >(domain->getGridDelta ()), surfaceMesh_);
204+ }
205+
206+ rayTracer_.setGeometry (triangleMesh);
207+
208+ if constexpr (D == 2 ) {
209+ surfaceMesh_->nodes = std::move (triangleMesh.nodes );
210+ surfaceMesh_->triangles = std::move (triangleMesh.triangles );
211+ surfaceMesh_->getCellData ().insertReplaceVectorData (
212+ std::move (triangleMesh.normals ), " Normals" );
213+ surfaceMesh_->minimumExtent = triangleMesh.minimumExtent ;
214+ surfaceMesh_->maximumExtent = triangleMesh.maximumExtent ;
215+ }
216+ }
217+
218+ template <class NumericType , int D, class TracerType >
219+ void setupLineGeometry (
220+ SmartPointer<Domain<NumericType, D>> &domain,
221+ SmartPointer<viennals::Mesh<float >> &surfaceMesh_,
222+ SmartPointer<KDTree<NumericType, Vec3D<NumericType>>> &elementKdTree_,
223+ TracerType &rayTracer_) {
224+ CreateSurfaceMesh<NumericType, float , D>(
225+ domain->getLevelSets ().back (), surfaceMesh_, elementKdTree_, 1e-12 , 0.05 )
226+ .apply ();
227+
228+ viennaray::LineMesh lineMesh (surfaceMesh_->nodes , surfaceMesh_->lines ,
229+ static_cast <float >(domain->getGridDelta ()));
230+ // lines might have changed, so we need to update the surfaceMesh_ later
231+
232+ std::vector<Vec3D<NumericType>> elementCenters (lineMesh.lines .size ());
233+ for (int i = 0 ; i < lineMesh.lines .size (); ++i) {
234+ auto const &p0 = lineMesh.nodes [lineMesh.lines [i][0 ]];
235+ auto const &p1 = lineMesh.nodes [lineMesh.lines [i][1 ]];
236+ auto center = (p0 + p1) / 2 .f ;
237+ elementCenters[i] = Vec3D<NumericType>{static_cast <NumericType>(center[0 ]),
238+ static_cast <NumericType>(center[1 ]),
239+ static_cast <NumericType>(center[2 ])};
240+ }
241+ elementKdTree_->setPoints (elementCenters);
242+ elementKdTree_->build ();
243+
244+ rayTracer_.setGeometry (lineMesh);
245+
246+ surfaceMesh_->nodes = std::move (lineMesh.nodes );
247+ surfaceMesh_->lines = std::move (lineMesh.lines );
248+ surfaceMesh_->getCellData ().insertReplaceVectorData (
249+ std::move (lineMesh.normals ), " Normals" );
250+ surfaceMesh_->minimumExtent = lineMesh.minimumExtent ;
251+ surfaceMesh_->maximumExtent = lineMesh.maximumExtent ;
252+ }
253+
254+ template <typename NumericType, class TracerType >
255+ void postProcessLineData (
256+ viennals::PointData<NumericType> &pointData,
257+ SmartPointer<viennals::Mesh<NumericType>> diskMesh, int smoothingNeighbors,
258+ NumericType gridDelta, TracerType &rayTracer_,
259+ SmartPointer<KDTree<NumericType, Vec3D<NumericType>>> elementKdTree_,
260+ SmartPointer<viennals::Mesh<float >> surfaceMesh_) {
261+
262+ const auto numRates = rayTracer_.getNumberOfRates ();
263+ const auto numPoints = rayTracer_.getNumberOfElements ();
264+ const auto numDisks = diskMesh->nodes .size ();
265+ assert (numRates > 0 );
266+ auto particles = rayTracer_.getParticles ();
267+ auto const &elementNormals =
268+ *surfaceMesh_->getCellData ().getVectorData (" Normals" );
269+ auto const &normals = *diskMesh->getCellData ().getVectorData (" Normals" );
270+ const auto numElements = surfaceMesh_->lines .size ();
271+
272+ NumericType conversionRadius = gridDelta * (smoothingNeighbors + 1 );
273+ conversionRadius *= conversionRadius; // use squared radius
274+
275+ std::vector<std::vector<std::pair<unsigned , NumericType>>> elementsToPoint;
276+ elementsToPoint.reserve (numDisks);
277+
278+ for (int i = 0 ; i < numDisks; i++) {
279+ auto closePoints =
280+ elementKdTree_
281+ ->findNearestWithinRadius (diskMesh->nodes [i], conversionRadius)
282+ .value ();
283+
284+ std::vector<std::pair<unsigned , NumericType>> closePointsArray;
285+ std::vector<NumericType> weights (closePoints.size (), NumericType (0 ));
286+
287+ unsigned numClosePoints = 0 ;
288+ for (std::size_t n = 0 ; n < closePoints.size (); ++n) {
289+ const auto &p = closePoints[n];
290+ assert (p.first < numElements);
291+
292+ NumericType weight = 0 ;
293+ for (int k = 0 ; k < 3 ; ++k) {
294+ weight += normals[i][k] * elementNormals[p.first ][k];
295+ }
296+ weight = std::max (weight, NumericType (0 ));
297+
298+ if (weight > NumericType (1e-6 ) && !std::isnan (weight)) {
299+ weights[n] = weight;
300+ ++numClosePoints;
301+ }
302+ }
303+
304+ if (numClosePoints == 0 ) { // fallback to nearest point
305+ auto nearestPoint = elementKdTree_->findNearest (diskMesh->nodes [i]);
306+ closePointsArray.emplace_back (nearestPoint->first , NumericType (1 ));
307+ }
308+
309+ // Compute weighted average
310+ const NumericType sum =
311+ std::accumulate (weights.begin (), weights.end (), NumericType (0 ));
312+
313+ if (sum > NumericType (0 )) {
314+ for (std::size_t k = 0 ; k < closePoints.size (); ++k) {
315+ if (weights[k] > NumericType (0 )) {
316+ closePointsArray.emplace_back (closePoints[k].first , weights[k] / sum);
317+ }
318+ }
319+ } else {
320+ // Fallback if all weights were discarded
321+ auto nearestPoint = elementKdTree_->findNearest (diskMesh->nodes [i]);
322+ closePointsArray.emplace_back (nearestPoint->first , NumericType (1 ));
323+ }
324+
325+ elementsToPoint.push_back (closePointsArray);
326+ }
327+ assert (elementsToPoint.size () == numDisks);
328+
329+ for (int pIdx = 0 ; pIdx < particles.size (); pIdx++) {
330+ for (int dIdx = 0 ; dIdx < particles[pIdx].dataLabels .size (); dIdx++) {
331+ auto elementFlux = rayTracer_.getFlux (pIdx, dIdx, smoothingNeighbors);
332+ auto name = particles[pIdx].dataLabels [dIdx];
333+
334+ // convert line fluxes to disk fluxes
335+ std::vector<NumericType> diskFlux (numDisks, 0 .);
336+
337+ for (int i = 0 ; i < numDisks; i++) {
338+ for (const auto &elemPair : elementsToPoint[i]) {
339+ diskFlux[i] += static_cast <NumericType>(elementFlux[elemPair.first ]) *
340+ elemPair.second ;
341+ }
342+ }
343+
344+ pointData.insertReplaceScalarData (std::move (diskFlux), name);
345+ }
346+ }
162347}
0 commit comments