Arcane  v3.15.3.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
BasicRayMeshIntersection.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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-2023 */
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/ISubDomain.h"
21#include "arcane/IMesh.h"
22#include "arcane/IItemFamily.h"
23#include "arcane/Item.h"
24#include "arcane/BasicService.h"
25#include "arcane/FactoryService.h"
26#include "arcane/ItemPrinter.h"
27#include "arcane/ItemGroup.h"
28#include "arcane/VariableTypes.h"
29#include "arcane/IRayMeshIntersection.h"
30#include "arcane/IParallelMng.h"
31#include "arcane/IParticleFamily.h"
32
33#include "arcane_packages.h"
34
35#ifdef ARCANE_HAS_PACKAGE_LIMA
36#include <Lima/lima++.h>
37#define GLOBAL_HAS_LIMA true
38#else
39#define GLOBAL_HAS_LIMA false
40#endif
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
45namespace
46{
47const bool global_has_lima = GLOBAL_HAS_LIMA;
48}
49
50namespace Arcane
51{
52
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55/*!
56 * \brief Calcul l'intersection d'un rayon avec un ensemble de triangles en 3D.
57 *
58 * Un rayon est une demi-droite et est défini par son origine et sa direction.
59 * Il faut positionner les rayons (via setRays()) et la liste des triangles
60 * (via setTriangles()) puis appeler la méthode compute(). En retour, on
61 * peut récupérer pour chaque rayon la distance (distances()) et le triangle intersecté
62 * (intersectedTriangleIndexes()).
63 *
64 * Les vues passées en argument (setRays() et setTriangles()) ne doivent pas être
65 * modifiées tant que l'instance existe.
66 */
68: public TraceAccessor
69{
70 public:
72 : TraceAccessor(tm)
73 {
74 }
75
76 /*!
77 * \brief Position la liste des rayons dont on souhaite calculer l'intersection.
78 */
80 {
81 m_rays_origin = origins;
82 m_rays_direction = directions;
83 }
84 /*!
85 * \brief Positionne la liste des triangles dont on souhaite calculer l'intersection
86 * avec les rayons. Le tableau \a indexes contient pour chaque triangle les indices
87 * dans le tableau \a coordinates de chaque sommet. Par exemple,
88 * indexes[0..2] contient les indices des sommets du 1er triangle, indexes[3..5]
89 * ceux du second.
90 */
92 {
93 m_triangles_coordinates = coordinates;
94 m_triangles_indexes = indexes;
95 }
96 /*!
97 * \brief Calcul l'intersection de chaque rayon avec la liste des triangles.
98 * Si un rayon intersecte plusieurs triangles, on concerve celui dont
99 * la distance par rapport à l'origine du rayon est la plus petite.
100 */
101 void compute();
102 /*!
103 * \brief Distance de l'origine d'un rayon à son point d'intersection.
104 * Distance (exprimée relativivement à la norme de \a directions)
105 * du point d'intersection d'un rayon par rapport à son origine.
106 * Pour le rayon \a i, son point d'intersection est donc donnée
107 * par la formule (origins[i] + distances[i]*directions[i]).
108 * La distance est négative si le rayon n'intersecte aucun triangle.
109 * Ce tableau est remplit lors de l'appel à compute().
110 */
112 {
113 return m_distances;
114 }
115
116 /*!
117 * \brief Indices des triangles intersectés.
118 * Indice dans le tableau donnée par \a setTriangles() du triangle
119 * intersecté par chaque rayon. Cet indice vaut (-1) si un rayon
120 * n'intersecte pas un triangle. Ce tableau est remplit lors
121 * de l'appel à compute().
122 */
124 {
125 return m_intersected_triangle_indexes;
126 }
127
128 Real checkIntersection(Real3 origin,Real3 direction,Real3 p0,Real3 p1,Real3 p2);
129
130 static bool checkBoundingBox(Real3 origin,Real3 direction,Real3 box_min,Real3 box_max);
131
132 private:
133
134 void _compute2(Int32 triangle_id,Real3 p0,Real3 p1,Real3 p2);
135
136 private:
137
138 Real3ConstArrayView m_rays_origin;
139 Real3ConstArrayView m_rays_direction;
140 Real3ConstArrayView m_triangles_coordinates;
141 Int32ConstArrayView m_triangles_indexes;
142
143 RealUniqueArray m_distances;
144 Int32UniqueArray m_intersected_triangle_indexes;
145};
146
147/*---------------------------------------------------------------------------*/
148/*---------------------------------------------------------------------------*/
149
151compute()
152{
153 Integer nb_ray = m_rays_origin.size();
154 m_distances.resize(nb_ray);
155 m_distances.fill(1.0e100);
156 m_intersected_triangle_indexes.resize(nb_ray);
157 m_intersected_triangle_indexes.fill(-1);
158 Integer nb_index = m_triangles_indexes.size();
159 if ((nb_index%3)!=0)
160 throw FatalErrorException(A_FUNCINFO,"bad triangle_index count (({0}) % 3)!=0");
161 Integer nb_triangle = nb_index / 3;
162 info() << "COMPUTE RAY INTERSECTION nb_ray=" << nb_ray
163 << " nb_triangle=" << nb_triangle;
164
165 for( Integer i=0; i<nb_triangle; ++i ){
166 Real3 p0 = m_triangles_coordinates[m_triangles_indexes[(i*3)]];
167 Real3 p1 = m_triangles_coordinates[m_triangles_indexes[(i*3)+1]];
168 Real3 p2 = m_triangles_coordinates[m_triangles_indexes[(i*3)+2]];
169 _compute2(i,p0,p1,p2);
170 }
171
172 for( Integer i=0; i<nb_ray; ++i ){
173 Int32 tid = m_intersected_triangle_indexes[i];
174 if (tid==(-1))
175 m_distances[i] = -1.0;
176 }
177}
178
179/*---------------------------------------------------------------------------*/
180/*---------------------------------------------------------------------------*/
181
182void RayTriangle3DIntersection::
183_compute2(Int32 triangle_id,Real3 p0,Real3 p1,Real3 p2)
184{
185 Integer nb_ray = m_rays_origin.size();
186 for( Integer i=0; i<nb_ray; ++i ){
187 Real t = checkIntersection(m_rays_origin[i],m_rays_direction[i],p0,p1,p2);
188 if (t>=0.0){
189 info() << "Segment " << i << " intersect triangle " << triangle_id << " T=" << t;
190 if (t<m_distances[i]){
191 m_distances[i] = t;
192 m_intersected_triangle_indexes[i] = triangle_id;
193 info() << "Get this triangle";
194 }
195 }
196 }
197}
198
199/*---------------------------------------------------------------------------*/
200/*---------------------------------------------------------------------------*/
201/*!
202 * \brief Calcul l'intersection de la demi-droite [origin,direction)
203 * avec le triangle (p0,p1,p2).
204 *
205 * La direction n'a pas besoin d'être normalisée.
206 *
207 * La position du point d'intersection est P = origin + t * direction
208 * où \a t est la valeur retournée par cette fonction. Cette valeur
209 * est négative si si aucun point d'intersection n'est trouvé.
210 */
213 Real3 direction,
215{
216 // Cette routine s'inspire du code de la bibliothèque WildMagic
217 // dont la licence est ci-dessous.
218
219 // Wild Magic Source Code
220 // David Eberly
221 // http://www.geometrictools.com
222 // Copyright (c) 1998-2009
223 //
224 // This library is free software; you can redistribute it and/or modify it
225 // under the terms of the GNU Lesser General Public License as published by
226 // the Free Software Foundation; either version 2.1 of the License, or (at
227 // your option) any later version. The license is available for reading at
228 // either of the locations:
229 // http://www.gnu.org/copyleft/lgpl.html
230 // http://www.geometrictools.com/License/WildMagicLicense.pdf
231 //
232
233
234 Real ZERO_TOLERANCE = 1.0e-14;
235 // compute the offset origin, edges, and normal
236 Real3 kDiff = origin - p0;
237 Real3 kEdge1 = p1 - p0;
238 Real3 kEdge2 = p2 - p0;
240
241 Real fDdN = math::dot(direction,kNormal);
242 Real fSign;
243 if (fDdN > ZERO_TOLERANCE)
244 {
245 fSign = (Real)1.0;
246 }
247 else if (fDdN < -ZERO_TOLERANCE)
248 {
249 fSign = (Real)-1.0;
250 fDdN = -fDdN;
251 }
252 else
253 {
254 // Segment and triangle are parallel, call it a "no intersection"
255 // even if the segment does intersect.
256 return (-1.0);
257 }
258
259 Real fDdQxE2 = fSign*math::dot(direction,math::vecMul(kDiff,kEdge2));
260 if (fDdQxE2 >= (Real)0.0)
261 {
262 Real fDdE1xQ = fSign*math::dot(direction,math::vecMul(kEdge1,kDiff));
263 if (fDdE1xQ >= (Real)0.0)
264 {
265 Real diff = fDdN-(fDdQxE2 + fDdE1xQ);
266 // L'epsilon sert si le segment traverse par la face à proximité
267 // d'une des arêtes de la face. Dans ce cas, on considère qu'il
268 // y a intersection. Sans cela, à cause des arrondis numériques,
269 // un segment pourrait traverser le maillage en passant par une
270 // arête entre deux faces sans intersecter ces dernières.
271 if (diff>=0.0 || diff>-ZERO_TOLERANCE)
272 {
273 // line intersects triangle, check if segment does
275
276 // Comme il s'agit d'une demi-droite et pas d'un segment,
277 // il y a toujours intersection si \a t est positif.
278#if 0
279 Real fExtDdN = m_pkSegment->Extent*fDdN;
280 if (-fExtDdN <= fQdN && fQdN <= fExtDdN)
281 {
282 // segment intersects triangle
283 return true;
284 }
285#endif
286 Real fInv = ((Real)1.0)/fDdN;
287 Real t = fQdN*fInv;
288 //Real b1 = fDdQxE2*fInv;
289 //Real b2 = fDdE1xQ*fInv;
290 //Real b0 = (Real)1.0 - b1 - b2;
291 // P = origin + t*direction = b0*V0 + b1*V1 + b2*V2
292 //info() << "** INTERSECT POS=" << b0 << " y=" << b1 << " z=" << b2 << " T=" << t;
293 //Real intersect_p = origin + t*direction;
294 return t;
295
296 // else: |t| > extent, no intersection
297 }
298 // else: b1+b2 > 1, no intersection
299 }
300 // else: b2 < 0, no intersection
301 }
302 // else: b1 < 0, no intersection
303
304 return (-1.0);
305}
306
307/*---------------------------------------------------------------------------*/
308/*---------------------------------------------------------------------------*/
309
310bool RayTriangle3DIntersection::
311checkBoundingBox(Real3 origin,Real3 direction,Real3 box_min,Real3 box_max)
312{
314 Real afWdU[3], afAWdU[3], afDdU[3], afADdU[3], afAWxDdU[3], fRhs;
315
317 Real3 Axis[3];
318 //Axis[0].x = box_max.x - box_min.x;
319 //Axis[1].y = box_max.y - box_min.y;
320 //Axis[2].z = box_max.z - box_min.z;
321 Axis[0] = Real3(1.0,0.0,0.0);
322 Axis[1] = Real3(0.0,1.0,0.0);
323 Axis[2] = Real3(0.0,0.0,1.0);
324 Real Extent[3];
325 Extent[0] = box_max.x - box_min.x;
326 Extent[1] = box_max.y - box_min.y;
327 Extent[2] = box_max.z - box_min.z;
328
329 afWdU[0] = math::dot(direction,Axis[0]);
330 afAWdU[0] = math::abs(afWdU[0]);
331 afDdU[0] = math::dot(kDiff,Axis[0]);
332 afADdU[0] = math::abs(afDdU[0]);
333 if (afADdU[0] > Extent[0] && afDdU[0]*afWdU[0] >= (Real)0.0)
334 {
335 return false;
336 }
337
338 afWdU[1] = math::dot(direction,Axis[1]);
339 afAWdU[1] = math::abs(afWdU[1]);
340 afDdU[1] = math::dot(kDiff,Axis[1]);
341 afADdU[1] = math::abs(afDdU[1]);
342 if (afADdU[1] > Extent[1] && afDdU[1]*afWdU[1] >= (Real)0.0)
343 {
344 return false;
345 }
346
347 afWdU[2] = math::dot(direction,Axis[2]);
348 afAWdU[2] = math::abs(afWdU[2]);
349 afDdU[2] = math::dot(kDiff,Axis[2]);
350 afADdU[2] = math::abs(afDdU[2]);
351 if (afADdU[2] > Extent[2] && afDdU[2]*afWdU[2] >= (Real)0.0)
352 {
353 return false;
354 }
355
356 Real3 kWxD = math::vecMul(direction,kDiff);
357
358 afAWxDdU[0] = math::abs(math::dot(kWxD,Axis[0]));
359 fRhs = Extent[1]*afAWdU[2] + Extent[2]*afAWdU[1];
360 if (afAWxDdU[0] > fRhs)
361 {
362 return false;
363 }
364
365 afAWxDdU[1] = math::abs(math::dot(kWxD,Axis[1]));
366 fRhs = Extent[0]*afAWdU[2] + Extent[2]*afAWdU[0];
367 if (afAWxDdU[1] > fRhs)
368 {
369 return false;
370 }
371
372 afAWxDdU[2] = math::abs(math::dot(kWxD,Axis[2]));
373 fRhs = Extent[0]*afAWdU[1] + Extent[1]*afAWdU[0];
374 if (afAWxDdU[2] > fRhs)
375 {
376 return false;
377 }
378
379 return true;
380}
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
386: public IRayFaceIntersector
387{
388 public:
390 : m_triangle_intersector(tm)
391 {
392 }
393 public:
395 Int32 orig_face_local_id,
396 Int32 face_local_id,
398 Int32* user_value,
399 Real* distance,Real3* position)
400 {
401 ARCANE_UNUSED(orig_face_local_id);
402 ARCANE_UNUSED(face_local_id);
403
404 Integer nb_node = face_nodes.size();
405 switch(nb_node){
406 case 4:
407 {
408 Real3 center = (face_nodes[0] + face_nodes[1] + face_nodes[2] + face_nodes[3]) / 4.0;
409 Real d0 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[0],face_nodes[1]);
410 Real d1 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[1],face_nodes[2]);
411 Real d2 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[2],face_nodes[3]);
412 Real d3 = m_triangle_intersector.checkIntersection(origin,direction,center,face_nodes[3],face_nodes[0]);
413 Real d = 1.0e100;
414 bool found = false;
415 if (d0>=0.0 && d0<d){
416 found = true;
417 d = d0;
418 }
419 if (d1>=0.0 && d1<d){
420 found = true;
421 d = d1;
422 }
423 if (d2>=0.0 && d2<d){
424 found = true;
425 d = d2;
426 }
427 if (d3>=0.0 && d3<d){
428 found = true;
429 d = d3;
430 }
431 if (!found)
432 d = -1.0;
433 *distance = d;
434 *position = origin + d * direction;
435 *user_value = 1;
436 return found;
437 }
438 break;
439 default:
440 throw NotImplementedException(A_FUNCINFO,"only quad face is implemented");
441 }
442 }
443 public:
444 RayTriangle3DIntersection m_triangle_intersector;
445};
446
447/*---------------------------------------------------------------------------*/
448/*---------------------------------------------------------------------------*/
449/*!
450 * \brief Service basique de calcul d'intersection entre segments et maillage.
451 */
453: public BasicService
455{
456 public:
457
459 virtual ~BasicRayMeshIntersection() {}
460
461 public:
462
463 virtual void build(){}
469 RealArrayView distances,
471
472 virtual void compute(IItemFamily* ray_family,
478 VariableParticleReal& distances,
480
482 {
483 m_face_intersector = intersector;
484 }
486 {
487 return m_face_intersector;
488 }
489
490 public:
491
492 inline void _checkBoundingBox(Real3 p,Real3* ARCANE_RESTRICT min_bounding_box,
493 Real3* ARCANE_RESTRICT max_bounding_box)
494 {
495 if (p.x<min_bounding_box->x)
496 min_bounding_box->x = p.x;
497 if (p.y<min_bounding_box->y)
498 min_bounding_box->y = p.y;
499 if (p.z<min_bounding_box->z)
500 min_bounding_box->z = p.z;
501
502 if (p.x>max_bounding_box->x)
503 max_bounding_box->x = p.x;
504 if (p.y>max_bounding_box->y)
505 max_bounding_box->y = p.y;
506 if (p.z>max_bounding_box->z)
507 max_bounding_box->z = p.z;
508 }
509
510 void _writeSegments(Int32 rank,
511 Real3ConstArrayView positions,
512 Real3ConstArrayView directions,
513 RealConstArrayView distances);
514 private:
515 IRayFaceIntersector* m_face_intersector;
516};
517
518/*---------------------------------------------------------------------------*/
519/*---------------------------------------------------------------------------*/
520
521BasicRayMeshIntersection::
522BasicRayMeshIntersection(const ServiceBuildInfo& sbi)
523: BasicService(sbi)
524, m_face_intersector(0)
525{
526}
527
528/*---------------------------------------------------------------------------*/
529/*---------------------------------------------------------------------------*/
530
539{
540 IMesh* mesh = this->mesh();
541
542 bool is_3d = mesh->dimension()==3;
543 info() << "COMPUTE INTERSECTION!!";
545 Integer nb_face = outer_faces.size();
546 Integer nb_segment = segments_position.size();
547 info() << "NB OUTER FACE=" << nb_face << " NB_SEGMENT=" << nb_segment;
549 const Real max_value = 1.0e100;
552
555 Integer max_face_local_id = mesh->faceFamily()->maxLocalId();
558
559 // Calcule les bounding box
560 {
562 Int32 lid = iface.localId();
565 for( NodeEnumerator inode((*iface).nodes()); inode.hasNext(); ++inode )
566 _checkBoundingBox(nodes_coordinates[inode],&face_min_bb,&face_max_bb);
569 //TODO: peut-etre ajouter un epsilon autour de le BB pour eviter
570 // les erreurs d'arrondi dans la determination de l'intersection
573 }
574 }
575
576 //RealArray segments_distance;
578 faces_local_id.fill(NULL_ITEM_LOCAL_ID);
579
580 if (!m_face_intersector)
581 m_face_intersector = new BasicRayFaceIntersector(traceMng());
582
584 for( Integer i=0; i<nb_segment; ++i ){
585 Real3 position = segments_position[i];
586 Real3 direction = segments_direction[i];
587 Int32 orig_face_local_id = segments_orig_face[i];
588 Real3 intersection;
589 Real distance = 1.0e100;
590 Int32 min_face_local_id = NULL_ITEM_LOCAL_ID;
591 Int32 user_value = 0;
593 const Face& face = *iface;
594 // On ne traite que ses propres faces
595 if (!face.isOwn())
596 continue;
597 Int32 lid = face.localId();
598 // En 3D, cherche si intersection avec la bounding box.
599 // s'il n'y en a pas, inutile d'aller plus loin.
600 bool is_bb = true;
601 if (is_3d)
602 is_bb = RayTriangle3DIntersection::checkBoundingBox(position,direction,faces_min_bb[lid],faces_max_bb[lid]);
603 if (!is_bb)
604 continue;
605 Integer nb_node = face.nbNode();
606 face_nodes.resize(nb_node);
607 for( NodeEnumerator inode(face.nodes()); inode.hasNext(); ++inode )
609 Real d = 0.0;
611 Int32 uv = 0;
612 bool is_found = m_face_intersector->computeIntersection(position,direction,orig_face_local_id,lid,
614 //if (i==15){
615 // for( Integer z=0; z<nb_node; ++z )
616 // info() << "FACE NODE lid=" << lid << " I=" << i << " v=" << face_nodes[z] << " d=" << d;
617 //}
618 //if (!is_bb)
619 //info() << "CHECK INTERSECTION: is_bb=" << is_bb << " " << is_found << '\n';
620 if (is_found && !is_bb)
621 fatal() << "Intersection found but no bounding box intersection";
622 if (is_found && d<distance){
623 distance = d;
625 intersection = local_intersection;
626 user_value = uv;
627 }
628 }
629 if (min_face_local_id==NULL_ITEM_LOCAL_ID)
630 distance = -1.0;
631 segments_distance[i] = distance;
632 segments_intersection[i] = intersection;
634 user_values[i] = user_value;
635 }
636}
637
639{
640 Int32 contrib_owner;
641 Int32 owner;
642 Int32 local_id;
643 Int32 face_local_id;
644 Int32 orig_face_local_id;
645 Int32 user_value;
646 Real distance;
647 Real3POD intersection;
648};
649
650
651/*---------------------------------------------------------------------------*/
652/*---------------------------------------------------------------------------*/
653
661 VariableParticleReal& distances,
663{
664 // NOTE: rays_orig_face n'est pas utilisé.
665
666 IMesh* mesh = ray_family->mesh();
667 IParallelMng* pm = mesh->parallelMng();
668 Int32 my_rank = pm->commRank();
669 // Suppose que les rayons sont compactés
670 Integer nb_local_ray = ray_family->allItems().size();
671 //if (nb_local_ray!=ray_family->maxLocalId()){
672 //fatal() << "La famille de rayons doit être compactée nb=" << nb_local_ray
673 // << " max_id=" << ray_family->maxLocalId();
674 //}
675 Integer global_nb_ray = pm->reduce(Parallel::ReduceSum,nb_local_ray);
676 if (global_nb_ray==0)
677 return;
678 info() << "LOCAL_NB_RAY=" << nb_local_ray << " GLOBAL=" << global_nb_ray;
679
680 // Recopie dans un tableau local les informations d'entrée.
681 // Cela est toujours nécessaire car les particules ne sont pas forcément
682 // compactées et il peut y avoir des trous dans la numérotation.
685
687 Integer index = iitem.index();
688 //local_ids[index] = iitem.localId();
689 //unique_ids[index] = (*iitem).uniqueId();
692 }
693
694 if (pm->isParallel()){
695
698 ENUMERATE_ITEM(iitem,ray_family->allItems()){
699 Integer index = iitem.index();
700 local_ids[index] = iitem.localId();
701 unique_ids[index] = (*iitem).uniqueId();
702 }
703
704 // En parallèle, pour l'instant récupère les rayons des autres processeurs
705
707 pm->allGatherVariable(local_positions,all_positions);
709 pm->allGatherVariable(local_directions,all_directions);
710
712 local_owners.fill(my_rank);
713
715 pm->allGatherVariable(local_owners,all_owners);
717 pm->allGatherVariable(local_ids,all_local_ids);
719 pm->allGatherVariable(unique_ids,all_unique_ids);
720
726 // Mettre à (-1) les faces dont je ne suis pas le propriétaire
727 for( Integer z=0, zn=all_orig_faces.size(); z<zn; ++z ){
728 if (all_owners[z]!=my_rank)
729 all_orig_faces[z] = NULL_ITEM_LOCAL_ID;
730 }
732 /*for( Integer i=0; i<global_nb_ray; ++i ){
733 info() << "RAY I=" << i << " uid=" << all_unique_ids[i] << " lid=" << all_local_ids[i]
734 << " owner=" << all_owners[i] << " position=" << all_positions[i]
735 << " direction=" << all_directions[i] << " distance=" << all_distances[i]
736 << " face=" << all_faces[i];
737 }*/
738 {
740
741 for( Integer i=0; i<global_nb_ray; ++i ){
742 Int32 face_lid = all_faces[i];
743 if (face_lid==NULL_ITEM_LOCAL_ID)
744 continue;
746 fi.contrib_owner = my_rank;
747 fi.owner = all_owners[i];
748 fi.local_id = all_local_ids[i];
749 fi.face_local_id = all_faces[i];
750 fi.orig_face_local_id = all_orig_faces[i];
751 fi.user_value = all_user_values[i];
752 fi.intersection = all_intersections[i];
753 fi.distance = all_distances[i];
754 founds_info.add(fi);
755 }
756 info() << "NB_FOUND=" << founds_info.size();
757 //Array<FoundInfo> global_founds_info;
761 pm->allGatherVariable(local_fi,global_founds_info_bytes);
764 Integer nb_total_found = global_founds_info.size();
766 rays_face.fill(NULL_ITEM_LOCAL_ID);
767 distances.fill(0.0);
768 VariableItemInt32& rays_new_owner = ray_family->itemsNewOwner();
770 for( Integer i=0; i<nb_total_found; ++i ){
771 const FoundInfo& fi = global_founds_info[i];
772 Int32 owner = fi.owner;
773 // Il ne faut traiter que ses propres rayons
774 if (owner!=my_rank)
775 continue;
776 Int32 local_id = fi.local_id;
777 Particle ray = rays[local_id];
778 Real distance = fi.distance;
779 if ((rays_face[ray]==NULL_ITEM_LOCAL_ID) || distance<distances[ray]){
780 distances[ray] = distance;
781 intersections[ray] = Real3(fi.intersection.x,fi.intersection.y,fi.intersection.z);
782 rays_face[ray] = fi.face_local_id;
783 rays_user_value[ray] = fi.user_value;
784 rays_new_owner[ray] = fi.contrib_owner;
785 //info() << "SET RAY uid=" << ray.uniqueId() << " distance=" << distance << " new_owner=" << fi.contrib_owner;
786 }
787 /*info() << "GLOBAL RAY I=" << i << " uid=" << ray.uniqueId() << " lid=" << fi.local_id
788 << " owner=" << fi.owner
789 << " distance=" << fi.distance
790 << " contrib_owner=" << fi.contrib_owner
791 << " face=" << fi.face_local_id
792 << " new_owner=" << rays_new_owner[ray];*/
793 }
794 ray_family->toParticleFamily()->exchangeParticles();
795 }
796 }
797 else{
798
801
803 Integer index = iitem.index();
806 }
807
811
813
814 // Recopie en sortie les valeurs dans les variables correspondantes.
816 Integer index = iitem.index();
818 distances[iitem] = out_distances[index];
819 rays_face[iitem] = out_faces[index];
820 }
821
822 }
823
824 // Pour test, écrit les rayons et leur point d'impact.
825 {
826 Integer nb_new_ray = ray_family->nbItem();
831 Integer index = iitem.index();
832 local_distances[index] = distances[iitem];
835 }
836 if (global_has_lima)
838 }
839
840}
841
842/*---------------------------------------------------------------------------*/
843/*---------------------------------------------------------------------------*/
844
845/*---------------------------------------------------------------------------*/
846/*---------------------------------------------------------------------------*/
847
848void BasicRayMeshIntersection::
849_writeSegments(Int32 rank,
852 RealConstArrayView distances)
853{
854#ifdef ARCANE_HAS_PACKAGE_LIMA
855 Lima::Maillage lima("segments");
856 lima.dimension(Lima::D3);
857
858 Integer nb_segment = positions.size();
860 for( Integer i=0; i<nb_segment; ++i ){
861 Real t = distances[i];
862 if (t<0.0)
863 t = 10.0;
864 lm_nodes[i*2].set_x(positions[i].x);
865 lm_nodes[i*2].set_y(positions[i].y);
866 lm_nodes[i*2].set_z(positions[i].z);
867
868 lm_nodes[(i*2)+1].set_x(positions[i].x + t*directions[i].x);
869 lm_nodes[(i*2)+1].set_y(positions[i].y + t*directions[i].y);
870 lm_nodes[(i*2)+1].set_z(positions[i].z + t*directions[i].z);
871 lima.ajouter(lm_nodes[(i*2)]);
872 lima.ajouter(lm_nodes[(i*2)+1]);
873 lima.ajouter(Lima::Bras(lm_nodes[i*2],lm_nodes[(i*2)+1]));
874 }
875 StringBuilder sb("segments");
876 sb+=rank;
877 sb+=".unf";
878 std::string s(sb.toString().localstr());
879 lima.ecrire(s);
880#else
881 ARCANE_UNUSED(rank);
882 ARCANE_UNUSED(positions);
883 ARCANE_UNUSED(directions);
884 ARCANE_UNUSED(distances);
885 ARCANE_THROW(NotSupportedException,"Lima is not available");
886#endif
887}
888
889/*---------------------------------------------------------------------------*/
890/*---------------------------------------------------------------------------*/
891
892ARCANE_REGISTER_SUB_DOMAIN_FACTORY(BasicRayMeshIntersection,IRayMeshIntersection,
893 BasicRayMeshIntersection);
894
895/*---------------------------------------------------------------------------*/
896/*---------------------------------------------------------------------------*/
897
898} // End namespace Arcane
899
900/*---------------------------------------------------------------------------*/
901/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#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.
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.
Face d'une maille.
Definition Item.h:944
Interface d'une famille d'entités.
virtual FaceGroup outerFaces()=0
Groupe de toutes les faces sur la frontière.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
Interface du gestionnaire de parallélisme pour un sous-domaine.
Interface générique du calcul de l'intersection d'un rayon avec une face.
virtual bool computeIntersection(Real3 origin, Real3 direction, Int32 orig_face_local_id, Int32 face_local_id, Real3ConstArrayView face_nodes, Int32 *user_value, Real *distance, Real3 *intersection_position)=0
Calcul l'intersection entre un rayon et une face.
Calcul de l'intersection entre un ensemble de segments et la surface d'un maillage.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:776
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Variable scalaire sur un type d'entité du maillage.
Vue sur les informations des particules.
Particule.
Definition Item.h:1397
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.
Vue modifiable d'un tableau d'un type T.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Exception lorsqu'une erreur fatale est survenue.
Interface du gestionnaire de traces.
Référence à une instance.
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
-*- 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:586
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:578