Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
BasicRayMeshIntersection.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* BasicRayMeshIntersection.cc (C) 2000-2026 */
9/* */
10/* Basic service for calculating intersection between segments and mesh. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Array.h"
15#include "arcane/utils/Real3.h"
16#include "arcane/utils/StringBuilder.h"
17#include "arcane/utils/TraceAccessor.h"
18#include "arcane/utils/NotImplementedException.h"
19
20#include "arcane/core/ISubDomain.h"
21#include "arcane/core/IMesh.h"
22#include "arcane/core/IItemFamily.h"
23#include "arcane/core/Item.h"
24#include "arcane/core/BasicService.h"
25#include "arcane/core/FactoryService.h"
26#include "arcane/core/ItemPrinter.h"
27#include "arcane/core/ItemGroup.h"
28#include "arcane/core/VariableTypes.h"
29#include "arcane/core/IRayMeshIntersection.h"
30#include "arcane/core/IParallelMng.h"
31#include "arcane/core/IParticleFamily.h"
32
33#include "arcane_packages.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
56class RayTriangle3DIntersection
57: public TraceAccessor
58{
59 public:
60
61 RayTriangle3DIntersection(ITraceMng* tm)
62 : TraceAccessor(tm)
63 {
64 }
65
70 {
71 m_rays_origin = origins;
72 m_rays_direction = directions;
73 }
74
82 {
83 m_triangles_coordinates = coordinates;
84 m_triangles_indexes = indexes;
85 }
86
91 void compute();
102 {
103 return m_distances;
104 }
105
114 {
115 return m_intersected_triangle_indexes;
116 }
117
118 Real checkIntersection(Real3 origin, Real3 direction, Real3 p0, Real3 p1, Real3 p2);
119
120 static bool checkBoundingBox(Real3 origin, Real3 direction, Real3 box_min, Real3 box_max);
121
122 private:
123
124 void _compute2(Int32 triangle_id, Real3 p0, Real3 p1, Real3 p2);
125
126 private:
127
128 Real3ConstArrayView m_rays_origin;
129 Real3ConstArrayView m_rays_direction;
130 Real3ConstArrayView m_triangles_coordinates;
131 Int32ConstArrayView m_triangles_indexes;
132
133 RealUniqueArray m_distances;
134 Int32UniqueArray m_intersected_triangle_indexes;
135};
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
141compute()
142{
143 Integer nb_ray = m_rays_origin.size();
144 m_distances.resize(nb_ray);
145 m_distances.fill(1.0e100);
146 m_intersected_triangle_indexes.resize(nb_ray);
147 m_intersected_triangle_indexes.fill(-1);
148 Integer nb_index = m_triangles_indexes.size();
149 if ((nb_index % 3) != 0)
150 throw FatalErrorException(A_FUNCINFO, "bad triangle_index count (({0}) % 3)!=0");
151 Integer nb_triangle = nb_index / 3;
152 info() << "COMPUTE RAY INTERSECTION nb_ray=" << nb_ray
153 << " nb_triangle=" << nb_triangle;
154
155 for (Integer i = 0; i < nb_triangle; ++i) {
156 Real3 p0 = m_triangles_coordinates[m_triangles_indexes[(i * 3)]];
157 Real3 p1 = m_triangles_coordinates[m_triangles_indexes[(i * 3) + 1]];
158 Real3 p2 = m_triangles_coordinates[m_triangles_indexes[(i * 3) + 2]];
159 _compute2(i, p0, p1, p2);
160 }
161
162 for (Integer i = 0; i < nb_ray; ++i) {
163 Int32 tid = m_intersected_triangle_indexes[i];
164 if (tid == (-1))
165 m_distances[i] = -1.0;
166 }
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172void RayTriangle3DIntersection::
173_compute2(Int32 triangle_id, Real3 p0, Real3 p1, Real3 p2)
174{
175 Integer nb_ray = m_rays_origin.size();
176 for (Integer i = 0; i < nb_ray; ++i) {
177 Real t = checkIntersection(m_rays_origin[i], m_rays_direction[i], p0, p1, p2);
178 if (t >= 0.0) {
179 info() << "Segment " << i << " intersect triangle " << triangle_id << " T=" << t;
180 if (t < m_distances[i]) {
181 m_distances[i] = t;
182 m_intersected_triangle_indexes[i] = triangle_id;
183 info() << "Get this triangle";
184 }
185 }
186 }
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
204 Real3 direction,
205 Real3 p0, Real3 p1, Real3 p2)
206{
207 // This routine is inspired by the code from the WildMagic library
208 // whose license is below.
209
210 // Wild Magic Source Code
211 // David Eberly
212 // http://www.geometrictools.com
213 // Copyright (c) 1998-2009
214 //
215 // This library is free software; you can redistribute it and/or modify it
216 // under the terms of the GNU Lesser General Public License as published by
217 // the Free Software Foundation; either version 2.1 of the License, or (at
218 // your option) any later version. The license is available for reading at
219 // either of the locations:
220 // http://www.gnu.org/copyleft/lgpl.html
221 // http://www.geometrictools.com/License/WildMagicLicense.pdf
222 //
223
224 Real ZERO_TOLERANCE = 1.0e-14;
225 // compute the offset origin, edges, and normal
226 Real3 kDiff = origin - p0;
227 Real3 kEdge1 = p1 - p0;
228 Real3 kEdge2 = p2 - p0;
229 Real3 kNormal = math::vecMul(kEdge1, kEdge2);
230
231 Real fDdN = math::dot(direction, kNormal);
232 Real fSign;
233 if (fDdN > ZERO_TOLERANCE) {
234 fSign = (Real)1.0;
235 }
236 else if (fDdN < -ZERO_TOLERANCE) {
237 fSign = (Real)-1.0;
238 fDdN = -fDdN;
239 }
240 else {
241 // Segment and triangle are parallel, call it a "no intersection"
242 // even if the segment does intersect.
243 return (-1.0);
244 }
245
246 Real fDdQxE2 = fSign * math::dot(direction, math::vecMul(kDiff, kEdge2));
247 if (fDdQxE2 >= (Real)0.0) {
248 Real fDdE1xQ = fSign * math::dot(direction, math::vecMul(kEdge1, kDiff));
249 if (fDdE1xQ >= (Real)0.0) {
250 Real diff = fDdN - (fDdQxE2 + fDdE1xQ);
251 // Epsilon is used if the segment passes through the face near
252 // one of the face edges. In this case, we consider there
253 // to be an intersection. Without this, due to numerical rounding,
254 // a segment could pass through the mesh by going through an
255 // edge between two faces without intersecting them.
256 if (diff >= 0.0 || diff > -ZERO_TOLERANCE) {
257 // line intersects triangle, check if segment does
258 Real fQdN = -fSign * math::dot(kDiff, kNormal);
259
260 // Since this is a half-line and not a segment,
261 // there is always an intersection if \a t is positive.
262#if 0
263 Real fExtDdN = m_pkSegment->Extent*fDdN;
264 if (-fExtDdN <= fQdN && fQdN <= fExtDdN)
265 {
266 // segment intersects triangle
267 return true;
268 }
269#endif
270 Real fInv = ((Real)1.0) / fDdN;
271 Real t = fQdN * fInv;
272 //Real b1 = fDdQxE2*fInv;
273 //Real b2 = fDdE1xQ*fInv;
274 //Real b0 = (Real)1.0 - b1 - b2;
275 // P = origin + t*direction = b0*V0 + b1*V1 + b2*V2
276 //info() << "** INTERSECT POS=" << b0 << " y=" << b1 << " z=" << b2 << " T=" << t;
277 //Real intersect_p = origin + t*direction;
278 return t;
279
280 // else: |t| > extent, no intersection
281 }
282 // else: b1+b2 > 1, no intersection
283 }
284 // else: b2 < 0, no intersection
285 }
286 // else: b1 < 0, no intersection
287
288 return (-1.0);
289}
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293
294bool RayTriangle3DIntersection::
295checkBoundingBox(Real3 origin, Real3 direction, Real3 box_min, Real3 box_max)
296{
297 Real3 box_center = (box_max + box_min) * 0.5;
298 Real afWdU[3], afAWdU[3], afDdU[3], afADdU[3], afAWxDdU[3], fRhs;
299
300 Real3 kDiff = origin - box_center;
301 Real3 Axis[3];
302 //Axis[0].x = box_max.x - box_min.x;
303 //Axis[1].y = box_max.y - box_min.y;
304 //Axis[2].z = box_max.z - box_min.z;
305 Axis[0] = Real3(1.0, 0.0, 0.0);
306 Axis[1] = Real3(0.0, 1.0, 0.0);
307 Axis[2] = Real3(0.0, 0.0, 1.0);
308 Real Extent[3];
309 Extent[0] = box_max.x - box_min.x;
310 Extent[1] = box_max.y - box_min.y;
311 Extent[2] = box_max.z - box_min.z;
312
313 afWdU[0] = math::dot(direction, Axis[0]);
314 afAWdU[0] = math::abs(afWdU[0]);
315 afDdU[0] = math::dot(kDiff, Axis[0]);
316 afADdU[0] = math::abs(afDdU[0]);
317 if (afADdU[0] > Extent[0] && afDdU[0] * afWdU[0] >= (Real)0.0) {
318 return false;
319 }
320
321 afWdU[1] = math::dot(direction, Axis[1]);
322 afAWdU[1] = math::abs(afWdU[1]);
323 afDdU[1] = math::dot(kDiff, Axis[1]);
324 afADdU[1] = math::abs(afDdU[1]);
325 if (afADdU[1] > Extent[1] && afDdU[1] * afWdU[1] >= (Real)0.0) {
326 return false;
327 }
328
329 afWdU[2] = math::dot(direction, Axis[2]);
330 afAWdU[2] = math::abs(afWdU[2]);
331 afDdU[2] = math::dot(kDiff, Axis[2]);
332 afADdU[2] = math::abs(afDdU[2]);
333 if (afADdU[2] > Extent[2] && afDdU[2] * afWdU[2] >= (Real)0.0) {
334 return false;
335 }
336
337 Real3 kWxD = math::vecMul(direction, kDiff);
338
339 afAWxDdU[0] = math::abs(math::dot(kWxD, Axis[0]));
340 fRhs = Extent[1] * afAWdU[2] + Extent[2] * afAWdU[1];
341 if (afAWxDdU[0] > fRhs) {
342 return false;
343 }
344
345 afAWxDdU[1] = math::abs(math::dot(kWxD, Axis[1]));
346 fRhs = Extent[0] * afAWdU[2] + Extent[2] * afAWdU[0];
347 if (afAWxDdU[1] > fRhs) {
348 return false;
349 }
350
351 afAWxDdU[2] = math::abs(math::dot(kWxD, Axis[2]));
352 fRhs = Extent[0] * afAWdU[1] + Extent[1] * afAWdU[0];
353 if (afAWxDdU[2] > fRhs) {
354 return false;
355 }
356
357 return true;
358}
359
360/*---------------------------------------------------------------------------*/
361/*---------------------------------------------------------------------------*/
362
363class BasicRayFaceIntersector
364: public IRayFaceIntersector
365{
366 public:
367
368 BasicRayFaceIntersector(ITraceMng* tm)
369 : m_triangle_intersector(tm)
370 {
371 }
372
373 public:
374
375 bool computeIntersection(Real3 origin, Real3 direction,
376 Int32 orig_face_local_id,
377 Int32 face_local_id,
378 Real3ConstArrayView face_nodes,
379 Int32* user_value,
380 Real* distance, Real3* position)
381 {
382 ARCANE_UNUSED(orig_face_local_id);
383 ARCANE_UNUSED(face_local_id);
384
385 Integer nb_node = face_nodes.size();
386 switch (nb_node) {
387 case 4: {
388 Real3 center = (face_nodes[0] + face_nodes[1] + face_nodes[2] + face_nodes[3]) / 4.0;
389 Real d0 = m_triangle_intersector.checkIntersection(origin, direction, center, face_nodes[0], face_nodes[1]);
390 Real d1 = m_triangle_intersector.checkIntersection(origin, direction, center, face_nodes[1], face_nodes[2]);
391 Real d2 = m_triangle_intersector.checkIntersection(origin, direction, center, face_nodes[2], face_nodes[3]);
392 Real d3 = m_triangle_intersector.checkIntersection(origin, direction, center, face_nodes[3], face_nodes[0]);
393 Real d = 1.0e100;
394 bool found = false;
395 if (d0 >= 0.0 && d0 < d) {
396 found = true;
397 d = d0;
398 }
399 if (d1 >= 0.0 && d1 < d) {
400 found = true;
401 d = d1;
402 }
403 if (d2 >= 0.0 && d2 < d) {
404 found = true;
405 d = d2;
406 }
407 if (d3 >= 0.0 && d3 < d) {
408 found = true;
409 d = d3;
410 }
411 if (!found)
412 d = -1.0;
413 *distance = d;
414 *position = origin + d * direction;
415 *user_value = 1;
416 return found;
417 } break;
418 default:
419 throw NotImplementedException(A_FUNCINFO, "only quad face is implemented");
420 }
421 }
422
423 public:
424
425 RayTriangle3DIntersection m_triangle_intersector;
426};
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
430
434class BasicRayMeshIntersection
435: public BasicService
437{
438 public:
439
440 BasicRayMeshIntersection(const ServiceBuildInfo& sbi);
441 virtual ~BasicRayMeshIntersection() {}
442
443 public:
444
445 virtual void build() {}
446 virtual void compute(Real3ConstArrayView segments_position,
447 Real3ConstArrayView segments_direction,
448 Int32ConstArrayView segments_orig_face,
449 Int32ArrayView user_values,
450 Real3ArrayView intersections,
451 RealArrayView distances,
452 Int32ArrayView faces_local_id);
453
454 virtual void compute(IItemFamily* ray_family,
455 VariableParticleReal3& rays_position,
456 VariableParticleReal3& rays_direction,
457 VariableParticleInt32& rays_orig_face,
458 VariableParticleInt32& user_values,
459 VariableParticleReal3& intersections,
460 VariableParticleReal& distances,
461 VariableParticleInt32& rays_face);
462
463 virtual void setFaceIntersector(IRayFaceIntersector* intersector)
464 {
465 m_face_intersector = intersector;
466 }
468 {
469 return m_face_intersector;
470 }
471
472 public:
473
474 inline void _checkBoundingBox(Real3 p, Real3* ARCANE_RESTRICT min_bounding_box,
475 Real3* ARCANE_RESTRICT max_bounding_box)
476 {
477 if (p.x < min_bounding_box->x)
478 min_bounding_box->x = p.x;
479 if (p.y < min_bounding_box->y)
480 min_bounding_box->y = p.y;
481 if (p.z < min_bounding_box->z)
482 min_bounding_box->z = p.z;
483
484 if (p.x > max_bounding_box->x)
485 max_bounding_box->x = p.x;
486 if (p.y > max_bounding_box->y)
487 max_bounding_box->y = p.y;
488 if (p.z > max_bounding_box->z)
489 max_bounding_box->z = p.z;
490 }
491
492 private:
493
494 IRayFaceIntersector* m_face_intersector;
495};
496
497/*---------------------------------------------------------------------------*/
498/*---------------------------------------------------------------------------*/
499
500BasicRayMeshIntersection::
501BasicRayMeshIntersection(const ServiceBuildInfo& sbi)
502: BasicService(sbi)
503, m_face_intersector(0)
504{
505}
506
507/*---------------------------------------------------------------------------*/
508/*---------------------------------------------------------------------------*/
509
511compute(Real3ConstArrayView segments_position,
512 Real3ConstArrayView segments_direction,
513 Int32ConstArrayView segments_orig_face,
514 Int32ArrayView user_values,
515 Real3ArrayView segments_intersection,
516 RealArrayView segments_distance,
517 Int32ArrayView faces_local_id)
518{
519 IMesh* mesh = this->mesh();
520
521 bool is_3d = mesh->dimension() == 3;
522 info() << "COMPUTE INTERSECTION!!";
523 FaceGroup outer_faces = mesh->outerFaces();
524 Integer nb_face = outer_faces.size();
525 Integer nb_segment = segments_position.size();
526 info() << "NB OUTER FACE=" << nb_face << " NB_SEGMENT=" << nb_segment;
527 VariableNodeReal3 nodes_coordinates(mesh->nodesCoordinates());
528 const Real max_value = 1.0e100;
529 const Real3 max_bb(max_value, max_value, max_value);
530 const Real3 min_bb(-max_value, -max_value, -max_value);
531
532 Real3 mesh_min_bounding_box(max_bb);
533 Real3 mesh_max_bounding_box(min_bb);
534 Integer max_face_local_id = mesh->faceFamily()->maxLocalId();
535 Real3UniqueArray faces_min_bb(max_face_local_id);
536 Real3UniqueArray faces_max_bb(max_face_local_id);
537
538 // Calculate the bounding boxes
539 {
540 ENUMERATE_FACE (iface, outer_faces) {
541 Int32 lid = iface.localId();
542 Real3 face_max_bb(max_bb);
543 Real3 face_min_bb(min_bb);
544 for (NodeEnumerator inode((*iface).nodes()); inode.hasNext(); ++inode)
545 _checkBoundingBox(nodes_coordinates[inode], &face_min_bb, &face_max_bb);
546 _checkBoundingBox(face_min_bb, &mesh_min_bounding_box, &mesh_max_bounding_box);
547 _checkBoundingBox(face_max_bb, &mesh_min_bounding_box, &mesh_max_bounding_box);
548 //TODO: maybe add an epsilon around the BB to avoid
549 // rounding errors in determining the intersection
550 faces_min_bb[lid] = face_min_bb;
551 faces_max_bb[lid] = face_max_bb;
552 }
553 }
554
555 //RealArray segments_distance;
556 segments_distance.fill(max_value);
557 faces_local_id.fill(NULL_ITEM_LOCAL_ID);
558
559 if (!m_face_intersector)
560 m_face_intersector = new BasicRayFaceIntersector(traceMng());
561
562 Real3UniqueArray face_nodes;
563 for (Integer i = 0; i < nb_segment; ++i) {
564 Real3 position = segments_position[i];
565 Real3 direction = segments_direction[i];
566 Int32 orig_face_local_id = segments_orig_face[i];
567 Real3 intersection;
568 Real distance = 1.0e100;
569 Int32 min_face_local_id = NULL_ITEM_LOCAL_ID;
570 Int32 user_value = 0;
571 ENUMERATE_FACE (iface, outer_faces) {
572 const Face& face = *iface;
573 // Only process its own faces
574 if (!face.isOwn())
575 continue;
576 Int32 lid = face.localId();
577 // In 3D, check for intersection with the bounding box.
578 // If there is none, there is no need to go further.
579 bool is_bb = true;
580 if (is_3d)
581 is_bb = RayTriangle3DIntersection::checkBoundingBox(position, direction, faces_min_bb[lid], faces_max_bb[lid]);
582 if (!is_bb)
583 continue;
584 Integer nb_node = face.nbNode();
585 face_nodes.resize(nb_node);
586 for (NodeEnumerator inode(face.nodes()); inode.hasNext(); ++inode)
587 face_nodes[inode.index()] = nodes_coordinates[inode];
588 Real d = 0.0;
589 Real3 local_intersection;
590 Int32 uv = 0;
591 bool is_found = m_face_intersector->computeIntersection(position, direction, orig_face_local_id, lid,
592 face_nodes, &uv, &d, &local_intersection);
593 //if (i==15){
594 // for( Integer z=0; z<nb_node; ++z )
595 // info() << "FACE NODE lid=" << lid << " I=" << i << " v=" << face_nodes[z] << " d=" << d;
596 //}
597 //if (!is_bb)
598 //info() << "CHECK INTERSECTION: is_bb=" << is_bb << " " << is_found << '\n';
599 if (is_found && !is_bb)
600 fatal() << "Intersection found but no bounding box intersection";
601 if (is_found && d < distance) {
602 distance = d;
603 min_face_local_id = lid;
604 intersection = local_intersection;
605 user_value = uv;
606 }
607 }
608 if (min_face_local_id == NULL_ITEM_LOCAL_ID)
609 distance = -1.0;
610 segments_distance[i] = distance;
611 segments_intersection[i] = intersection;
612 faces_local_id[i] = min_face_local_id;
613 user_values[i] = user_value;
614 }
615}
616
618{
619 Int32 contrib_owner;
620 Int32 owner;
621 Int32 local_id;
622 Int32 face_local_id;
623 Int32 orig_face_local_id;
624 Int32 user_value;
625 Real distance;
626 Real3POD intersection;
627};
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
631
633compute(IItemFamily* ray_family,
634 VariableParticleReal3& rays_position,
635 VariableParticleReal3& rays_direction,
636 VariableParticleInt32& rays_orig_face,
637 VariableParticleInt32& rays_user_value,
638 VariableParticleReal3& intersections,
639 VariableParticleReal& distances,
640 VariableParticleInt32& rays_face)
641{
642 // NOTE: rays_orig_face is not used.
643
644 IMesh* mesh = ray_family->mesh();
645 IParallelMng* pm = mesh->parallelMng();
646 Int32 my_rank = pm->commRank();
647 // Assume that the rays are compacted
648 Integer nb_local_ray = ray_family->allItems().size();
649 //if (nb_local_ray!=ray_family->maxLocalId()){
650 //fatal() << "The ray family must be compacted nb=" << nb_local_ray
651 // << " max_id=" << ray_family->maxLocalId();
652 //}
653 Integer global_nb_ray = pm->reduce(Parallel::ReduceSum, nb_local_ray);
654 if (global_nb_ray == 0)
655 return;
656 info() << "LOCAL_NB_RAY=" << nb_local_ray << " GLOBAL=" << global_nb_ray;
657
658 // Copy input information into a local array.
659 // This is always necessary because particles are not necessarily
660 // compacted and there may be holes in the numbering.
661 Real3UniqueArray local_positions(nb_local_ray);
662 Real3UniqueArray local_directions(nb_local_ray);
663
664 ENUMERATE_PARTICLE (iitem, ray_family->allItems()) {
665 Integer index = iitem.index();
666 //local_ids[index] = iitem.localId();
667 //unique_ids[index] = (*iitem).uniqueId();
668 local_positions[index] = rays_position[iitem];
669 local_directions[index] = rays_direction[iitem];
670 }
671
672 if (pm->isParallel()) {
673
674 Int32UniqueArray local_ids(nb_local_ray);
675 Int64UniqueArray unique_ids(nb_local_ray);
676 ENUMERATE_ITEM (iitem, ray_family->allItems()) {
677 Integer index = iitem.index();
678 local_ids[index] = iitem.localId();
679 unique_ids[index] = (*iitem).uniqueId();
680 }
681
682 // In parallel, currently retrieve rays from other processors
683
684 Real3UniqueArray all_positions;
685 pm->allGatherVariable(local_positions, all_positions);
686 Real3UniqueArray all_directions;
687 pm->allGatherVariable(local_directions, all_directions);
688
689 Int32UniqueArray local_owners(nb_local_ray);
690 local_owners.fill(my_rank);
691
692 Int32UniqueArray all_owners;
693 pm->allGatherVariable(local_owners, all_owners);
694 Int32UniqueArray all_local_ids;
695 pm->allGatherVariable(local_ids, all_local_ids);
696 Int64UniqueArray all_unique_ids;
697 pm->allGatherVariable(unique_ids, all_unique_ids);
698
699 Int32UniqueArray all_user_values(global_nb_ray);
700 Int32UniqueArray all_orig_faces(global_nb_ray, NULL_ITEM_LOCAL_ID);
701 RealUniqueArray all_distances(global_nb_ray);
702 Real3UniqueArray all_intersections(global_nb_ray);
703 Int32UniqueArray all_faces(global_nb_ray);
704 // Set faces that I am not the owner of to (-1)
705 for (Integer z = 0, zn = all_orig_faces.size(); z < zn; ++z) {
706 if (all_owners[z] != my_rank)
707 all_orig_faces[z] = NULL_ITEM_LOCAL_ID;
708 }
709 compute(all_positions, all_directions, all_orig_faces, all_user_values, all_intersections, all_distances, all_faces);
710 /*for( Integer i=0; i<global_nb_ray; ++i ){
711 info() << "RAY I=" << i << " uid=" << all_unique_ids[i] << " lid=" << all_local_ids[i]
712 << " owner=" << all_owners[i] << " position=" << all_positions[i]
713 << " direction=" << all_directions[i] << " distance=" << all_distances[i]
714 << " face=" << all_faces[i];
715 }*/
716 {
717 UniqueArray<FoundInfo> founds_info;
718
719 for (Integer i = 0; i < global_nb_ray; ++i) {
720 Int32 face_lid = all_faces[i];
721 if (face_lid == NULL_ITEM_LOCAL_ID)
722 continue;
723 FoundInfo fi;
724 fi.contrib_owner = my_rank;
725 fi.owner = all_owners[i];
726 fi.local_id = all_local_ids[i];
727 fi.face_local_id = all_faces[i];
728 fi.orig_face_local_id = all_orig_faces[i];
729 fi.user_value = all_user_values[i];
730 fi.intersection = all_intersections[i];
731 fi.distance = all_distances[i];
732 founds_info.add(fi);
733 }
734 info() << "NB_FOUND=" << founds_info.size();
735 //Array<FoundInfo> global_founds_info;
736 ByteUniqueArray global_founds_info_bytes;
737 Integer finfo_byte_size = arcaneCheckArraySize(founds_info.size() * sizeof(FoundInfo));
738 ByteConstArrayView local_fi(finfo_byte_size, (const Byte*)founds_info.data());
739 pm->allGatherVariable(local_fi, global_founds_info_bytes);
740 Integer gfi_byte_size = arcaneCheckArraySize(global_founds_info_bytes.size() / sizeof(FoundInfo));
741 ConstArrayView<FoundInfo> global_founds_info(gfi_byte_size, (const FoundInfo*)global_founds_info_bytes.data());
742 Integer nb_total_found = global_founds_info.size();
743 ParticleInfoListView rays(ray_family);
744 rays_face.fill(NULL_ITEM_LOCAL_ID);
745 distances.fill(0.0);
746 VariableItemInt32& rays_new_owner = ray_family->itemsNewOwner();
747 rays_new_owner.fill(my_rank);
748 for (Integer i = 0; i < nb_total_found; ++i) {
749 const FoundInfo& fi = global_founds_info[i];
750 Int32 owner = fi.owner;
751 // Only process its own rays
752 if (owner != my_rank)
753 continue;
754 Int32 local_id = fi.local_id;
755 Particle ray = rays[local_id];
756 Real distance = fi.distance;
757 if ((rays_face[ray] == NULL_ITEM_LOCAL_ID) || distance < distances[ray]) {
758 distances[ray] = distance;
759 intersections[ray] = Real3(fi.intersection.x, fi.intersection.y, fi.intersection.z);
760 rays_face[ray] = fi.face_local_id;
761 rays_user_value[ray] = fi.user_value;
762 rays_new_owner[ray] = fi.contrib_owner;
763 //info() << "SET RAY uid=" << ray.uniqueId() << " distance=" << distance << " new_owner=" << fi.contrib_owner;
764 }
765 /*info() << "GLOBAL RAY I=" << i << " uid=" << ray.uniqueId() << " lid=" << fi.local_id
766 << " owner=" << fi.owner
767 << " distance=" << fi.distance
768 << " contrib_owner=" << fi.contrib_owner
769 << " face=" << fi.face_local_id
770 << " new_owner=" << rays_new_owner[ray];*/
771 }
772 ray_family->toParticleFamily()->exchangeParticles();
773 }
774 }
775 else {
776
777 Int32UniqueArray orig_faces(nb_local_ray);
778 Int32UniqueArray user_values(nb_local_ray);
779
780 ENUMERATE_PARTICLE (iitem, ray_family->allItems()) {
781 Integer index = iitem.index();
782 orig_faces[index] = rays_orig_face[iitem];
783 user_values[index] = rays_user_value[iitem];
784 }
785
786 Real3UniqueArray out_intersections(nb_local_ray);
787 RealUniqueArray out_distances(nb_local_ray);
788 Int32UniqueArray out_faces(nb_local_ray);
789
790 compute(local_positions, local_directions, orig_faces, user_values, out_intersections, out_distances, out_faces);
791
792 // Copy values back to the corresponding variables in the output.
793 ENUMERATE_PARTICLE (iitem, ray_family->allItems()) {
794 Integer index = iitem.index();
795 intersections[iitem] = out_intersections[index];
796 distances[iitem] = out_distances[index];
797 rays_face[iitem] = out_faces[index];
798 }
799 }
800
801 // For testing, write the rays and their impact point.
802 {
803 Integer nb_new_ray = ray_family->nbItem();
804 RealUniqueArray local_distances(nb_new_ray);
805 local_directions.resize(nb_new_ray);
806 local_positions.resize(nb_new_ray);
807 ENUMERATE_PARTICLE (iitem, ray_family->allItems()) {
808 Integer index = iitem.index();
809 local_distances[index] = distances[iitem];
810 local_directions[index] = rays_direction[iitem];
811 local_positions[index] = rays_position[iitem];
812 }
813 }
814}
815
816/*---------------------------------------------------------------------------*/
817/*---------------------------------------------------------------------------*/
818
821
822/*---------------------------------------------------------------------------*/
823/*---------------------------------------------------------------------------*/
824
825} // End namespace Arcane
826
827/*---------------------------------------------------------------------------*/
828/*---------------------------------------------------------------------------*/
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_PARTICLE(name, group)
Generic enumerator for a particle group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
Integer size() const
Number of elements in the vector.
void fill(const T &o) noexcept
Fills the array with the value o.
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
void add(ConstReferenceType val)
Adds element val to the end of the array.
const T * data() const
Access to the root of the array without any protection.
bool computeIntersection(Real3 origin, Real3 direction, Int32 orig_face_local_id, Int32 face_local_id, Real3ConstArrayView face_nodes, Int32 *user_value, Real *distance, Real3 *position)
Calculates the intersection between a ray and a face.
Basic service for calculating intersection between segments and mesh.
virtual void build()
Build-level construction of the service.
virtual void setFaceIntersector(IRayFaceIntersector *intersector)
Sets the intersection callback.
virtual IRayFaceIntersector * faceIntersector()
Intersector used (0 if none specified).
virtual void compute(Real3ConstArrayView segments_position, Real3ConstArrayView segments_direction, Int32ConstArrayView segments_orig_face, Int32ArrayView user_values, Real3ArrayView intersections, RealArrayView distances, Int32ArrayView faces_local_id)
Calculates the intersection.
Base class of a service linked to a subdomain.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Face of a cell.
Definition Item.h:1032
Interface of an entity family.
Definition IItemFamily.h:83
virtual IParticleFamily * toParticleFamily()=0
Returns the interface of the particle family for this family.
virtual ItemGroup allItems() const =0
Group of all entities.
virtual IMesh * mesh() const =0
Associated mesh.
virtual Integer nbItem() const =0
Number of entities.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable containing the number of the new subdomain owning the entity.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Performs an all-gather operation across all processors.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
virtual void exchangeParticles()=0
Exchanging entities.
Generic interface for calculating the intersection of a ray with a face.
Calculation of the intersection between a set of segments and the surface of a mesh.
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Definition Item.h:843
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
constexpr bool isOwn() const
true if the entity belongs to the subdomain
Definition Item.h:267
View of particle information.
Particle.
Definition Item.h:1529
Calculates the intersection of a ray with a set of triangles in 3D.
void setRays(Real3ConstArrayView origins, Real3ConstArrayView directions)
Positions the list of rays for which intersection is desired.
Real checkIntersection(Real3 origin, Real3 direction, Real3 p0, Real3 p1, Real3 p2)
Calculates the intersection of the half-line [origin,direction) with the triangle (p0,...
void compute()
Calculates the intersection of each ray with the list of triangles. If a ray intersects multiple tria...
void setTriangles(Real3ConstArrayView coordinates, Int32ConstArrayView indexes)
Positions the list of triangles for which intersection is desired with the rays. The array indexes co...
Int32ConstArrayView intersectedTriangleIndexes()
Indices of intersected triangles. Index in the array provided by setTriangles() of the triangle inter...
RealConstArrayView distances()
Distance from the origin of a ray to its intersection point. Distance (expressed relative to the norm...
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Structure containing the information to create a service.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
__host__ __device__ Real dot(Real2 u, Real2 v)
Dot product of u by v in .
Definition MathUtils.h:94
__host__ __device__ Real3 vecMul(Real3 u, Real3 v)
Vector cross product of u by v in .
Definition MathUtils.h:48
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
ItemEnumeratorT< Node > NodeEnumerator
Enumerators over nodes.
Definition ItemTypes.h:255
MeshVariableScalarRefT< Particle, Real3 > VariableParticleReal3
Coordinate type particle quantity.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
MeshVariableScalarRefT< Particle, Int32 > VariableParticleInt32
Particle quantity of 32-bit integer type.
MeshVariableScalarRefT< Particle, Real > VariableParticleReal
Real type particle quantity.
ItemVariableScalarRefT< Int32 > VariableItemInt32
32-bit integer type quantity
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Integer arcaneCheckArraySize(unsigned long long size)
Checks that size can be converted into an 'Integer' to serve as the size of an array....
ConstArrayView< Real3 > Real3ConstArrayView
C equivalent of a 1D array of Real3.
Definition UtilsTypes.h:496
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
ArrayView< Real3 > Real3ArrayView
C equivalent of a 1D array of Real3.
Definition UtilsTypes.h:467
Int32 Integer
Type representing an integer.
UniqueArray< Real3 > Real3UniqueArray
Dynamic 1D array of rank 3 vectors.
Definition UtilsTypes.h:363
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
Definition UtilsTypes.h:349
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:459
std::int32_t Int32
Signed integer type of 32 bits.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:488
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35