Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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/* Service basique de calcul d'intersection entre segments et maillage. */
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/*---------------------------------------------------------------------------*/
55class RayTriangle3DIntersection
56: public TraceAccessor
57{
58 public:
59 RayTriangle3DIntersection(ITraceMng* tm)
60 : TraceAccessor(tm)
61 {
62 }
63
68 {
69 m_rays_origin = origins;
70 m_rays_direction = directions;
71 }
72
80 {
81 m_triangles_coordinates = coordinates;
82 m_triangles_indexes = indexes;
83 }
84
89 void compute();
100 {
101 return m_distances;
102 }
103
112 {
113 return m_intersected_triangle_indexes;
114 }
115
116 Real checkIntersection(Real3 origin,Real3 direction,Real3 p0,Real3 p1,Real3 p2);
117
118 static bool checkBoundingBox(Real3 origin,Real3 direction,Real3 box_min,Real3 box_max);
119
120 private:
121
122 void _compute2(Int32 triangle_id,Real3 p0,Real3 p1,Real3 p2);
123
124 private:
125
126 Real3ConstArrayView m_rays_origin;
127 Real3ConstArrayView m_rays_direction;
128 Real3ConstArrayView m_triangles_coordinates;
129 Int32ConstArrayView m_triangles_indexes;
130
131 RealUniqueArray m_distances;
132 Int32UniqueArray m_intersected_triangle_indexes;
133};
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
139compute()
140{
141 Integer nb_ray = m_rays_origin.size();
142 m_distances.resize(nb_ray);
143 m_distances.fill(1.0e100);
144 m_intersected_triangle_indexes.resize(nb_ray);
145 m_intersected_triangle_indexes.fill(-1);
146 Integer nb_index = m_triangles_indexes.size();
147 if ((nb_index%3)!=0)
148 throw FatalErrorException(A_FUNCINFO,"bad triangle_index count (({0}) % 3)!=0");
149 Integer nb_triangle = nb_index / 3;
150 info() << "COMPUTE RAY INTERSECTION nb_ray=" << nb_ray
151 << " nb_triangle=" << nb_triangle;
152
153 for( Integer i=0; i<nb_triangle; ++i ){
154 Real3 p0 = m_triangles_coordinates[m_triangles_indexes[(i*3)]];
155 Real3 p1 = m_triangles_coordinates[m_triangles_indexes[(i*3)+1]];
156 Real3 p2 = m_triangles_coordinates[m_triangles_indexes[(i*3)+2]];
157 _compute2(i,p0,p1,p2);
158 }
159
160 for( Integer i=0; i<nb_ray; ++i ){
161 Int32 tid = m_intersected_triangle_indexes[i];
162 if (tid==(-1))
163 m_distances[i] = -1.0;
164 }
165}
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
170void RayTriangle3DIntersection::
171_compute2(Int32 triangle_id,Real3 p0,Real3 p1,Real3 p2)
172{
173 Integer nb_ray = m_rays_origin.size();
174 for( Integer i=0; i<nb_ray; ++i ){
175 Real t = checkIntersection(m_rays_origin[i],m_rays_direction[i],p0,p1,p2);
176 if (t>=0.0){
177 info() << "Segment " << i << " intersect triangle " << triangle_id << " T=" << t;
178 if (t<m_distances[i]){
179 m_distances[i] = t;
180 m_intersected_triangle_indexes[i] = triangle_id;
181 info() << "Get this triangle";
182 }
183 }
184 }
185}
186
187/*---------------------------------------------------------------------------*/
188/*---------------------------------------------------------------------------*/
201 Real3 direction,
202 Real3 p0,Real3 p1,Real3 p2)
203{
204 // Cette routine s'inspire du code de la bibliothèque WildMagic
205 // dont la licence est ci-dessous.
206
207 // Wild Magic Source Code
208 // David Eberly
209 // http://www.geometrictools.com
210 // Copyright (c) 1998-2009
211 //
212 // This library is free software; you can redistribute it and/or modify it
213 // under the terms of the GNU Lesser General Public License as published by
214 // the Free Software Foundation; either version 2.1 of the License, or (at
215 // your option) any later version. The license is available for reading at
216 // either of the locations:
217 // http://www.gnu.org/copyleft/lgpl.html
218 // http://www.geometrictools.com/License/WildMagicLicense.pdf
219 //
220
221
222 Real ZERO_TOLERANCE = 1.0e-14;
223 // compute the offset origin, edges, and normal
224 Real3 kDiff = origin - p0;
225 Real3 kEdge1 = p1 - p0;
226 Real3 kEdge2 = p2 - p0;
227 Real3 kNormal = math::vecMul(kEdge1,kEdge2);
228
229 Real fDdN = math::dot(direction,kNormal);
230 Real fSign;
231 if (fDdN > ZERO_TOLERANCE)
232 {
233 fSign = (Real)1.0;
234 }
235 else if (fDdN < -ZERO_TOLERANCE)
236 {
237 fSign = (Real)-1.0;
238 fDdN = -fDdN;
239 }
240 else
241 {
242 // Segment and triangle are parallel, call it a "no intersection"
243 // even if the segment does intersect.
244 return (-1.0);
245 }
246
247 Real fDdQxE2 = fSign*math::dot(direction,math::vecMul(kDiff,kEdge2));
248 if (fDdQxE2 >= (Real)0.0)
249 {
250 Real fDdE1xQ = fSign*math::dot(direction,math::vecMul(kEdge1,kDiff));
251 if (fDdE1xQ >= (Real)0.0)
252 {
253 Real diff = fDdN-(fDdQxE2 + fDdE1xQ);
254 // L'epsilon sert si le segment traverse par la face à proximité
255 // d'une des arêtes de la face. Dans ce cas, on considère qu'il
256 // y a intersection. Sans cela, à cause des arrondis numériques,
257 // un segment pourrait traverser le maillage en passant par une
258 // arête entre deux faces sans intersecter ces dernières.
259 if (diff>=0.0 || diff>-ZERO_TOLERANCE)
260 {
261 // line intersects triangle, check if segment does
262 Real fQdN = -fSign*math::dot(kDiff,kNormal);
263
264 // Comme il s'agit d'une demi-droite et pas d'un segment,
265 // il y a toujours intersection si \a t est positif.
266#if 0
267 Real fExtDdN = m_pkSegment->Extent*fDdN;
268 if (-fExtDdN <= fQdN && fQdN <= fExtDdN)
269 {
270 // segment intersects triangle
271 return true;
272 }
273#endif
274 Real fInv = ((Real)1.0)/fDdN;
275 Real t = fQdN*fInv;
276 //Real b1 = fDdQxE2*fInv;
277 //Real b2 = fDdE1xQ*fInv;
278 //Real b0 = (Real)1.0 - b1 - b2;
279 // P = origin + t*direction = b0*V0 + b1*V1 + b2*V2
280 //info() << "** INTERSECT POS=" << b0 << " y=" << b1 << " z=" << b2 << " T=" << t;
281 //Real intersect_p = origin + t*direction;
282 return t;
283
284 // else: |t| > extent, no intersection
285 }
286 // else: b1+b2 > 1, no intersection
287 }
288 // else: b2 < 0, no intersection
289 }
290 // else: b1 < 0, no intersection
291
292 return (-1.0);
293}
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297
298bool RayTriangle3DIntersection::
299checkBoundingBox(Real3 origin,Real3 direction,Real3 box_min,Real3 box_max)
300{
301 Real3 box_center = (box_max+box_min) * 0.5;
302 Real afWdU[3], afAWdU[3], afDdU[3], afADdU[3], afAWxDdU[3], fRhs;
303
304 Real3 kDiff = origin - box_center;
305 Real3 Axis[3];
306 //Axis[0].x = box_max.x - box_min.x;
307 //Axis[1].y = box_max.y - box_min.y;
308 //Axis[2].z = box_max.z - box_min.z;
309 Axis[0] = Real3(1.0,0.0,0.0);
310 Axis[1] = Real3(0.0,1.0,0.0);
311 Axis[2] = Real3(0.0,0.0,1.0);
312 Real Extent[3];
313 Extent[0] = box_max.x - box_min.x;
314 Extent[1] = box_max.y - box_min.y;
315 Extent[2] = box_max.z - box_min.z;
316
317 afWdU[0] = math::dot(direction,Axis[0]);
318 afAWdU[0] = math::abs(afWdU[0]);
319 afDdU[0] = math::dot(kDiff,Axis[0]);
320 afADdU[0] = math::abs(afDdU[0]);
321 if (afADdU[0] > Extent[0] && afDdU[0]*afWdU[0] >= (Real)0.0)
322 {
323 return false;
324 }
325
326 afWdU[1] = math::dot(direction,Axis[1]);
327 afAWdU[1] = math::abs(afWdU[1]);
328 afDdU[1] = math::dot(kDiff,Axis[1]);
329 afADdU[1] = math::abs(afDdU[1]);
330 if (afADdU[1] > Extent[1] && afDdU[1]*afWdU[1] >= (Real)0.0)
331 {
332 return false;
333 }
334
335 afWdU[2] = math::dot(direction,Axis[2]);
336 afAWdU[2] = math::abs(afWdU[2]);
337 afDdU[2] = math::dot(kDiff,Axis[2]);
338 afADdU[2] = math::abs(afDdU[2]);
339 if (afADdU[2] > Extent[2] && afDdU[2]*afWdU[2] >= (Real)0.0)
340 {
341 return false;
342 }
343
344 Real3 kWxD = math::vecMul(direction,kDiff);
345
346 afAWxDdU[0] = math::abs(math::dot(kWxD,Axis[0]));
347 fRhs = Extent[1]*afAWdU[2] + Extent[2]*afAWdU[1];
348 if (afAWxDdU[0] > fRhs)
349 {
350 return false;
351 }
352
353 afAWxDdU[1] = math::abs(math::dot(kWxD,Axis[1]));
354 fRhs = Extent[0]*afAWdU[2] + Extent[2]*afAWdU[0];
355 if (afAWxDdU[1] > fRhs)
356 {
357 return false;
358 }
359
360 afAWxDdU[2] = math::abs(math::dot(kWxD,Axis[2]));
361 fRhs = Extent[0]*afAWdU[1] + Extent[1]*afAWdU[0];
362 if (afAWxDdU[2] > fRhs)
363 {
364 return false;
365 }
366
367 return true;
368}
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
372
373class BasicRayFaceIntersector
374: public IRayFaceIntersector
375{
376 public:
377 BasicRayFaceIntersector(ITraceMng* tm)
378 : m_triangle_intersector(tm)
379 {
380 }
381 public:
382 bool computeIntersection(Real3 origin,Real3 direction,
383 Int32 orig_face_local_id,
384 Int32 face_local_id,
385 Real3ConstArrayView face_nodes,
386 Int32* user_value,
387 Real* distance,Real3* position)
388 {
389 ARCANE_UNUSED(orig_face_local_id);
390 ARCANE_UNUSED(face_local_id);
391
392 Integer nb_node = face_nodes.size();
393 switch(nb_node){
394 case 4:
395 {
396 Real3 center = (face_nodes[0] + face_nodes[1] + face_nodes[2] + face_nodes[3]) / 4.0;
397 Real d0 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[0],face_nodes[1]);
398 Real d1 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[1],face_nodes[2]);
399 Real d2 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[2],face_nodes[3]);
400 Real d3 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[3],face_nodes[0]);
401 Real d = 1.0e100;
402 bool found = false;
403 if (d0>=0.0 && d0<d){
404 found = true;
405 d = d0;
406 }
407 if (d1>=0.0 && d1<d){
408 found = true;
409 d = d1;
410 }
411 if (d2>=0.0 && d2<d){
412 found = true;
413 d = d2;
414 }
415 if (d3>=0.0 && d3<d){
416 found = true;
417 d = d3;
418 }
419 if (!found)
420 d = -1.0;
421 *distance = d;
422 *position = origin + d * direction;
423 *user_value = 1;
424 return found;
425 }
426 break;
427 default:
428 throw NotImplementedException(A_FUNCINFO,"only quad face is implemented");
429 }
430 }
431 public:
432 RayTriangle3DIntersection m_triangle_intersector;
433};
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
440class BasicRayMeshIntersection
441: public BasicService
443{
444 public:
445
446 BasicRayMeshIntersection(const ServiceBuildInfo& sbi);
447 virtual ~BasicRayMeshIntersection() {}
448
449 public:
450
451 virtual void build(){}
452 virtual void compute(Real3ConstArrayView segments_position,
453 Real3ConstArrayView segments_direction,
454 Int32ConstArrayView segments_orig_face,
455 Int32ArrayView user_values,
456 Real3ArrayView intersections,
457 RealArrayView distances,
458 Int32ArrayView faces_local_id);
459
460 virtual void compute(IItemFamily* ray_family,
461 VariableParticleReal3& rays_position,
462 VariableParticleReal3& rays_direction,
463 VariableParticleInt32& rays_orig_face,
464 VariableParticleInt32& user_values,
465 VariableParticleReal3& intersections,
466 VariableParticleReal& distances,
467 VariableParticleInt32& rays_face);
468
469 virtual void setFaceIntersector(IRayFaceIntersector* intersector)
470 {
471 m_face_intersector = intersector;
472 }
474 {
475 return m_face_intersector;
476 }
477
478 public:
479
480 inline void _checkBoundingBox(Real3 p,Real3* ARCANE_RESTRICT min_bounding_box,
481 Real3* ARCANE_RESTRICT max_bounding_box)
482 {
483 if (p.x<min_bounding_box->x)
484 min_bounding_box->x = p.x;
485 if (p.y<min_bounding_box->y)
486 min_bounding_box->y = p.y;
487 if (p.z<min_bounding_box->z)
488 min_bounding_box->z = p.z;
489
490 if (p.x>max_bounding_box->x)
491 max_bounding_box->x = p.x;
492 if (p.y>max_bounding_box->y)
493 max_bounding_box->y = p.y;
494 if (p.z>max_bounding_box->z)
495 max_bounding_box->z = p.z;
496 }
497
498 private:
499 IRayFaceIntersector* m_face_intersector;
500};
501
502/*---------------------------------------------------------------------------*/
503/*---------------------------------------------------------------------------*/
504
505BasicRayMeshIntersection::
506BasicRayMeshIntersection(const ServiceBuildInfo& sbi)
507: BasicService(sbi)
508, m_face_intersector(0)
509{
510}
511
512/*---------------------------------------------------------------------------*/
513/*---------------------------------------------------------------------------*/
514
516compute(Real3ConstArrayView segments_position,
517 Real3ConstArrayView segments_direction,
518 Int32ConstArrayView segments_orig_face,
519 Int32ArrayView user_values,
520 Real3ArrayView segments_intersection,
521 RealArrayView segments_distance,
522 Int32ArrayView faces_local_id)
523{
524 IMesh* mesh = this->mesh();
525
526 bool is_3d = mesh->dimension()==3;
527 info() << "COMPUTE INTERSECTION!!";
528 FaceGroup outer_faces = mesh->outerFaces();
529 Integer nb_face = outer_faces.size();
530 Integer nb_segment = segments_position.size();
531 info() << "NB OUTER FACE=" << nb_face << " NB_SEGMENT=" << nb_segment;
532 VariableNodeReal3 nodes_coordinates(mesh->nodesCoordinates());
533 const Real max_value = 1.0e100;
534 const Real3 max_bb(max_value,max_value,max_value);
535 const Real3 min_bb(-max_value,-max_value,-max_value);
536
537 Real3 mesh_min_bounding_box(max_bb);
538 Real3 mesh_max_bounding_box(min_bb);
539 Integer max_face_local_id = mesh->faceFamily()->maxLocalId();
540 Real3UniqueArray faces_min_bb(max_face_local_id);
541 Real3UniqueArray faces_max_bb(max_face_local_id);
542
543 // Calcule les bounding box
544 {
545 ENUMERATE_FACE(iface,outer_faces){
546 Int32 lid = iface.localId();
547 Real3 face_max_bb(max_bb);
548 Real3 face_min_bb(min_bb);
549 for( NodeEnumerator inode((*iface).nodes()); inode.hasNext(); ++inode )
550 _checkBoundingBox(nodes_coordinates[inode],&face_min_bb,&face_max_bb);
551 _checkBoundingBox(face_min_bb,&mesh_min_bounding_box,&mesh_max_bounding_box);
552 _checkBoundingBox(face_max_bb,&mesh_min_bounding_box,&mesh_max_bounding_box);
553 //TODO: peut-etre ajouter un epsilon autour de le BB pour eviter
554 // les erreurs d'arrondi dans la determination de l'intersection
555 faces_min_bb[lid] = face_min_bb;
556 faces_max_bb[lid] = face_max_bb;
557 }
558 }
559
560 //RealArray segments_distance;
561 segments_distance.fill(max_value);
562 faces_local_id.fill(NULL_ITEM_LOCAL_ID);
563
564 if (!m_face_intersector)
565 m_face_intersector = new BasicRayFaceIntersector(traceMng());
566
567 Real3UniqueArray face_nodes;
568 for( Integer i=0; i<nb_segment; ++i ){
569 Real3 position = segments_position[i];
570 Real3 direction = segments_direction[i];
571 Int32 orig_face_local_id = segments_orig_face[i];
572 Real3 intersection;
573 Real distance = 1.0e100;
574 Int32 min_face_local_id = NULL_ITEM_LOCAL_ID;
575 Int32 user_value = 0;
576 ENUMERATE_FACE(iface,outer_faces){
577 const Face& face = *iface;
578 // On ne traite que ses propres faces
579 if (!face.isOwn())
580 continue;
581 Int32 lid = face.localId();
582 // En 3D, cherche si intersection avec la bounding box.
583 // s'il n'y en a pas, inutile d'aller plus loin.
584 bool is_bb = true;
585 if (is_3d)
586 is_bb = RayTriangle3DIntersection::checkBoundingBox(position,direction,faces_min_bb[lid],faces_max_bb[lid]);
587 if (!is_bb)
588 continue;
589 Integer nb_node = face.nbNode();
590 face_nodes.resize(nb_node);
591 for( NodeEnumerator inode(face.nodes()); inode.hasNext(); ++inode )
592 face_nodes[inode.index()] = nodes_coordinates[inode];
593 Real d = 0.0;
594 Real3 local_intersection;
595 Int32 uv = 0;
596 bool is_found = m_face_intersector->computeIntersection(position,direction,orig_face_local_id,lid,
597 face_nodes,&uv,&d,&local_intersection);
598 //if (i==15){
599 // for( Integer z=0; z<nb_node; ++z )
600 // info() << "FACE NODE lid=" << lid << " I=" << i << " v=" << face_nodes[z] << " d=" << d;
601 //}
602 //if (!is_bb)
603 //info() << "CHECK INTERSECTION: is_bb=" << is_bb << " " << is_found << '\n';
604 if (is_found && !is_bb)
605 fatal() << "Intersection found but no bounding box intersection";
606 if (is_found && d<distance){
607 distance = d;
608 min_face_local_id = lid;
609 intersection = local_intersection;
610 user_value = uv;
611 }
612 }
613 if (min_face_local_id==NULL_ITEM_LOCAL_ID)
614 distance = -1.0;
615 segments_distance[i] = distance;
616 segments_intersection[i] = intersection;
617 faces_local_id[i] = min_face_local_id;
618 user_values[i] = user_value;
619 }
620}
621
623{
624 Int32 contrib_owner;
625 Int32 owner;
626 Int32 local_id;
627 Int32 face_local_id;
628 Int32 orig_face_local_id;
629 Int32 user_value;
630 Real distance;
631 Real3POD intersection;
632};
633
634
635/*---------------------------------------------------------------------------*/
636/*---------------------------------------------------------------------------*/
637
639compute(IItemFamily* ray_family,
640 VariableParticleReal3& rays_position,
641 VariableParticleReal3& rays_direction,
642 VariableParticleInt32& rays_orig_face,
643 VariableParticleInt32& rays_user_value,
644 VariableParticleReal3& intersections,
645 VariableParticleReal& distances,
646 VariableParticleInt32& rays_face)
647{
648 // NOTE: rays_orig_face n'est pas utilisé.
649
650 IMesh* mesh = ray_family->mesh();
651 IParallelMng* pm = mesh->parallelMng();
652 Int32 my_rank = pm->commRank();
653 // Suppose que les rayons sont compactés
654 Integer nb_local_ray = ray_family->allItems().size();
655 //if (nb_local_ray!=ray_family->maxLocalId()){
656 //fatal() << "La famille de rayons doit être compactée nb=" << nb_local_ray
657 // << " max_id=" << ray_family->maxLocalId();
658 //}
659 Integer global_nb_ray = pm->reduce(Parallel::ReduceSum,nb_local_ray);
660 if (global_nb_ray==0)
661 return;
662 info() << "LOCAL_NB_RAY=" << nb_local_ray << " GLOBAL=" << global_nb_ray;
663
664 // Recopie dans un tableau local les informations d'entrée.
665 // Cela est toujours nécessaire car les particules ne sont pas forcément
666 // compactées et il peut y avoir des trous dans la numérotation.
667 Real3UniqueArray local_positions(nb_local_ray);
668 Real3UniqueArray local_directions(nb_local_ray);
669
670 ENUMERATE_PARTICLE(iitem,ray_family->allItems()){
671 Integer index = iitem.index();
672 //local_ids[index] = iitem.localId();
673 //unique_ids[index] = (*iitem).uniqueId();
674 local_positions[index] = rays_position[iitem];
675 local_directions[index] = rays_direction[iitem];
676 }
677
678 if (pm->isParallel()){
679
680 Int32UniqueArray local_ids(nb_local_ray);
681 Int64UniqueArray unique_ids(nb_local_ray);
682 ENUMERATE_ITEM(iitem,ray_family->allItems()){
683 Integer index = iitem.index();
684 local_ids[index] = iitem.localId();
685 unique_ids[index] = (*iitem).uniqueId();
686 }
687
688 // En parallèle, pour l'instant récupère les rayons des autres processeurs
689
690 Real3UniqueArray all_positions;
691 pm->allGatherVariable(local_positions,all_positions);
692 Real3UniqueArray all_directions;
693 pm->allGatherVariable(local_directions,all_directions);
694
695 Int32UniqueArray local_owners(nb_local_ray);
696 local_owners.fill(my_rank);
697
698 Int32UniqueArray all_owners;
699 pm->allGatherVariable(local_owners,all_owners);
700 Int32UniqueArray all_local_ids;
701 pm->allGatherVariable(local_ids,all_local_ids);
702 Int64UniqueArray all_unique_ids;
703 pm->allGatherVariable(unique_ids,all_unique_ids);
704
705 Int32UniqueArray all_user_values(global_nb_ray);
706 Int32UniqueArray all_orig_faces(global_nb_ray,NULL_ITEM_LOCAL_ID);
707 RealUniqueArray all_distances(global_nb_ray);
708 Real3UniqueArray all_intersections(global_nb_ray);
709 Int32UniqueArray all_faces(global_nb_ray);
710 // Mettre à (-1) les faces dont je ne suis pas le propriétaire
711 for( Integer z=0, zn=all_orig_faces.size(); z<zn; ++z ){
712 if (all_owners[z]!=my_rank)
713 all_orig_faces[z] = NULL_ITEM_LOCAL_ID;
714 }
715 compute(all_positions,all_directions,all_orig_faces,all_user_values,all_intersections,all_distances,all_faces);
716 /*for( Integer i=0; i<global_nb_ray; ++i ){
717 info() << "RAY I=" << i << " uid=" << all_unique_ids[i] << " lid=" << all_local_ids[i]
718 << " owner=" << all_owners[i] << " position=" << all_positions[i]
719 << " direction=" << all_directions[i] << " distance=" << all_distances[i]
720 << " face=" << all_faces[i];
721 }*/
722 {
723 UniqueArray<FoundInfo> founds_info;
724
725 for( Integer i=0; i<global_nb_ray; ++i ){
726 Int32 face_lid = all_faces[i];
727 if (face_lid==NULL_ITEM_LOCAL_ID)
728 continue;
729 FoundInfo fi;
730 fi.contrib_owner = my_rank;
731 fi.owner = all_owners[i];
732 fi.local_id = all_local_ids[i];
733 fi.face_local_id = all_faces[i];
734 fi.orig_face_local_id = all_orig_faces[i];
735 fi.user_value = all_user_values[i];
736 fi.intersection = all_intersections[i];
737 fi.distance = all_distances[i];
738 founds_info.add(fi);
739 }
740 info() << "NB_FOUND=" << founds_info.size();
741 //Array<FoundInfo> global_founds_info;
742 ByteUniqueArray global_founds_info_bytes;
743 Integer finfo_byte_size = arcaneCheckArraySize(founds_info.size()*sizeof(FoundInfo));
744 ByteConstArrayView local_fi(finfo_byte_size,(const Byte*)founds_info.data());
745 pm->allGatherVariable(local_fi,global_founds_info_bytes);
746 Integer gfi_byte_size = arcaneCheckArraySize(global_founds_info_bytes.size()/sizeof(FoundInfo));
747 ConstArrayView<FoundInfo> global_founds_info(gfi_byte_size,(const FoundInfo*)global_founds_info_bytes.data());
748 Integer nb_total_found = global_founds_info.size();
749 ParticleInfoListView rays(ray_family);
750 rays_face.fill(NULL_ITEM_LOCAL_ID);
751 distances.fill(0.0);
752 VariableItemInt32& rays_new_owner = ray_family->itemsNewOwner();
753 rays_new_owner.fill(my_rank);
754 for( Integer i=0; i<nb_total_found; ++i ){
755 const FoundInfo& fi = global_founds_info[i];
756 Int32 owner = fi.owner;
757 // Il ne faut traiter que ses propres rayons
758 if (owner!=my_rank)
759 continue;
760 Int32 local_id = fi.local_id;
761 Particle ray = rays[local_id];
762 Real distance = fi.distance;
763 if ((rays_face[ray]==NULL_ITEM_LOCAL_ID) || distance<distances[ray]){
764 distances[ray] = distance;
765 intersections[ray] = Real3(fi.intersection.x,fi.intersection.y,fi.intersection.z);
766 rays_face[ray] = fi.face_local_id;
767 rays_user_value[ray] = fi.user_value;
768 rays_new_owner[ray] = fi.contrib_owner;
769 //info() << "SET RAY uid=" << ray.uniqueId() << " distance=" << distance << " new_owner=" << fi.contrib_owner;
770 }
771 /*info() << "GLOBAL RAY I=" << i << " uid=" << ray.uniqueId() << " lid=" << fi.local_id
772 << " owner=" << fi.owner
773 << " distance=" << fi.distance
774 << " contrib_owner=" << fi.contrib_owner
775 << " face=" << fi.face_local_id
776 << " new_owner=" << rays_new_owner[ray];*/
777 }
778 ray_family->toParticleFamily()->exchangeParticles();
779 }
780 }
781 else{
782
783 Int32UniqueArray orig_faces(nb_local_ray);
784 Int32UniqueArray user_values(nb_local_ray);
785
786 ENUMERATE_PARTICLE(iitem,ray_family->allItems()){
787 Integer index = iitem.index();
788 orig_faces[index] = rays_orig_face[iitem];
789 user_values[index] = rays_user_value[iitem];
790 }
791
792 Real3UniqueArray out_intersections(nb_local_ray);
793 RealUniqueArray out_distances(nb_local_ray);
794 Int32UniqueArray out_faces(nb_local_ray);
795
796 compute(local_positions,local_directions,orig_faces,user_values,out_intersections,out_distances,out_faces);
797
798 // Recopie en sortie les valeurs dans les variables correspondantes.
799 ENUMERATE_PARTICLE(iitem,ray_family->allItems()){
800 Integer index = iitem.index();
801 intersections[iitem] = out_intersections[index];
802 distances[iitem] = out_distances[index];
803 rays_face[iitem] = out_faces[index];
804 }
805
806 }
807
808 // Pour test, écrit les rayons et leur point d'impact.
809 {
810 Integer nb_new_ray = ray_family->nbItem();
811 RealUniqueArray local_distances(nb_new_ray);
812 local_directions.resize(nb_new_ray);
813 local_positions.resize(nb_new_ray);
814 ENUMERATE_PARTICLE(iitem,ray_family->allItems()){
815 Integer index = iitem.index();
816 local_distances[index] = distances[iitem];
817 local_directions[index] = rays_direction[iitem];
818 local_positions[index] = rays_position[iitem];
819 }
820 }
821
822}
823
824/*---------------------------------------------------------------------------*/
825/*---------------------------------------------------------------------------*/
826
829
830/*---------------------------------------------------------------------------*/
831/*---------------------------------------------------------------------------*/
832
833} // End namespace Arcane
834
835/*---------------------------------------------------------------------------*/
836/*---------------------------------------------------------------------------*/
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_PARTICLE(name, group)
Enumérateur générique d'un groupe de particules.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
Integer size() const
Nombre d'éléments du vecteur.
void fill(const T &o) noexcept
Remplit le tableau avec la valeur o.
void fill(const DataType &data)
Remplissage du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
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)
Calcul l'intersection entre un rayon et une face.
Service basique de calcul d'intersection entre segments et maillage.
virtual void build()
Construction de niveau build du service.
virtual void setFaceIntersector(IRayFaceIntersector *intersector)
Positionne le callback d'intersection.
virtual IRayFaceIntersector * faceIntersector()
Intersecteur utilisé (0 si aucun spécifié)
virtual void compute(Real3ConstArrayView segments_position, Real3ConstArrayView segments_direction, Int32ConstArrayView segments_orig_face, Int32ArrayView user_values, Real3ArrayView intersections, RealArrayView distances, Int32ArrayView faces_local_id)
Calcule l'intersection.
Classe de base de service lié à un sous-domaine.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Face d'une maille.
Definition Item.h:964
Exception lorsqu'une erreur fatale est survenue.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual IParticleFamily * toParticleFamily()=0
Retourne l'interface de la famille de particule de cette famille.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual IMesh * mesh() const =0
Maillage associé
virtual Integer nbItem() const =0
Nombre d'entités.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable contenant le numéro du nouveau sous-domaine propriétaire de l'entité.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
virtual void exchangeParticles()=0
Échange des entités.
Interface générique du calcul de l'intersection d'un rayon avec une face.
Calcul de l'intersection entre un ensemble de segments et la surface d'un maillage.
Interface du gestionnaire de traces.
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:794
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
constexpr bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Exception lorsqu'une fonction n'est pas implémentée.
Vue sur les informations des particules.
Particule.
Definition Item.h:1423
Calcul l'intersection d'un rayon avec un ensemble de triangles en 3D.
void setRays(Real3ConstArrayView origins, Real3ConstArrayView directions)
Position la liste des rayons dont on souhaite calculer l'intersection.
Real checkIntersection(Real3 origin, Real3 direction, Real3 p0, Real3 p1, Real3 p2)
Calcul l'intersection de la demi-droite [origin,direction) avec le triangle (p0,p1,...
void compute()
Calcul l'intersection de chaque rayon avec la liste des triangles. Si un rayon intersecte plusieurs t...
void setTriangles(Real3ConstArrayView coordinates, Int32ConstArrayView indexes)
Positionne la liste des triangles dont on souhaite calculer l'intersection avec les rayons....
Int32ConstArrayView intersectedTriangleIndexes()
Indices des triangles intersectés. Indice dans le tableau donnée par setTriangles() du triangle inter...
RealConstArrayView distances()
Distance de l'origine d'un rayon à son point d'intersection. Distance (exprimée relativivement à la n...
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
__host__ __device__ Real dot(Real2 u, Real2 v)
Produit scalaire de u par v dans .
Definition MathUtils.h:96
__host__ __device__ Real3 vecMul(Real3 u, Real3 v)
Produit vectoriel de u par v. dans .
Definition MathUtils.h:52
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemEnumeratorT< Node > NodeEnumerator
Enumérateurs sur des noeuds.
Definition ItemTypes.h:254
MeshVariableScalarRefT< Particle, Real3 > VariableParticleReal3
Grandeur particulaire de type coordonnées.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Particle, Int32 > VariableParticleInt32
Grandeur particulaire de type entier 32 bits.
MeshVariableScalarRefT< Particle, Real > VariableParticleReal
Grandeur particulaire de type réel.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
@ ReduceSum
Somme des valeurs.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
ConstArrayView< Real3 > Real3ConstArrayView
Equivalent C d'un tableau à une dimension de Real3.
Definition UtilsTypes.h:496
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:339
ArrayView< Real3 > Real3ArrayView
Equivalent C d'un tableau à une dimension de Real3.
Definition UtilsTypes.h:467
Int32 Integer
Type représentant un entier.
UniqueArray< Real3 > Real3UniqueArray
Tableau dynamique à une dimension de vecteurs de rang 3.
Definition UtilsTypes.h:363
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:482
UniqueArray< Byte > ByteUniqueArray
Tableau dynamique à une dimension de caractères.
Definition UtilsTypes.h:335
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:453
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:349
double Real
Type représentant un réel.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:476
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:459
std::int32_t Int32
Type entier signé sur 32 bits.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:488
Real y
deuxième composante du triplet
Definition Real3.h:36
Real z
troisième composante du triplet
Definition Real3.h:37
Real x
première composante du triplet
Definition Real3.h:35