Arcane  4.1.11.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
TiedInterface.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/* TiedInterface.cc (C) 2000-2025 */
9/* */
10/* Information on mesh semi-conformities. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/String.h"
15#include "arcane/utils/HashTableMap.h"
16#include "arcane/utils/Real3.h"
17#include "arcane/utils/OStringStream.h"
18#include "arcane/utils/NotImplementedException.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/ITraceMng.h"
21#include "arcane/utils/Collection.h"
22#include "arcane/utils/Enumerator.h"
23#include "arcane/utils/CheckedConvert.h"
24
25#include "arcane/mesh/TiedInterface.h"
26
27#include "arcane/core/IMesh.h"
28#include "arcane/core/IMeshSubMeshTransition.h"
30#include "arcane/core/ItemGroup.h"
31#include "arcane/core/Item.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/VariableTypes.h"
34#include "arcane/core/IItemFamily.h"
35#include "arcane/core/ItemCompare.h"
36#include "arcane/core/IParallelMng.h"
37#include "arcane/core/GeometricUtilities.h"
38#include "arcane/core/SerializeBuffer.h"
39#include "arcane/core/ItemPrinter.h"
40#include "arcane/core/IMeshUtilities.h"
41
42#include <set>
43#include <map>
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48namespace Arcane::mesh
49{
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
55{
56 public:
57
58 void printInfos()
59 {
60 std::ostream& o = cout;
61 o << " MasterFacesUid=" << m_master_faces_uid.size()
62 << " SlaveNodesUid=" << m_slave_nodes_uid.size()
63 << " SlaveFacesUid=" << m_slave_faces_uid.size()
64 << " MasterFacesNbSlaveNode=" << m_master_faces_nb_slave_node.size()
65 << " MasterFacesNbSlaveFace=" << m_master_faces_nb_slave_face.size()
66 << " SlaveNodesIso=" << m_slave_nodes_iso.size()
67 << " MasterFacesSlaveFaceIndex=" << m_master_faces_slave_face_index.size()
68 << " MasterFacesSlaveNodeIndex=" << m_master_faces_slave_node_index.size()
69 << "\n";
70 };
71
72 public:
73
86
87 IntegerUniqueArray m_master_faces_slave_face_index;
88 IntegerUniqueArray m_master_faces_slave_node_index;
89};
90
91/*---------------------------------------------------------------------------*/
92/*---------------------------------------------------------------------------*/
93
95{
96 public:
97
98 Integer size() const { return m_nodes_unique_id.size(); }
99 void add(ItemUniqueId node_unique_id)
100 {
101 m_nodes_unique_id.add(node_unique_id);
102 }
103
104 public:
105
106 UniqueArray<ItemUniqueId> m_nodes_unique_id;
107};
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112class TiedInterfaceNodeInfo
113{
114 public:
115
116 TiedInterfaceNodeInfo()
117 : m_unique_id(NULL_ITEM_ID)
118 {}
119 TiedInterfaceNodeInfo(ItemUniqueId node_uid)
120 : m_unique_id(node_uid)
121 {}
122
123 public:
124
125 ItemUniqueId uniqueId() const
126 {
127 return m_unique_id;
128 }
129 void addConnectedFace(ItemUniqueId uid)
130 {
131 for (Integer i = 0, is = m_connected_master_faces.size(); i < is; ++i)
132 if (m_connected_master_faces[i] == uid)
133 return;
135 }
136
137 private:
138
141
142 public:
143 public:
144
147
150};
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
160class TiedInterfaceFace
161{
162 public:
163
164 TiedInterfaceFace()
165 : m_unique_id(NULL_ITEM_ID)
166 , m_cell_unique_id(NULL_ITEM_ID)
167 , m_owner(-1)
168 , m_nb_node(0)
169 , m_data_index(-1)
170 , m_mng(0)
171 {}
172 TiedInterfaceFace(ItemUniqueId unique_id, ItemUniqueId cell_unique_id, Integer nb_node, Integer owner,
173 Integer data_index, TiedInterfaceFaceInfoMng* mng)
174 : m_unique_id(unique_id)
175 , m_cell_unique_id(cell_unique_id)
176 , m_owner(owner)
177 , m_nb_node(nb_node)
178 , m_data_index(data_index)
179 , m_mng(mng)
180 {}
181
182 public:
183
184 ItemUniqueId uniqueId() const
185 {
186 return m_unique_id;
187 }
188 ItemUniqueId cellUniqueId() const
189 {
190 return m_cell_unique_id;
191 }
192 Integer nbNode() const
193 {
194 return m_nb_node;
195 }
196 ItemUniqueId nodeUniqueId(Integer i) const
197 {
198 return m_mng->m_nodes_unique_id[m_data_index + i];
199 }
200 Integer owner() const
201 {
202 return m_owner;
203 }
204 void setCenter(Real3 center)
205 {
206 m_center = center;
207 }
208 Real3 center() const
209 {
210 return m_center;
211 }
212
213 private:
214
215 ItemUniqueId m_unique_id;
216 ItemUniqueId m_cell_unique_id;
217 Integer m_owner;
218 Integer m_nb_node;
219 Real3 m_center;
220
221 public:
222
223 Integer m_data_index;
225};
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230class TiedInterfaceMasterFace
231{
232 public:
233
234 class NodeInfo
235 {
236 public:
237
238 NodeInfo()
239 : m_unique_id(NULL_ITEM_ID)
240 , m_alpha(-1.0)
241 , m_beta(-1.0)
242 {}
243 NodeInfo(ItemUniqueId uid)
244 : m_unique_id(uid)
245 , m_alpha(-1.0)
246 , m_beta(-1.0)
247 {}
248
249 public:
250
251 ItemUniqueId m_unique_id;
252 Real m_alpha;
253 Real m_beta;
254 };
255 typedef HashTableMapT<ItemUniqueId, NodeInfo> NodeInfoList;
256
257 public:
258
259 TiedInterfaceMasterFace()
260 : m_unique_id(NULL_ITEM_ID)
261 {}
263 : m_unique_id(unique_id)
264 {}
265
266 public:
267
268 ItemUniqueId uniqueId() const
269 {
270 return m_unique_id;
271 }
272
273 public:
274
275 ItemUniqueId m_unique_id;
276 SharedArray<TiedInterfaceFace*> m_slave_faces;
277};
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
281
282class TiedInterfaceSortedNodeInfo
283{
284 public:
285
286 TiedInterfaceSortedNodeInfo(ItemUniqueId uid, Real alpha, Real beta)
287 : m_uid(uid)
288 , m_alpha(alpha)
289 , m_beta(beta)
290 {}
291
292 public:
293
294 bool operator<(const TiedInterfaceSortedNodeInfo& rhs) const
295 {
296 if (m_alpha != rhs.m_alpha)
297 return m_alpha < rhs.m_alpha;
298 if (m_beta != rhs.m_beta)
299 return (m_beta < rhs.m_beta);
300 return (m_uid < rhs.m_uid);
301 }
302
303 public:
304
305 ItemUniqueId uniqueId() const { return m_uid; }
306
307 public:
308
309 ItemUniqueId m_uid;
310 Real m_alpha;
311 Real m_beta;
312};
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
316
317class TiedInterfaceStructurationInfo
318{
319 public:
320
321 TiedInterfaceStructurationInfo(ItemUniqueId node_uid, Real alpha, Real beta)
322 : m_node_uid(node_uid)
323 , m_alpha(alpha)
324 , m_beta(beta)
325 , m_x(-1)
326 , m_y(-1)
327 {
328 }
329 TiedInterfaceStructurationInfo()
330 : m_node_uid(NULL_ITEM_UNIQUE_ID)
331 , m_alpha(0.0)
332 , m_beta(0.0)
333 , m_x(-1)
334 , m_y(-1)
335 {
336 }
337
338 public:
339
340 bool operator<(const TiedInterfaceStructurationInfo& rhs) const
341 {
342 if (m_x != rhs.m_x)
343 return m_x < rhs.m_x;
344 if (m_y != rhs.m_y)
345 return (m_y < rhs.m_y);
346 return false;
347 }
348
349 public:
350
351 void setStructuration(Integer x, Integer y)
352 {
353 if (m_x != (-1) && x != m_x)
354 ARCANE_FATAL("already set with a different x value old={0} new={1}", m_x, x);
355 if (m_y != (-1) && y != m_y)
356 ARCANE_FATAL("already set with a different y value old={0} new={1}", m_y, y);
357 m_x = x;
358 m_y = y;
359 }
360 bool hasStructuration() const
361 {
362 return (m_x != (-1) && m_y != (-1));
363 }
364
365 public:
366
367 ItemUniqueId m_node_uid;
368 Real m_alpha;
369 Real m_beta;
372};
373
374/*---------------------------------------------------------------------------*/
375/*---------------------------------------------------------------------------*/
402class TiedInterfaceBuilder
403: public TraceAccessor
404{
405 public:
406
408 typedef HashTableMapT<ItemUniqueId, TiedInterfaceFace> TiedInterfaceFaceMap;
410 typedef HashTableMapEnumeratorT<ItemUniqueId, TiedInterfaceFace> TiedInterfaceFaceMapEnumerator;
411 typedef std::set<TiedInterfaceSortedNodeInfo> SortedNodeInfoSet;
414
415 public:
416
417 TiedInterfaceBuilder(IMesh* mesh, const FaceGroup& slave_interface, bool use_own, bool is_debug);
418 void setPlanarTolerance(Real tolerance);
419
420 public:
421
422 void computeInterfaceConnections(bool allow_communication);
423 void computeInterfaceInfos(TiedInterfaceBuilderInfos& infos, bool is_structured);
424 void changeOwners(Int64Array& linked_cells, Int32Array& linked_owers);
425 void changeOwnersOld();
426 const FaceGroup& masterInterface() const { return m_master_interface; }
427
428 private:
429
430 bool m_is_debug;
431 IMesh* m_mesh;
432 VariableNodeReal3 m_nodes_coord;
433 TiedInterfaceFaceInfoMng m_face_info_mng;
434 //UniqueArray<TiedInterfaceFace> m_slave_faces;
435 NodeInfoList m_nodes_info;
436 TiedInterfaceFaceMap m_slave_faces;
437 TiedInterfaceFaceMap m_master_faces;
438 String m_slave_interface_name;
439 FaceGroup m_slave_interface;
440 FaceGroup m_master_interface;
443 Real m_planar_tolerance;
444
445 private:
446
448 void _searchMasterFaces(Array<ItemUniqueId>& slave_faces_to_process,
449 Array<ItemUniqueId>& remaining_slave_faces);
450 bool _isInsideFace(const TiedInterfaceFace& face, Real3 point);
451 Real3 _computeNormale(const TiedInterfaceFace& face);
454 TiedInterfaceFaceMap& face_map);
455 void _gatherAllNodesInfo();
456 void _printFaces(std::ostream& o, TiedInterfaceFaceMap& face_map);
457 void _computeProjectionInfos(TiedInterfaceBuilderInfos& infos, bool is_structured);
458 void _addFaceToList(const Face& face, TiedInterfaceFaceMap& face_map);
459 void _detectStructuration(const TiedInterfaceMasterFace& master_face,
460 StructurationMap& nodes);
461 void _detectStructurationRecursive(Array<ItemUniqueId>& slave_faces_to_process,
462 Array<ItemUniqueId>& remaining_slave_faces,
463 StructurationMap& slave_nodes);
465};
466
467/*---------------------------------------------------------------------------*/
468/*---------------------------------------------------------------------------*/
469
470TiedInterfaceBuilder::
471TiedInterfaceBuilder(IMesh* mesh, const FaceGroup& slave_interface,
472 bool use_own, bool is_debug)
473: TraceAccessor(mesh->traceMng())
474, m_is_debug(is_debug)
475, m_mesh(mesh)
476, m_nodes_coord(m_mesh->toPrimaryMesh()->nodesCoordinates())
477, m_nodes_info(1000, true)
478, m_slave_faces(5000, true)
479, m_master_faces(1000, true)
480, m_slave_interface_name(slave_interface.name())
481, m_slave_interface(slave_interface)
482, m_slave_faces_master_face_uid(1000, true)
483, m_planar_tolerance(0.0)
484{
485 if (use_own)
486 m_slave_interface = slave_interface.own();
487}
488
489/*---------------------------------------------------------------------------*/
490/*---------------------------------------------------------------------------*/
491
492void TiedInterfaceBuilder::
493setPlanarTolerance(Real tolerance)
494{
495 m_planar_tolerance = tolerance;
496}
497
498/*---------------------------------------------------------------------------*/
499/*---------------------------------------------------------------------------*/
500
501void TiedInterfaceBuilder::
502_searchMasterFaces(Array<ItemUniqueId>& slave_faces_to_process,
503 Array<ItemUniqueId>& remaining_slave_faces)
504{
505 String func_name = "TiedInterfaceBuilder::_searchMasterFaces()";
506
507 std::set<ItemUniqueId> master_faces_to_test;
508 UniqueArray<ItemUniqueId> master_faces_found;
509 master_faces_found.reserve(100);
510 Real3UniqueArray slave_face_nodes_coord;
511 slave_face_nodes_coord.reserve(100);
512 Real3UniqueArray triangle_centers;
513 triangle_centers.reserve(100);
514
515 if (m_is_debug) {
516 info() << "nb slave faces to process=" << slave_faces_to_process.size();
517 //info() << "nb remaining slave faces=" << remaining_slave_faces.size();
518 }
519 for (Integer islaveface = 0, izz = slave_faces_to_process.size(); islaveface < izz; ++islaveface) {
520 master_faces_to_test.clear();
521 master_faces_found.clear();
522
523 TiedInterfaceFace& face = m_slave_faces[slave_faces_to_process[islaveface]];
524
525 slave_face_nodes_coord.clear();
526
527 Integer nb_node = face.nbNode();
528 triangle_centers.resize(nb_node);
529
530 for (Integer inode = 0; inode < nb_node; ++inode) {
531 TiedInterfaceNodeInfo& node_info = m_nodes_info[face.nodeUniqueId(inode)];
532 slave_face_nodes_coord.add(node_info.m_coord);
533 for (Integer zface = 0, zz = node_info.m_connected_master_faces.size(); zface < zz; ++zface) {
534 master_faces_to_test.insert(node_info.m_connected_master_faces[zface]);
535 }
536 }
537
538 for (Integer inode = 0; inode < nb_node; ++inode) {
539 triangle_centers[inode] = (slave_face_nodes_coord[inode] + slave_face_nodes_coord[(inode + 1) % nb_node] + face.center()) / 3.;
540 }
541
542 // Iterates through the list of possible master faces, and checks if one of the barycenters
543 // of the triangular decomposition of the slave face is inside one of these faces.
544 for (std::set<ItemUniqueId>::const_iterator i_master_face(master_faces_to_test.begin());
545 i_master_face != master_faces_to_test.end(); ++i_master_face) {
546 TiedInterfaceFaceMap::Data* data = m_master_faces.lookup(*i_master_face);
547 if (!data)
548 ARCANE_FATAL("INTERNAL: Can not find face uid={0}", *i_master_face);
549 const TiedInterfaceFace& master_face = data->value();
550 bool is_found = false;
551 for (Integer inode = 0; inode < nb_node; ++inode) {
552 if (_isInsideFace(master_face, triangle_centers[inode])) {
553 // info() << "Master found " << master_face.uniqueId() << " vs slave:" << face.uniqueId();
554 // info() << "Master coords:" << m_nodes_info[master_face.nodeUniqueId(0)].m_coord
555 // << " " << m_nodes_info[master_face.nodeUniqueId(1)].m_coord
556 // << " " << m_nodes_info[master_face.nodeUniqueId(2)].m_coord
557 // << " " << m_nodes_info[master_face.nodeUniqueId(3)].m_coord;
558 // info() << "Slave coords:" << m_nodes_info[face.nodeUniqueId(0)].m_coord
559 // << " " << m_nodes_info[face.nodeUniqueId(1)].m_coord
560 // << " " << m_nodes_info[face.nodeUniqueId(2)].m_coord
561 // << " " << m_nodes_info[face.nodeUniqueId(3)].m_coord;
562 // info() << "This point : " << inode << " " << triangle_centers[inode];
563 is_found = true;
564 break;
565 }
566 }
567
568 if (is_found) {
569 //info() << "SlaveFace " << face.uniqueId() << " found in face "
570 //<< master_face.uniqueId() << " d=" << best_d.m_distance;
571 master_faces_found.add(master_face.uniqueId());
572 }
573 }
574 switch (master_faces_found.size()) {
575 case 1: {
576 ItemUniqueId master_face_uid = master_faces_found[0];
577 //info() << "** GOOD: SlaveFace " << face.uniqueId() << " found in face " << master_face_uid;
578 for (Integer inode = 0; inode < nb_node; ++inode) {
579 TiedInterfaceNodeInfo& node_info = m_nodes_info[face.nodeUniqueId(inode)];
580 node_info.m_connected_master_faces.add(master_face_uid);
581 }
582 //face.setMasterFace(master_face_uid);
583 m_slave_faces_master_face_uid.add(face.uniqueId(), master_face_uid);
584 } break;
585 case 0:
586 // Not found, add to the list for the next test.
587 //info() << "** BAD: SlaveFace " << face.uniqueId();
588 remaining_slave_faces.add(face.uniqueId());
589 break;
590 default: {
591 // This case can occur if in 2D or 3D a mesh has a weld on
592 // two connected faces. In this case, there are often several
593 // possible master faces. To distinguish them, we choose
594 // the master face whose orientation (the normal) is most collinear
595 // with the slave mesh. To do this, it is enough to calculate
596 // the dot product between the slave face and each master face
597 // potential and take the largest in absolute value (to avoid
598 // orientation problems).
599 Real3 face_normale = _computeNormale(face);
600 OStringStream ostr;
601 ostr() << "Too many master faces for a slave face (max=1) "
602 << " nb_master=" << master_faces_found.size()
603 << " (slave_face=" << face.uniqueId() << ",normal=" << face_normale << ")"
604 << " master_list=";
605 Real max_dot = -1.0;
606 Integer keep_index = -1;
607 for (Integer zz = 0; zz < master_faces_found.size(); ++zz) {
608 ItemUniqueId muid = master_faces_found[zz];
609 const TiedInterfaceFace& master_face = m_master_faces.lookupValue(muid);
610 Real3 n = _computeNormale(master_face);
611 Real d = math::scaMul(n, face_normale);
612 if (math::abs(d) > max_dot) {
613 max_dot = math::abs(d);
614 keep_index = zz;
615 }
616 ostr() << " (uid=" << muid << ",nb_node=" << master_face.nbNode()
617 << " center=" << master_face.center()
618 << " normale=" << n
619 << " dot=" << d
620 << ")";
621 }
622 if (keep_index >= 0) {
623 info() << func_name << " " << ostr.str() << ". Keeping index=" << keep_index;
624 {
625 ItemUniqueId master_face_uid = master_faces_found[keep_index];
626 for (Integer inode = 0; inode < nb_node; ++inode) {
627 TiedInterfaceNodeInfo& node_info = m_nodes_info[face.nodeUniqueId(inode)];
628 node_info.m_connected_master_faces.add(master_face_uid);
629 }
630 //face.setMasterFace(master_face_uid);
631 m_slave_faces_master_face_uid.add(face.uniqueId(), master_face_uid);
632 }
633 }
634 else
635 ARCANE_FATAL(ostr.str());
636 }
637 }
638 }
639}
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
663_findProjection(const TiedInterfaceFace& face, Real3 point)
664{
665 Integer nb_node = face.nbNode();
666
668
669 if (nb_node > 3) {
670 for (Integer inode = 0; inode < nb_node; ++inode) {
671 Real3 v1 = m_nodes_info[face.nodeUniqueId(inode)].m_coord;
672 Real3 v2 = m_nodes_info[face.nodeUniqueId((inode + 1) % nb_node)].m_coord;
673 GeometricUtilities::ProjectionInfo d = min_distance.projection(face.center(), v1, v2, point);
674 //info() << " DISTANCE: r=" << region << " d=" << d;
675 if (d.m_region == 0) {
676 if (min_distance.m_region != 0) {
677 min_distance = d;
678 }
679 else {
680 if (d.m_distance < min_distance.m_distance) {
681 min_distance = d;
682 }
683 }
684 }
685 else {
686 if (min_distance.m_region != 0) {
687 if (d.m_distance < min_distance.m_distance) {
688 min_distance = d;
689 }
690 }
691 }
692 }
693 }
694 else if (nb_node == 3) {
695 Real3 v1 = m_nodes_info[face.nodeUniqueId(0)].m_coord;
696 Real3 v2 = m_nodes_info[face.nodeUniqueId(1)].m_coord;
697 Real3 v3 = m_nodes_info[face.nodeUniqueId(2)].m_coord;
698 min_distance = min_distance.projection(v1, v2, v3, point);
699 }
700 else if (nb_node == 2) {
701 Real3 v1 = m_nodes_info[face.nodeUniqueId(0)].m_coord;
702 Real3 v2 = m_nodes_info[face.nodeUniqueId(1)].m_coord;
703 min_distance = min_distance.projection(v1, v2, point);
704 }
705 return min_distance;
706}
707
708/*---------------------------------------------------------------------------*/
709/*---------------------------------------------------------------------------*/
710
711Real3 TiedInterfaceBuilder::
712_computeNormale(const TiedInterfaceFace& face)
713{
714 Integer nb_node = face.nbNode();
715 Real3 normale;
716 if (nb_node >= 3) {
717 for (Integer inode = 0; inode < nb_node; ++inode) {
718 Real3 v1 = m_nodes_info[face.nodeUniqueId(inode)].m_coord;
719 Real3 v2 = m_nodes_info[face.nodeUniqueId((inode + 1) % nb_node)].m_coord;
720 Real3 v3 = m_nodes_info[face.nodeUniqueId((inode + 2) % nb_node)].m_coord;
721 Real3 vd_a = v1 - v2;
722 Real3 vd_b = v3 - v2;
723 Real3 local_normale = math::vecMul(vd_a, vd_b);
724 normale += local_normale;
725 }
726 }
727 else if (nb_node == 2) {
728 Real3 v1 = m_nodes_info[face.nodeUniqueId(0)].m_coord;
729 Real3 v2 = m_nodes_info[face.nodeUniqueId(1)].m_coord;
730 if (v1.z != 0.0 || v2.z != 0.0)
731 throw NotImplementedException(A_FUNCINFO, "edge in 3D space");
732 Real x = v2.x - v1.x;
733 Real y = v2.y - v1.y;
734 normale = Real3(-y, x, 0.0);
735 }
736 else
737 throw NotSupportedException(A_FUNCINFO, "can not compute normal of face with 0 or 1 node");
738 return normale.normalize();
739}
740
741/*---------------------------------------------------------------------------*/
742/*---------------------------------------------------------------------------*/
743
744bool TiedInterfaceBuilder::
745_isInsideFace(const TiedInterfaceFace& face, Real3 point)
746{
747 Integer nb_node = face.nbNode();
748 if (nb_node > 2) {
749 for (Integer inode = 0; inode < nb_node; ++inode) {
750 Real3 v1 = m_nodes_info[face.nodeUniqueId(inode)].m_coord;
751 Real3 v2 = m_nodes_info[face.nodeUniqueId((inode + 1) % nb_node)].m_coord;
752 if (m_planar_tolerance != 0.0) { // Ne fait le calcul que si le test est utile
753 Real ecart = math::mixteMul(point - face.center(), math::normalizeReal3(v1 - face.center()), math::normalizeReal3(v2 - face.center()));
754 if (math::abs(ecart) > m_planar_tolerance * math::normeR3(v1 - v2)) {
755 if (m_is_debug)
756 info() << "Reject non planar projection " << point << " from face uid=" << face.uniqueId();
757 return false;
758 }
759 }
760 if (GeometricUtilities::ProjectionInfo::isInside(face.center(), v1, v2, point))
761 return true;
762 }
763 }
764 else if (nb_node == 2) {
765 Real3 v1 = m_nodes_info[face.nodeUniqueId(0)].m_coord;
766 Real3 v2 = m_nodes_info[face.nodeUniqueId(1)].m_coord;
768 return true;
769 }
770 return false;
771}
772
773/*---------------------------------------------------------------------------*/
774/*---------------------------------------------------------------------------*/
793{
794 // Slave face marker
795 std::set<ItemUniqueId> slave_faces_flag;
796
797 Integer nb_slave_face = m_slave_interface.size();
798 m_nodes_info.resize((nb_slave_face * 2) + 5);
799 m_master_faces.resize(nb_slave_face + 5);
800 m_slave_faces.resize((nb_slave_face * 2) + 5);
801
802 // Builds the necessary information concerning the
803 // slave faces and marks all the nodes.
804 ENUMERATE_FACE (iface, m_slave_interface) {
805 const Face& face = *iface;
806 slave_faces_flag.insert(face.uniqueId());
807 _addFaceToList(face, m_slave_faces);
808 }
809
810 info() << "SLAVE_INTERFACE: nb_face=" << m_slave_interface.size();
811 // From the marked nodes, determines the master faces
812 Int32UniqueArray master_faces_lid;
813 bool has_not_handled_face = false;
814 ENUMERATE_FACE (iface, m_mesh->outerFaces()) {
815 const Face& face = *iface;
816 // Checks that it is not a slave face
817 if (slave_faces_flag.find(face.uniqueId()) != slave_faces_flag.end())
818 continue;
819 Integer nb_node = face.nbNode();
820 bool is_master_face = true;
821 // A face is master if each of its nodes is in the list of slave nodes
822 for (Node node : face.nodes()) {
823 ItemUniqueId uid = node.uniqueId();
824 if (!m_nodes_info.lookup(uid)) {
825 is_master_face = false;
826 break;
827 }
828 }
829 if (is_master_face) {
830 // For now, only supports faces with 2 and 4 nodes.
831 if (nb_node != 4 && nb_node != 2)
832 has_not_handled_face = true;
833 master_faces_lid.add(face.localId());
834 for (Node node : face.nodes()) {
835 TiedInterfaceNodeInfo& znode = m_nodes_info[node.uniqueId()];
836 znode.m_connected_master_faces.add(face.uniqueId());
837 }
838 _addFaceToList(face, m_master_faces);
839 }
840 }
841 if (has_not_handled_face)
842 ARCANE_FATAL("Some faces of the tied interface '{0}' has incorrect number of nodes (should be 2 or 4)",
843 m_slave_interface.name());
844
845 m_master_interface = m_mesh->faceFamily()->createGroup(m_slave_interface_name + "_MASTER",
846 master_faces_lid, true);
847 info() << "MASTER_INTERFACE: nb_face=" << m_master_interface.size();
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
853void TiedInterfaceBuilder::
854_addFaceToList(const Face& face, TiedInterfaceFaceMap& face_map)
855{
856 Integer nb_node = face.nbNode();
857 Real3 center(0., 0., 0.);
858 Integer data_index = m_face_info_mng.size();
859 for (Node node : face.nodes()) {
860 Real3 node_coord = m_nodes_coord[node];
861 ItemUniqueId uid = node.uniqueId();
862 NodeInfoList::Data* i = m_nodes_info.lookup(uid);
863 if (!i) {
864 TiedInterfaceNodeInfo node_info(uid);
865 node_info.m_coord = node_coord;
866 m_nodes_info.add(uid, node_info);
867 }
868 m_face_info_mng.add(uid);
869 center += node_coord;
870 }
871 center /= nb_node;
872 //info() << "ADD FACE uid=" << face.uniqueId() << " nb_node="
873 //<< nb_node << " center=" << center;
874 TiedInterfaceFace sf(face.uniqueId(), face.cell(0).uniqueId(), nb_node, face.owner(), data_index, &m_face_info_mng);
875 sf.setCenter(center);
876 face_map.add(face.uniqueId(), sf);
877}
878
879/*---------------------------------------------------------------------------*/
880/*---------------------------------------------------------------------------*/
887{
888 std::set<ItemUniqueId> master_face_with_slave;
889
890 for (TiedInterfaceFaceMapEnumerator i(m_slave_faces); ++i;) {
891 TiedInterfaceFace& slave_face = *i;
892 ItemUniqueId master_uid = m_slave_faces_master_face_uid[slave_face.uniqueId()];
893 master_face_with_slave.insert(master_uid);
894 }
895
896 Int32UniqueArray local_ids_to_remove;
897 ENUMERATE_FACE (iface, m_master_interface.own()) {
898 Face face = *iface;
899 ItemUniqueId uid = face.uniqueId();
900 if (master_face_with_slave.find(uid) == master_face_with_slave.end()) {
901 local_ids_to_remove.add(iface.itemLocalId());
902 }
903 }
904
905 if (!local_ids_to_remove.empty()) {
906 info() << "Removing faces from master list name=" << m_master_interface.name()
907 << " ids=" << local_ids_to_remove;
908 m_master_interface.removeItems(local_ids_to_remove, false);
909 }
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
915void TiedInterfaceBuilder::
916_computeProjectionInfos(TiedInterfaceBuilderInfos& infos, bool is_structured)
917{
919 Integer nb_master_face = m_master_interface.size();
920 MasterFaceList m_master_faces_full((nb_master_face * 2) + 1, true);
921
922 infos.m_master_faces_uid.reserve(nb_master_face);
923 infos.m_master_faces_nb_slave_node.reserve(nb_master_face);
924 infos.m_master_faces_nb_slave_face.reserve(nb_master_face);
925
926 TiedInterfaceMasterFace null_value;
927 ENUMERATE_FACE (iface, m_master_interface.own()) {
928 const Face& face = *iface;
929 ItemUniqueId master_uid = face.uniqueId();
930 m_master_faces_full.add(master_uid, TiedInterfaceMasterFace(master_uid));
931 }
932
933 for (TiedInterfaceFaceMapEnumerator i(m_slave_faces); ++i;) {
934 TiedInterfaceFace& slave_face = *i;
935 ItemUniqueId master_uid = m_slave_faces_master_face_uid[slave_face.uniqueId()];
936 TiedInterfaceMasterFace& mf = m_master_faces_full[master_uid];
937 mf.m_slave_faces.add(&slave_face);
938 }
939
940 ENUMERATE_FACE (iface, m_master_interface.own()) {
941 Face face = *iface;
942 ItemUniqueId master_uid = face.uniqueId();
943 //TiedInterfaceMasterFace& mf = *enumerator;
944 TiedInterfaceMasterFace& mf = m_master_faces_full[master_uid];
945 Integer master_face_nb_slave_face = mf.m_slave_faces.size();
946 //Int64 master_uid = mf.uniqueId();
947 if (m_is_debug)
948 info() << "MASTER FACE uid=" << master_uid << " NB_SLAVE_FACE=" << master_face_nb_slave_face
949 << " face_owner=" << face.owner();
950 infos.m_master_faces_uid.add(master_uid);
951 infos.m_master_faces_nb_slave_face.add(master_face_nb_slave_face);
952 infos.m_master_faces_slave_face_index.add(infos.m_slave_faces_uid.size());
953 for (Integer zz = 0; zz < master_face_nb_slave_face; ++zz) {
954 ItemUniqueId slave_uid = mf.m_slave_faces[zz]->uniqueId();
955 infos.m_slave_faces_uid.add(slave_uid);
956 }
957 }
958
959 std::set<ItemUniqueId> slave_nodes_set;
960 SortedNodeInfoSet slave_nodes_sorted_set;
961
962 bool is_dimension_2d = m_mesh->dimension() == 2;
963 ENUMERATE_FACE (imasterface, m_master_interface.own()) {
964 Face master_face = *imasterface;
965 ItemUniqueId master_uid = master_face.uniqueId();
966 slave_nodes_set.clear();
967 slave_nodes_sorted_set.clear();
968 TiedInterfaceMasterFace& face2 = m_master_faces_full[master_uid];
969 if (m_is_debug) {
970 Integer face2_nb_node = master_face.nbNode();
971 info() << "MASTER FACE: uid=" << face2.uniqueId()
972 << " cell_uid=" << master_face.cell(0).uniqueId()
973 << " cell_owner=" << master_face.cell(0).owner()
974 << " nb_node=" << face2_nb_node;
975 for (Integer in2 = 0; in2 < face2_nb_node; ++in2)
976 info() << "Node " << in2 << " uid=" << master_face.node(in2).uniqueId();
977 }
978 TiedInterfaceFace& face = m_master_faces[face2.uniqueId()];
979 Integer nb_node = face.nbNode();
980 Integer nb_slave_face = face2.m_slave_faces.size();
981 for (Integer i = 0; i < nb_slave_face; ++i) {
982 const TiedInterfaceFace& slave_face = *face2.m_slave_faces[i];
983 Integer slave_nb_node = slave_face.nbNode();
984 for (Integer z = 0; z < slave_nb_node; ++z) {
985 ItemUniqueId node_uid = slave_face.nodeUniqueId(z);
986 slave_nodes_set.insert(node_uid);
987 //info() << "ADD NODE uid=" << node_uid;
988 }
989 }
990 if (m_is_debug)
991 info() << "MASTER FACE: NB_SLAVE_FACE=" << nb_slave_face
992 << " NB_SLAVE_NODE=" << slave_nodes_set.size();
993 infos.m_master_faces_slave_node_index.add(infos.m_slave_nodes_uid.size());
994 infos.m_master_faces_nb_slave_node.add(CheckedConvert::toInteger(slave_nodes_set.size()));
995 {
996 std::set<ItemUniqueId>::const_iterator i_node = slave_nodes_set.begin();
997 // Cas 3D, les faces sont des quadrangles
998 if (nb_node == 4) {
999 GeometricUtilities::QuadMapping face_mapping;
1000 for (Integer i = 0; i < nb_node; ++i) {
1001 ItemUniqueId node_uid = face.nodeUniqueId(i);
1002 face_mapping.m_pos[i] = m_nodes_info[node_uid].m_coord;
1003 }
1004
1005 for (; i_node != slave_nodes_set.end(); ++i_node) {
1006 ItemUniqueId node_uid = *i_node;
1007 TiedInterfaceNodeInfo& node_info = m_nodes_info[node_uid];
1008 Real3 uvw;
1009 Real3 point = node_info.m_coord;
1010 GeometricUtilities::ProjectionInfo projection = _findProjection(face, point);
1011 if (m_is_debug)
1012 info() << "POINT PROJECTION: uid=" << node_uid << ' '
1013 << projection.m_projection << " r=" << projection.m_region
1014 << " d=" << projection.m_distance
1015 << " alpha=" << projection.m_alpha
1016 << " beta=" << projection.m_beta;
1017 bool is_bad = face_mapping.cartesianToIso(point, uvw, 0);
1018 if (m_is_debug)
1019 info() << "ISO1 =" << uvw;
1020 is_bad = face_mapping.cartesianToIso2(point, uvw, 0);
1021 if (m_is_debug)
1022 info() << "ISO2 =" << uvw;
1023 if (is_bad) {
1024 warning() << "Can not compute iso-coordinates for point " << point;
1025 face_mapping.cartesianToIso(point, uvw, traceMng());
1026 }
1027
1028 if (math::abs(uvw.x) > 1.1 || math::abs(uvw.y) > 1.1 || math::abs(uvw.z) > 1.1) {
1029 info() << "BAD PROJECTION INFO";
1030 info() << "P0 = " << face_mapping.m_pos[0];
1031 info() << "P1 = " << face_mapping.m_pos[1];
1032 info() << "P2 = " << face_mapping.m_pos[2];
1033 info() << "P3 = " << face_mapping.m_pos[3];
1034 warning() << "Internal: bad iso value: " << uvw
1035 << " node=" << node_uid << " pos=" << point
1036 << " projection=" << projection.m_projection
1037 << " face_uid=" << face.uniqueId()
1038 << " cell_uid=" << face.cellUniqueId();
1039 face_mapping.cartesianToIso(point, uvw, traceMng());
1040 face_mapping.cartesianToIso(projection.m_projection, uvw, traceMng());
1041 }
1042 //else
1043 //info() << "POINT ISO1: " << uvw;
1044 //Real3 new_point = face_mapping.evaluatePosition(uvw);
1045 //info() << "POINT ISO_TO_CART: " << (new_point-point).abs();
1046
1047 // Cas particulier des noeuds de la face esclave qui sont des noeuds maitres.
1048 // Dans ce cas, on fixe en dur leur coordonnées iso pour éviter une
1049 // perte de précision.
1050 if (node_uid == face.nodeUniqueId(0)) {
1051 uvw.x = ARCANE_REAL(-1.0);
1052 uvw.y = ARCANE_REAL(-1.0);
1053 }
1054 else if (node_uid == face.nodeUniqueId(1)) {
1055 uvw.x = ARCANE_REAL(1.0);
1056 uvw.y = ARCANE_REAL(-1.0);
1057 }
1058 else if (node_uid == face.nodeUniqueId(2)) {
1059 uvw.x = ARCANE_REAL(1.0);
1060 uvw.y = ARCANE_REAL(1.0);
1061 }
1062 else if (node_uid == face.nodeUniqueId(3)) {
1063 uvw.x = ARCANE_REAL(-1.0);
1064 uvw.y = ARCANE_REAL(1.0);
1065 }
1066
1067 slave_nodes_sorted_set.insert(TiedInterfaceSortedNodeInfo(node_uid, uvw.x, uvw.y));
1068 }
1069 }
1070 // Case 2D, les faces sont des arêtes
1071 else if (nb_node == 2) {
1072 for (; i_node != slave_nodes_set.end(); ++i_node) {
1073 ItemUniqueId node_uid = *i_node;
1074 TiedInterfaceNodeInfo& node_info = m_nodes_info[node_uid];
1075 Real3 point = node_info.m_coord;
1076 GeometricUtilities::ProjectionInfo projection = _findProjection(face, point);
1077 //info() << "POINT PROJECTION: uid=" << node_uid << ' '
1078 // << projection.m_projection
1079 //<< " r=" << projection.m_region << " d=" << projection.m_distance;
1080 // Cas particulier des noeuds de la face esclave qui sont des noeuds maitres.
1081 // Dans ce cas, on fixe en dur leur coordonnées iso pour éviter une
1082 // perte de précision.
1083 Real alpha = projection.m_alpha;
1084 if (node_uid == face.nodeUniqueId(0)) {
1085 alpha = ARCANE_REAL(0.0);
1086 }
1087 else if (node_uid == face.nodeUniqueId(1)) {
1088 alpha = ARCANE_REAL(1.0);
1089 }
1090 slave_nodes_sorted_set.insert(TiedInterfaceSortedNodeInfo(node_uid, alpha, 0.0));
1091 }
1092 }
1093 else
1094 ARCANE_FATAL("Can not detect structuration for face with nb_node={0}."
1095 " Valid values are 2 or 4",
1096 nb_node);
1097 }
1098 if (slave_nodes_sorted_set.size() != slave_nodes_set.size()) {
1099 ARCANE_FATAL("Internal: error sorting nodes in TiedInterface: bad compare");
1100 }
1101 // En cas de structuration, la détecte et recalcule
1102 // les coordonnées iso avec cette info.
1103 if (is_structured) {
1104 StructurationMap struct_map(CheckedConvert::toInteger(slave_nodes_sorted_set.size() * 2), true);
1105 SortedNodeInfoSet::const_iterator i_node = slave_nodes_sorted_set.begin();
1106 for (; i_node != slave_nodes_sorted_set.end(); ++i_node) {
1107 const TiedInterfaceSortedNodeInfo& node = *i_node;
1108 ItemUniqueId uid = node.uniqueId();
1109 TiedInterfaceStructurationInfo struct_info(uid, node.m_alpha, node.m_beta);
1110 struct_map.add(uid, struct_info);
1111 if (m_is_debug)
1112 info() << "Add to struct map node_uid=" << uid << " alpha=" << node.m_alpha << " beta=" << node.m_beta;
1113 }
1114 _detectStructuration(face2, struct_map);
1115 // Recherche la valeur de la structuration.
1116 // Comme on commence la structuration avec le noeud 0 de la face maitre,
1117 // C'est la valeur (x,y) du noeud 2 la maille maitre pour un quad, et
1118 // le noeud 1 pour une arête
1119 TiedInterfaceStructurationInfo sinfo = struct_map[face.nodeUniqueId(nb_node / 2)];
1120 if (m_is_debug)
1121 info() << "********* STRUCTURE X=" << sinfo.m_x << " Y=" << sinfo.m_y;
1122 Integer sx = sinfo.m_x;
1123 Integer sy = sinfo.m_y;
1124 Real rx = (Real)sinfo.m_x;
1125 Real ry = (Real)sinfo.m_y;
1126 slave_nodes_sorted_set.clear();
1127 for (StructurationMapEnumerator imap(struct_map); ++imap;) {
1128 TiedInterfaceStructurationInfo& minfo = *imap;
1129 ItemUniqueId node_uid = minfo.m_node_uid;
1130 Real old_alpha = minfo.m_alpha;
1131 Real old_beta = minfo.m_beta;
1132 Real new_alpha = 0.0;
1133 Real new_beta = 0.0;
1134 if (is_dimension_2d) {
1135 // En 2D, les coordonnées iso vont de 0.0 à 1.0
1136 if (sx != 0)
1137 new_alpha = (1.0 * minfo.m_x) / rx;
1138 }
1139 else {
1140 if (sx != 0)
1141 new_alpha = -1.0 + (2.0 * minfo.m_x) / rx;
1142 if (sy != 0)
1143 new_beta = -1.0 + (2.0 * minfo.m_y) / ry;
1144 }
1145 if (m_is_debug)
1146 info() << "NEW NODE oldx=" << old_alpha << " newx=" << new_alpha
1147 << " oldy=" << old_beta << " newy=" << new_beta;
1148 slave_nodes_sorted_set.insert(TiedInterfaceSortedNodeInfo(node_uid, new_alpha, new_beta));
1149 }
1150 }
1151 {
1152 SortedNodeInfoSet::const_iterator i_node = slave_nodes_sorted_set.begin();
1153 for (; i_node != slave_nodes_sorted_set.end(); ++i_node) {
1154 const TiedInterfaceSortedNodeInfo& node = *i_node;
1155 if (m_is_debug)
1156 info() << "ADD TO SLAVE NODE: node_uid=" << node.m_uid
1157 << " alpha=" << node.m_alpha
1158 << " beta=" << node.m_beta;
1159 infos.m_slave_nodes_uid.add(node.m_uid);
1160 infos.m_slave_nodes_iso.add(Real2(node.m_alpha, node.m_beta));
1161 }
1162 }
1163 }
1164}
1165
1166/*---------------------------------------------------------------------------*/
1167/*---------------------------------------------------------------------------*/
1168
1169void TiedInterfaceBuilder::
1170_detectStructuration(const TiedInterfaceMasterFace& master_face,
1171 StructurationMap& slave_nodes)
1172{
1173 Integer nb_slave_face = master_face.m_slave_faces.size();
1174 // Positionne le premier noeud de la face comme étant le noeud (0,0)
1175 // de la structuration.
1176 TiedInterfaceFace& mface = m_master_faces[master_face.uniqueId()];
1177 TiedInterfaceStructurationInfo& sinfo = slave_nodes[mface.nodeUniqueId(0)];
1178 sinfo.setStructuration(0, 0);
1179 //info() << "** SET STRUCTURATION node=" << mface.nodeUniqueId(0);
1180 UniqueArray<ItemUniqueId> slave_faces;
1181 UniqueArray<ItemUniqueId> remaining_slave_faces;
1182 for (Integer i = 0; i < nb_slave_face; ++i) {
1183 const TiedInterfaceFace& slave_face = *master_face.m_slave_faces[i];
1184 slave_faces.add(slave_face.uniqueId());
1185 }
1186
1187 for (Integer zz = 0; zz < (nb_slave_face + 1); ++zz) {
1188 remaining_slave_faces.clear();
1189 Integer nb_to_process = slave_faces.size();
1190 _detectStructurationRecursive(slave_faces, remaining_slave_faces, slave_nodes);
1191 Integer nb_remaining = remaining_slave_faces.size();
1192 if (nb_remaining == 0)
1193 break;
1194 if (nb_to_process == nb_remaining) {
1195 ARCANE_FATAL("Can not compute structuration for a tied interface"
1196 " remaining_slaves={0}",
1197 nb_remaining);
1198 }
1199 slave_faces.copy(remaining_slave_faces);
1200 }
1201}
1202
1203/*---------------------------------------------------------------------------*/
1204/*---------------------------------------------------------------------------*/
1205
1206void TiedInterfaceBuilder::
1207_detectStructurationRecursive(Array<ItemUniqueId>& slave_faces,
1208 Array<ItemUniqueId>& remaining_slave_faces,
1209 StructurationMap& slave_nodes)
1210{
1211 // Parcours chaque face.
1212 // Une face peut être traitée si un de ses noeuds a déjà une structuration.
1213 // Si ce n'est pas le cas, la face est ajoutée à remaining_slave_faces
1214 // pour être traitée ultérieurement.
1215 // En cas de structuration, on prend le premier trouvé. A partir de ce noeud A,
1216 // on regarde le noeud suivant B dans la face. On regarde si ce
1217 // noeud B différe de notre noeud de référence suivant alpha ou beta.
1218 // S'il s'agit de alpha, il aura le même y et il sera en (x+1) si alpha
1219 // de B est supérieur à celui de A.
1220 // La même chose pour y si la différence est en beta.
1221 // NOTE. Comme la projection n'est pas forcément très bonne, deux
1222 // noeuds de même x par exemple peuvent avoir un alpha légèrement différent.
1223 // Pour déterminer si c'est alpha ou beta qui varie le plus, on
1224 // prend le plus grand de abs(A.alpha-B.alpha) et abs(A.beta-B.beta)
1225 for (Integer i = 0, is = slave_faces.size(); i < is; ++i) {
1226 Integer node_index = (-1);
1227 TiedInterfaceStructurationInfo old_sinfo;
1228 const TiedInterfaceFace& face = m_slave_faces[slave_faces[i]];
1229 Integer nb_node = face.nbNode();
1230 for (Integer z = 0; z < nb_node; ++z) {
1231 ItemUniqueId node_uid = face.nodeUniqueId(z);
1232 const TiedInterfaceStructurationInfo& sinfo = slave_nodes[node_uid];
1233 if (m_is_debug)
1234 info() << "CHECK NODE face_uid=" << face.uniqueId()
1235 << " node_uid=" << node_uid
1236 << " x=" << sinfo.m_x
1237 << " y=" << sinfo.m_y
1238 << " alpha=" << sinfo.m_alpha
1239 << " beta=" << sinfo.m_beta;
1240 if (sinfo.hasStructuration()) {
1241 node_index = z;
1242 old_sinfo = sinfo;
1243 break;
1244 }
1245 }
1246 if (node_index == (-1)) {
1247 remaining_slave_faces.add(slave_faces[i]);
1248 continue;
1249 }
1250
1251 for (Integer z = 1; z < nb_node; ++z) {
1252 ItemUniqueId next_uid = face.nodeUniqueId((node_index + z) % nb_node);
1253 TiedInterfaceStructurationInfo& next_info = slave_nodes[next_uid];
1254 Real diff_alpha = next_info.m_alpha - old_sinfo.m_alpha;
1255 Real diff_beta = next_info.m_beta - old_sinfo.m_beta;
1256 Integer x = old_sinfo.m_x;
1257 Integer y = old_sinfo.m_y;
1258 if (math::abs(diff_alpha) > math::abs(diff_beta)) {
1259 // La variation est en x.
1260 if (next_info.m_alpha > old_sinfo.m_alpha) {
1261 if (m_is_debug)
1262 info() << "SUP_ALPHA SET NEXT uid=" << next_uid << " x=" << (x + 1) << " y=" << (y);
1263 next_info.setStructuration(x + 1, y);
1264 }
1265 else {
1266 if (m_is_debug)
1267 info() << "INF_ALPHA SET NEXT uid=" << next_uid << " x=" << (x - 1) << " y=" << (y);
1268 next_info.setStructuration(x - 1, y);
1269 }
1270 }
1271 else {
1272 // La variation est en y.
1273 if (next_info.m_beta > old_sinfo.m_beta) {
1274 if (m_is_debug)
1275 info() << "SUP_BETA SET NEXT uid=" << next_uid << " x=" << (x) << " y=" << (y + 1);
1276 next_info.setStructuration(x, y + 1);
1277 }
1278 else {
1279 if (m_is_debug)
1280 info() << "INF_BETA SET NEXT uid=" << next_uid << " x=" << (x) << " y=" << (y - 1);
1281 next_info.setStructuration(x, y - 1);
1282 }
1283 }
1284 old_sinfo = next_info;
1285 }
1286 }
1287}
1288
1289/*---------------------------------------------------------------------------*/
1290/*---------------------------------------------------------------------------*/
1291
1292void TiedInterfaceBuilder::
1293_printFaces(std::ostream& o, TiedInterfaceFaceMap& face_map)
1294{
1295 // Utilise une map pour trier les faces suivant leur uniqueId() afin
1296 // que l'affichage soit toujours le meme.
1297 typedef std::map<ItemUniqueId, TiedInterfaceFace*> FacesMap;
1298
1299 FacesMap faces;
1300 for (TiedInterfaceFaceMapEnumerator i(face_map); ++i;) {
1301 TiedInterfaceFace* mf = &i.m_current_data->value();
1302 faces.insert(std::make_pair(mf->uniqueId(), mf));
1303 }
1304
1305 for (FacesMap::const_iterator i(faces.begin()); i != faces.end(); ++i) {
1306 TiedInterfaceFace& mf = *(i->second);
1307 Integer nb_node = mf.nbNode();
1308 o << " face=" << mf.uniqueId() << " nb_node=" << nb_node
1309 << " center=" << mf.center() << '\n';
1310 for (Integer z = 0; z < nb_node; ++z) {
1311 ItemUniqueId nuid(mf.nodeUniqueId(z));
1312 o << " node uid=" << nuid << " coord=" << m_nodes_info[nuid].m_coord << '\n';
1313 }
1314 }
1315}
1316
1317/*---------------------------------------------------------------------------*/
1318/*---------------------------------------------------------------------------*/
1330{
1332 Integer nb_to_send = 0;
1333 RealUniqueArray coords;
1334 Int64UniqueArray unique_ids;
1335 IntegerUniqueArray nb_connected_master_faces;
1336 Int64UniqueArray connected_master_faces;
1337 for (NodeInfoListEnumerator i(m_nodes_info); ++i;) {
1338 const TiedInterfaceNodeInfo& ni = *i;
1339 ++nb_to_send;
1340 unique_ids.add(ni.uniqueId());
1341 coords.add(ni.m_coord.x);
1342 coords.add(ni.m_coord.y);
1343 coords.add(ni.m_coord.z);
1344 Integer nb_connected = ni.m_connected_master_faces.size();
1345 nb_connected_master_faces.add(nb_connected);
1346 for (Integer z = 0; z < nb_connected; ++z)
1347 connected_master_faces.add(ni.m_connected_master_faces[z]);
1348 }
1349
1350 IParallelMng* pm = m_mesh->parallelMng();
1351 Integer nb_rank = pm->commSize();
1352
1353 SerializeBuffer sbuf;
1354 sbuf.setMode(ISerializer::ModeReserve);
1355 sbuf.reserveInteger(1); // for the number of nodes
1356 sbuf.reserveInteger(1); // for the number of connected faces
1357 sbuf.reserve(DT_Int64, unique_ids.size()); // for the uniqueId() of the nodes
1358 sbuf.reserveInteger(nb_connected_master_faces.size()); // for the number of connected faces
1359 sbuf.reserve(DT_Int64, connected_master_faces.size()); // for the uniqueId() of the faces
1360 sbuf.reserve(DT_Real, coords.size());
1361
1362 sbuf.allocateBuffer();
1364 sbuf.putInteger(nb_to_send);
1365 sbuf.putInteger(connected_master_faces.size());
1366 sbuf.put(unique_ids);
1367 sbuf.put(nb_connected_master_faces);
1368 sbuf.put(connected_master_faces);
1369 sbuf.put(coords);
1370
1371 SerializeBuffer recv_buf;
1372 pm->allGather(&sbuf, &recv_buf);
1373 recv_buf.setMode(ISerializer::ModeGet);
1374
1375 for (Integer i = 0; i < nb_rank; ++i) {
1376 Integer nb_node = recv_buf.getInteger();
1377 Integer nb_connected_face = recv_buf.getInteger();
1378 unique_ids.resize(nb_node);
1379 nb_connected_master_faces.resize(nb_node);
1380 connected_master_faces.resize(nb_connected_face);
1381 coords.resize(nb_node * 3);
1382
1383 recv_buf.get(unique_ids);
1384 recv_buf.get(nb_connected_master_faces);
1385 recv_buf.get(connected_master_faces);
1386 recv_buf.get(coords);
1387
1388 // Iterates through all received faces and adds those that are missing,
1389 // adds them.
1390 Integer face_index = 0;
1391 for (Integer z = 0; z < nb_node; ++z) {
1392 Integer nb_face = nb_connected_master_faces[z];
1393 if (nb_face != 0) {
1394 ItemUniqueId uid(unique_ids[z]);
1395 NodeInfoList::Data* data = m_nodes_info.lookup(uid);
1396 if (data) {
1397 TiedInterfaceNodeInfo& ni = data->value();
1398 //info() << "RECEIVE NODE uid=" << uid << " nb_face=" << nb_face;
1399 for (Integer zz = 0; zz < nb_face; ++zz) {
1400 ItemUniqueId fuid(connected_master_faces[face_index + zz]);
1401 //info() << " FACE=" << fuid;
1402 ni.addConnectedFace(fuid);
1403 }
1404 }
1405 }
1406 face_index += nb_face;
1407 }
1408 }
1409 pm->barrier();
1410}
1411
1412/*---------------------------------------------------------------------------*/
1413/*---------------------------------------------------------------------------*/
1423 TiedInterfaceFaceMap& face_map)
1424{
1425 IParallelMng* pm = m_mesh->parallelMng();
1426 Int32 my_rank = pm->commRank();
1427 Int32 nb_rank = pm->commSize();
1428
1429 SerializeBuffer sbuf;
1430 sbuf.setMode(ISerializer::ModeReserve);
1431 Integer nb_to_send = faces_to_send.size();
1432
1433 Int64UniqueArray unique_ids(nb_to_send);
1434 Int64UniqueArray cells_unique_ids(nb_to_send);
1435 Int64UniqueArray nodes_unique_id;
1436 nodes_unique_id.reserve(nb_to_send * 4);
1437 IntegerUniqueArray nb_nodes(nb_to_send);
1438 RealUniqueArray coords;
1439 coords.reserve(3 * nb_to_send);
1440 RealUniqueArray nodes_coords;
1441 nodes_coords.reserve(3 * nb_to_send);
1442 for (Integer i = 0; i < nb_to_send; ++i) {
1443 const TiedInterfaceFace& mf = face_map[faces_to_send[i]];
1444 for (Integer z = 0, zs = mf.nbNode(); z < zs; ++z) {
1445 ItemUniqueId nuid(mf.nodeUniqueId(z));
1446 nodes_unique_id.add(nuid.asInt64());
1447 TiedInterfaceNodeInfo ni = m_nodes_info[nuid];
1448 nodes_coords.add(ni.m_coord.x);
1449 nodes_coords.add(ni.m_coord.y);
1450 nodes_coords.add(ni.m_coord.z);
1451 }
1452 unique_ids[i] = mf.uniqueId().asInt64();
1453 cells_unique_ids[i] = mf.cellUniqueId().asInt64();
1454 nb_nodes[i] = mf.nbNode();
1455
1456 coords.add(mf.center().x);
1457 coords.add(mf.center().y);
1458 coords.add(mf.center().z);
1459 }
1460 sbuf.reserveInteger(1); // for the number of faces
1461 sbuf.reserveInteger(1); // for the subdomain number
1462 sbuf.reserveInteger(1); // for the number of nodes in the list
1463 sbuf.reserve(DT_Int64, unique_ids.size()); // for the unique id of the faces
1464 sbuf.reserve(DT_Int64, cells_unique_ids.size()); // for the unique id of the face meshes
1465 sbuf.reserveInteger(nb_nodes.size()); // for the number of nodes
1466 sbuf.reserve(DT_Int64, nodes_unique_id.size()); // for the list of nodes
1467 sbuf.reserve(DT_Real, coords.size()); // for the center coordinates
1468 sbuf.reserve(DT_Real, nodes_coords.size()); // for the node coordinates
1469 sbuf.allocateBuffer();
1471 sbuf.putInteger(nb_to_send);
1472 sbuf.putInteger(my_rank);
1473 sbuf.putInteger(nodes_unique_id.size());
1474 sbuf.put(unique_ids);
1475 sbuf.put(cells_unique_ids);
1476 sbuf.put(nb_nodes);
1477 sbuf.put(nodes_unique_id);
1478 sbuf.put(coords);
1479 sbuf.put(nodes_coords);
1480
1481 SerializeBuffer recv_buf;
1482 pm->allGather(&sbuf, &recv_buf);
1483 recv_buf.setMode(ISerializer::ModeGet);
1484
1485 for (Integer i = 0; i < nb_rank; ++i) {
1486 Integer nb_face = recv_buf.getInteger();
1487 Integer sid = recv_buf.getInteger();
1488 Integer nb_node_unique_id = recv_buf.getInteger();
1489 //info() << " READ n=" << nb_face << " sid=" << sid;
1490 unique_ids.resize(nb_face);
1491 cells_unique_ids.resize(nb_face);
1492 nb_nodes.resize(nb_face);
1493 nodes_unique_id.resize(nb_node_unique_id);
1494 coords.resize(nb_face * 3);
1495 nodes_coords.resize(nb_node_unique_id * 3);
1496
1497 recv_buf.get(unique_ids);
1498 recv_buf.get(cells_unique_ids);
1499 recv_buf.get(nb_nodes);
1500 recv_buf.get(nodes_unique_id);
1501 recv_buf.get(coords);
1502 recv_buf.get(nodes_coords);
1503
1504 // Iterates through all received faces and adds those that are missing,
1505 // adds them.
1506 Integer node_index = 0;
1507 for (Integer z = 0; z < nb_face; ++z) {
1508 Integer nb_node = nb_nodes[z];
1509 ItemUniqueId uid(unique_ids[z]);
1510 ItemUniqueId cell_uid(cells_unique_ids[z]);
1511 if (!face_map.hasKey(uid)) {
1512 Real3 center;
1513 center.x = coords[z * 3];
1514 center.y = coords[z * 3 + 1];
1515 center.z = coords[z * 3 + 2];
1516 //info() << " RECV FACE: " << uid << " owner=" << sid << " center=" << center;
1517
1518 Integer data_index = m_face_info_mng.size();
1519 for (Integer zz = 0; zz < nb_node; ++zz) {
1520 ItemUniqueId nuid(nodes_unique_id[node_index + zz]);
1521 m_face_info_mng.add(nuid);
1522 // Adds the node to the list.
1523 TiedInterfaceNodeInfo ni(nuid);
1524 ni.m_coord.x = nodes_coords[(node_index + zz) * 3];
1525 ni.m_coord.y = nodes_coords[(node_index + zz) * 3 + 1];
1526 ni.m_coord.z = nodes_coords[(node_index + zz) * 3 + 2];
1527 //info() << "ADD NODE uid=" << nuid << " coord=" << ni.m_coord;
1528 m_nodes_info.add(nuid, ni);
1529 }
1530 TiedInterfaceFace sf(uid, cell_uid, nb_node, sid, data_index, &m_face_info_mng);
1531 sf.setCenter(center);
1532 face_map.add(uid, sf);
1533 }
1534 node_index += nb_node;
1535 }
1536 }
1537 pm->barrier();
1538}
1539
1540/*---------------------------------------------------------------------------*/
1541/*---------------------------------------------------------------------------*/
1556{
1557 IItemFamily* cell_family = m_mesh->cellFamily();
1558 IntegerUniqueArray cells_nb_connected(cell_family->maxLocalId());
1559 cells_nb_connected.fill(0);
1560 VariableItemInt32 cells_owner = cell_family->itemsNewOwner();
1561 {
1562 ENUMERATE_FACE (iface, m_slave_interface.own()) {
1563 Face face = *iface;
1564 const TiedInterfaceFace& slave_face = m_slave_faces[face.uniqueId()];
1565 ItemUniqueId master_face = m_slave_faces_master_face_uid[slave_face.uniqueId()];
1566 Integer master_owner = m_master_faces[master_face].owner();
1567 Cell slave_cell = face.cell(0);
1568 Int32 cell_lid = slave_cell.localId();
1569 ++cells_nb_connected[cell_lid];
1570 if (cells_nb_connected[cell_lid] > 1) {
1571 ARCANE_FATAL("Cell {0} is connected to more than one master face",
1572 ItemPrinter(slave_cell));
1573 }
1574 cells_owner[slave_cell] = master_owner;
1575 }
1576 }
1577}
1578
1579/*---------------------------------------------------------------------------*/
1580/*---------------------------------------------------------------------------*/
1593changeOwners(Int64Array& linked_cells, Int32Array& linked_owners)
1594{
1595 IItemFamily* cell_family = m_mesh->cellFamily();
1596 UniqueArray<ItemUniqueId> cells_last_master_uid(cell_family->maxLocalId());
1597 cells_last_master_uid.fill(ItemUniqueId());
1598 //VariableItemInt32 cells_owner = cell_family->itemsNewOwner();
1599 {
1600 ENUMERATE_FACE (iface, m_slave_interface.own()) {
1601 Face face = *iface;
1602 const TiedInterfaceFace& slave_face = m_slave_faces[face.uniqueId()];
1603 ItemUniqueId master_face = m_slave_faces_master_face_uid[slave_face.uniqueId()];
1604 Int32 master_owner = m_master_faces[master_face].owner();
1605 Cell slave_cell = face.cell(0);
1606 Int32 cell_lid = slave_cell.localId();
1607 ItemUniqueId last_master_uid = cells_last_master_uid[cell_lid];
1608 ItemUniqueId slave_face_cell_uid = face.cell(0).uniqueId();
1609 ItemUniqueId master_face_cell_uid = m_master_faces[master_face].cellUniqueId();
1610 // The first element must be the smallest uid
1611 if (slave_face_cell_uid < master_face_cell_uid) {
1612 linked_cells.add(slave_face_cell_uid);
1613 linked_cells.add(master_face_cell_uid);
1614 linked_owners.add(face.owner());
1615 }
1616 else {
1617 linked_cells.add(master_face_cell_uid);
1618 linked_cells.add(slave_face_cell_uid);
1619 linked_owners.add(master_owner);
1620 }
1621 if (last_master_uid != NULL_ITEM_UNIQUE_ID) {
1622 // Mesh connected to several master faces.
1623 // Checks that they are all in the same subdomain.
1624 Int32 last_master_owner = m_master_faces[last_master_uid].owner();
1625 if (last_master_owner != master_owner)
1626 ARCANE_FATAL("Cell {0} is connected to more than one master face:"
1627 " face1={1} owner1={2} face2={3} owner2={4}",
1628 ItemPrinter(slave_cell),
1629 last_master_uid, last_master_owner, master_face, master_owner);
1630 }
1631 cells_last_master_uid[cell_lid] = master_face;
1632 }
1633 }
1634}
1635
1636/*---------------------------------------------------------------------------*/
1637/*---------------------------------------------------------------------------*/
1646computeInterfaceConnections(bool allow_communication)
1647{
1648 IParallelMng* pm = m_mesh->parallelMng();
1649 Int32 my_rank = pm->commRank();
1650
1652
1653 // In parallel, it is necessary to send the master surface info to everyone.
1654 if (allow_communication) {
1655 UniqueArray<ItemUniqueId> master_faces_to_send;
1656 for (TiedInterfaceFaceMapEnumerator i(m_master_faces); ++i;) {
1657 TiedInterfaceFace& sf = *i;
1658 if (sf.owner() == my_rank)
1659 master_faces_to_send.add(sf.uniqueId());
1660 }
1661 _gatherFaces(master_faces_to_send, m_master_faces);
1662 }
1663
1664#if 0
1665 if (allow_communication && arcaneIsCheck()){
1666 String fname = "master_face_";
1667 fname += m_slave_interface.name();
1668 if (is_parallel){
1669 fname += ".";
1670 fname += pm->commRank();
1671 }
1672 ofstream ofile(fname.localstr());
1673 _printFaces(ofile,m_master_faces);
1674 }
1675#endif
1676
1677 {
1678 UniqueArray<ItemUniqueId> slave_faces_to_process;
1679 for (TiedInterfaceFaceMapEnumerator i(m_slave_faces); ++i;) {
1680 slave_faces_to_process.add((*i).uniqueId());
1681 }
1682
1683 UniqueArray<ItemUniqueId> remaining_slave_faces;
1684 //TODO delete the 10000
1685 for (Integer zz = 0; zz < 10000; ++zz) {
1686 if (allow_communication) {
1687 info() << " SEND RECV NODES INFO n=" << zz;
1689 }
1690 //slave_faces_to_process.resize(remaining_slave_faces_index.size());
1691 //slave_faces_to_process.copy(remaining_slave_faces_index);
1692 //warning() << " SEARCH: NB=" << slave_faces_to_proceed.size();
1693 remaining_slave_faces.clear();
1694 _searchMasterFaces(slave_faces_to_process, remaining_slave_faces);
1695 Integer nb_remaining = remaining_slave_faces.size();
1696 Integer nb_to_process = slave_faces_to_process.size();
1697 if (allow_communication) {
1698 info() << "NB REMAINING n=" << nb_remaining;
1699 nb_remaining = pm->reduce(Parallel::ReduceSum, nb_remaining);
1700 info() << "CUMULATIVE NB REMAINING n=" << nb_remaining;
1701 nb_to_process = pm->reduce(Parallel::ReduceSum, nb_to_process);
1702 }
1703 if (nb_remaining == 0)
1704 break;
1705 if (nb_remaining == nb_to_process) {
1706 ARCANE_FATAL("Can not compute master/slave infos for a tied interface. Remaining_slaves={0}",
1707 nb_remaining);
1708 }
1709 slave_faces_to_process.copy(remaining_slave_faces);
1710 }
1711 }
1712}
1713
1714/*---------------------------------------------------------------------------*/
1715/*---------------------------------------------------------------------------*/
1726computeInterfaceInfos(TiedInterfaceBuilderInfos& infos, bool is_structured)
1727{
1729 _computeProjectionInfos(infos, is_structured);
1730}
1731
1732/*---------------------------------------------------------------------------*/
1733/*---------------------------------------------------------------------------*/
1734
1735/*---------------------------------------------------------------------------*/
1736/*---------------------------------------------------------------------------*/
1737
1738bool TiedInterface::m_is_debug = false;
1739
1740/*---------------------------------------------------------------------------*/
1741/*---------------------------------------------------------------------------*/
1742
1743TiedInterface::
1744TiedInterface(IMesh* mesh)
1745: TraceAccessor(mesh->traceMng())
1746, m_mesh(mesh)
1747, m_planar_tolerance(0.)
1748{
1749 if (!platform::getEnvironmentVariable("ARCANE_DEBUG_TIED_INTERFACE").null())
1750 m_is_debug = true;
1751}
1752
1753/*---------------------------------------------------------------------------*/
1754/*---------------------------------------------------------------------------*/
1755
1756TiedInterface::
1757~TiedInterface()
1758{
1759}
1760
1761/*---------------------------------------------------------------------------*/
1762/*---------------------------------------------------------------------------*/
1763
1764/*---------------------------------------------------------------------------*/
1765/*---------------------------------------------------------------------------*/
1766
1769masterInterface() const
1770{
1771 return m_master_interface;
1772}
1773
1776slaveInterface() const
1777{
1778 return m_slave_interface;
1779}
1780
1782masterInterfaceName() const
1783{
1784 return m_master_interface_name;
1785}
1786
1788slaveInterfaceName() const
1789{
1790 return m_slave_interface_name;
1791}
1792
1793TiedInterfaceNodeList TiedInterface::
1794tiedNodes() const
1795{
1796 return m_tied_nodes;
1797}
1798
1799TiedInterfaceFaceList TiedInterface::
1800tiedFaces() const
1801{
1802 return m_tied_faces;
1803}
1804
1805void TiedInterface::
1806resizeNodes(IntegerConstArrayView new_sizes)
1807{
1808 m_tied_nodes.resize(new_sizes);
1809}
1810
1811void TiedInterface::
1812resizeFaces(IntegerConstArrayView new_sizes)
1813{
1814 m_tied_faces.resize(new_sizes);
1815}
1816
1817void TiedInterface::
1818setNodes(Integer index, ConstArrayView<TiedNode> nodes)
1819{
1820 for (Integer i = 0, is = nodes.size(); i < is; ++i)
1821 m_tied_nodes[index][i] = nodes[i];
1822}
1823
1824void TiedInterface::
1825setFaces(Integer index, ConstArrayView<TiedFace> faces)
1826{
1827 for (Integer i = 0, is = faces.size(); i < is; ++i)
1828 m_tied_faces[index][i] = faces[i];
1829}
1830
1831/*---------------------------------------------------------------------------*/
1832/*---------------------------------------------------------------------------*/
1833
1834class TiedInterfacePartitionConstraint
1836{
1837 public:
1838
1839 TiedInterfacePartitionConstraint(IMesh* mesh, ConstArrayView<FaceGroup> slave_interfaces, bool is_debug)
1840 : m_mesh(mesh)
1841 , m_slave_interfaces(slave_interfaces)
1842 , m_is_debug(is_debug)
1843 , m_is_initial(true)
1844 {
1845 }
1846
1847 public:
1848
1849 virtual void addLinkedCells(Int64Array& linked_cells, Int32Array& linked_owners)
1850 {
1851 IParallelMng* pm = m_mesh->parallelMng();
1852 ITraceMng* tm = pm->traceMng();
1853 // It is necessary to perform the communications only for the initial partitioning because subsequently
1854 // the faces on both sides of a connection are in the same subdomain.
1855 if (m_is_initial) {
1856 Integer nb_interface = m_slave_interfaces.size();
1857 for (Integer i = 0; i < nb_interface; ++i) {
1858 TiedInterfaceBuilder builder(m_mesh, m_slave_interfaces[i], false, m_is_debug);
1859 builder.computeInterfaceConnections(true);
1860 builder.changeOwners(linked_cells, linked_owners);
1861 }
1862 }
1863 else {
1864 TiedInterfaceCollection tied_interfaces = m_mesh->tiedInterfaces();
1865 for (TiedInterfaceCollection::Enumerator itied(tied_interfaces); ++itied;) {
1866 _addLinkedCells(*itied, linked_cells, linked_owners);
1867 }
1868 }
1869 tm->info() << "NB_LINKED_CELL=" << linked_cells.size();
1870 }
1871
1872 virtual void setInitialRepartition(bool is_initial)
1873 {
1874 m_is_initial = is_initial;
1875 }
1876
1877 void _addLinkedCells(ITiedInterface* interface, Int64Array& linked_cells, Int32Array& linked_owners)
1878 {
1879 FaceGroup master_interface = interface->masterInterface();
1880 //TiedInterfaceFaceList tied_faces = interface->tiedFaces();
1881 ENUMERATE_FACE (iface, master_interface) {
1882 Face face = *iface;
1883 Cell cell = face.cell(0);
1884 Int64 cell_uid = cell.uniqueId();
1885 Int32 owner = cell.owner();
1886 for (Face isubface : face.slaveFaces()) {
1887 Cell sub_cell = isubface.cell(0);
1888 Int64 sub_cell_uid = sub_cell.uniqueId();
1889 if (sub_cell_uid < cell_uid) {
1890 linked_cells.add(sub_cell_uid);
1891 linked_cells.add(cell_uid);
1892 linked_owners.add(owner);
1893 }
1894 else {
1895 linked_cells.add(cell_uid);
1896 linked_cells.add(sub_cell_uid);
1897 linked_owners.add(owner);
1898 }
1899 }
1900 }
1901 }
1902
1903 private:
1904
1905 IMesh* m_mesh;
1906 UniqueArray<FaceGroup> m_slave_interfaces;
1907 bool m_is_debug;
1908 bool m_is_initial;
1909};
1910
1911/*---------------------------------------------------------------------------*/
1912/*---------------------------------------------------------------------------*/
1921
1922/*---------------------------------------------------------------------------*/
1923/*---------------------------------------------------------------------------*/
1928build(const FaceGroup& slave_interface, bool is_structured)
1929{
1930 info() << "Compute information for the tied interface " << slave_interface.name();
1931
1932 TiedInterfaceBuilder builder(m_mesh, slave_interface, true, m_is_debug);
1934
1935 builder.setPlanarTolerance(m_planar_tolerance);
1936 builder.computeInterfaceConnections(false);
1937 builder.computeInterfaceInfos(infos, is_structured);
1938
1939 //infos.printInfos();
1940
1941 m_slave_interface = slave_interface.own();
1942 m_slave_interface_name = slave_interface.name();
1943 m_master_interface = builder.masterInterface().own();
1944 m_master_interface_name = builder.masterInterface().name();
1945
1946 {
1947 Integer nb_master_face = infos.m_master_faces_uid.size();
1948 m_tied_nodes.resize(infos.m_master_faces_nb_slave_node);
1949 m_tied_faces.resize(infos.m_master_faces_nb_slave_face);
1950
1951 IItemFamily* node_family = m_mesh->itemFamily(IK_Node);
1952 IItemFamily* face_family = m_mesh->itemFamily(IK_Face);
1953
1954 Int32UniqueArray slave_nodes_lid(infos.m_slave_nodes_uid.size());
1955 node_family->itemsUniqueIdToLocalId(slave_nodes_lid, infos.m_slave_nodes_uid);
1956 NodeInfoListView nodes(node_family);
1957
1958 Int32UniqueArray slave_faces_lid(infos.m_slave_faces_uid.size());
1959 face_family->itemsUniqueIdToLocalId(slave_faces_lid, infos.m_slave_faces_uid);
1960 FaceInfoListView faces(face_family);
1961
1962 for (Integer i_master = 0; i_master < nb_master_face; ++i_master) {
1963 Integer nb_slave_node = infos.m_master_faces_nb_slave_node[i_master];
1964 Integer nb_slave_face = infos.m_master_faces_nb_slave_face[i_master];
1965 if (m_is_debug)
1966 info() << "Master Face: " << infos.m_master_faces_uid[i_master]
1967 << " nb_slave_face=" << nb_slave_face
1968 << " nb_slave_node=" << nb_slave_node
1969 << " node_index=" << infos.m_master_faces_slave_node_index[i_master];
1970 for (Integer zz = 0; zz < nb_slave_node; ++zz) {
1971 Integer first_index = infos.m_master_faces_slave_node_index[i_master];
1972
1973 if (m_is_debug)
1974 info() << "Node: uid=" << infos.m_slave_nodes_uid[first_index + zz]
1975 << " uv=" << infos.m_slave_nodes_iso[first_index + zz];
1976 Integer local_id = slave_nodes_lid[first_index + zz];
1977 TiedNode tn(zz, nodes[local_id], infos.m_slave_nodes_iso[first_index + zz]);
1978 m_tied_nodes[i_master][zz] = tn;
1979 }
1980
1981 for (Integer zz = 0; zz < nb_slave_face; ++zz) {
1982 Integer first_index = infos.m_master_faces_slave_face_index[i_master];
1983
1984 if (m_is_debug)
1985 info() << "Face: uid=" << infos.m_slave_faces_uid[first_index + zz];
1986 Integer local_id = slave_faces_lid[first_index + zz];
1987 m_tied_faces[i_master][zz] = TiedFace(zz, faces[local_id]);
1988 }
1989 }
1990 }
1991}
1992
1993/*---------------------------------------------------------------------------*/
1994/*---------------------------------------------------------------------------*/
1995
1998{
1999 m_planar_tolerance = tol;
2000}
2001
2002/*---------------------------------------------------------------------------*/
2003/*---------------------------------------------------------------------------*/
2004
2005void TiedInterface::
2006reload(IItemFamily* face_family,
2007 const String& master_interface_name,
2008 const String& slave_interface_name)
2009{
2010 m_master_interface_name = master_interface_name;
2011 m_slave_interface_name = slave_interface_name;
2012 ItemGroup group = face_family->findGroup(master_interface_name);
2013 if (group.null())
2014 ARCANE_FATAL("Can not find master group named '{0}'", master_interface_name);
2015 m_master_interface = group.own();
2016 group = face_family->findGroup(slave_interface_name);
2017 if (group.null())
2018 ARCANE_FATAL("Can not find slave group named '{0}'", slave_interface_name);
2019 m_slave_interface = group.own();
2020}
2021
2022/*---------------------------------------------------------------------------*/
2023/*---------------------------------------------------------------------------*/
2024
2025void TiedInterface::
2026rebuild(ITiedInterfaceRebuilder* rebuilder,
2027 IntegerConstArrayView nb_slave_node,
2028 IntegerConstArrayView nb_slave_face)
2029{
2030 info() << "REBUILD_TIED_INTERFACE name=" << m_master_interface.name();
2031 m_tied_nodes.resize(nb_slave_node);
2032 m_tied_faces.resize(nb_slave_face);
2033
2034 IItemFamily* node_family = m_mesh->itemFamily(IK_Node);
2035 IItemFamily* face_family = m_mesh->itemFamily(IK_Face);
2036
2037 NodeInfoListView nodes(node_family);
2038 FaceInfoListView faces(face_family);
2039
2040 Integer master_index = 0;
2041 Int32UniqueArray work_nodes_local_id;
2042 Real2UniqueArray work_nodes_iso;
2043 Int32UniqueArray work_faces_local_id;
2044
2045 ENUMERATE_FACE (iface, m_master_interface) {
2046 Face face = *iface;
2047 ArrayView<TiedNode> face_tied_nodes = m_tied_nodes[master_index];
2048 ArrayView<TiedFace> face_tied_faces = m_tied_faces[master_index];
2049 ++master_index;
2050
2051 info(4) << "NEW VALUES face=" << ItemPrinter(face) << " n=" << face_tied_nodes.size() << " m=" << face_tied_faces.size();
2052 for (Node inode : face.nodes())
2053 info(4) << "MasterFace node=" << ItemPrinter(inode);
2054 Integer nb_node = face_tied_nodes.size();
2055 Integer nb_face = face_tied_faces.size();
2056 work_nodes_local_id.resize(nb_node);
2057 work_nodes_iso.resize(nb_node);
2058 work_faces_local_id.resize(nb_face);
2059
2060 rebuilder->fillTiedInfos(face, work_nodes_local_id, work_nodes_iso, work_faces_local_id);
2061
2062 for (Integer zz = 0; zz < nb_node; ++zz) {
2063 Integer local_id = work_nodes_local_id[zz];
2064 Real2 iso = work_nodes_iso[zz];
2065 info(4) << "NEW NODE slave_node=" << ItemPrinter(nodes[local_id]) << " iso=" << iso;
2066 face_tied_nodes[zz] = TiedNode(zz, nodes[local_id], iso);
2067 }
2068
2069 for (Integer zz = 0; zz < nb_face; ++zz) {
2070 Int32 local_id = work_faces_local_id[zz];
2071 info(4) << "NEW FACE slave_face=" << ItemPrinter(faces[local_id]);
2072 face_tied_faces[zz] = TiedFace(zz, faces[local_id]);
2073 }
2074 }
2075}
2076
2077/*---------------------------------------------------------------------------*/
2078/*---------------------------------------------------------------------------*/
2079
2080void TiedInterface::
2081checkValid()
2082{
2083 _checkValid(false);
2084}
2085
2086/*---------------------------------------------------------------------------*/
2087/*---------------------------------------------------------------------------*/
2088
2089void TiedInterface::
2090_checkValid(bool is_print)
2091{
2092 Integer nb_error = 0;
2093 Integer max_print_error = 50;
2094 std::set<Int64> nodes_in_master_face;
2095 ITiedInterface* interface = this;
2096 FaceGroup slave_group = interface->slaveInterface();
2097 FaceGroup master_group = interface->masterInterface();
2098 info() << "Interface: Slave=" << slave_group.name()
2099 << " nb_face=" << slave_group.size();
2100 info() << "Interface: Master=" << master_group.name()
2101 << " nb_face=" << master_group.size();
2102 TiedInterfaceNodeList tied_nodes(interface->tiedNodes());
2103 TiedInterfaceFaceList tied_faces(interface->tiedFaces());
2104 ENUMERATE_FACE (iface, master_group) {
2105 Face face = *iface;
2106 Int32 master_face_owner = face.owner();
2107 FaceVectorView slave_faces = face.slaveFaces();
2108 if (!face.isMasterFace()) {
2109 ++nb_error;
2110 if (nb_error < max_print_error)
2111 error() << " Face uid=" << ItemPrinter(face) << " should have isMaster() true";
2112 }
2113 if (iface.index() > 100000)
2114 break;
2115 nodes_in_master_face.clear();
2116 if (is_print)
2117 info() << "Master face uid=" << ItemPrinter(face)
2118 << " kind=" << face.kind()
2119 << " cell=" << ItemPrinter(face.cell(0))
2120 << " iface.index()=" << iface.index();
2121
2122 Int32 cell_face_owner = face.cell(0).owner();
2123 if (cell_face_owner != master_face_owner) {
2124 ++nb_error;
2125 if (nb_error < max_print_error)
2126 error() << "master_face and its cell do not have the same owner: face_owner=" << master_face_owner
2127 << " cell_owner=" << cell_face_owner;
2128 }
2129 if (is_print)
2130 for (Node inode : face.nodes())
2131 info() << "Master face node uid=" << inode.uniqueId();
2132 for (Integer zz = 0, zs = tied_nodes[iface.index()].size(); zz < zs; ++zz) {
2133 TiedNode tn = tied_nodes[iface.index()][zz];
2134 nodes_in_master_face.insert(tn.node().uniqueId());
2135 if (is_print) {
2136 info() << " node_uid=" << tn.node().uniqueId()
2137 << " iso=" << tn.isoCoordinates()
2138 << " kind=" << tn.node().kind();
2139 }
2140 }
2141 for (Node inode : face.nodes())
2142 if (nodes_in_master_face.find(inode.uniqueId()) == nodes_in_master_face.end()) {
2143 ++nb_error;
2144 if (nb_error < max_print_error)
2145 error() << "node in master face not in slave node list node=" << ItemPrinter(inode);
2146 }
2147 Integer nb_tied = tied_faces[iface.index()].size();
2148 if (nb_tied != slave_faces.size()) {
2149 ++nb_error;
2150 if (nb_error < max_print_error) {
2151 error() << "face=" << ItemPrinter(face) << " bad number of slave faces interne="
2152 << slave_faces.size() << " struct=" << nb_tied;
2153 ENUMERATE_FACE (islaveface, slave_faces) {
2154 info() << "SLAVE " << ItemPrinter(*islaveface);
2155 }
2156 }
2157 }
2158 for (Integer zz = 0, zs = tied_faces[iface.index()].size(); zz < zs; ++zz) {
2159 TiedFace tf = tied_faces[iface.index()][zz];
2160 Face tied_slave_face = tf.face();
2161 if (!tied_slave_face.isSlaveFace()) {
2162 ++nb_error;
2163 if (nb_error < max_print_error)
2164 error() << "slave face uid=" << ItemPrinter(tf.face()) << " should have isSlave() true";
2165 }
2166 if (tied_slave_face.masterFace() != face) {
2167 ++nb_error;
2168 if (nb_error < max_print_error)
2169 error() << "slave face uid=" << ItemPrinter(tf.face()) << " should have masterSlave() valid";
2170 }
2171 if (tied_slave_face != slave_faces[zz]) {
2172 ++nb_error;
2173 if (nb_error < max_print_error)
2174 error() << "bad slave face internal=" << ItemPrinter(slave_faces[zz])
2175 << " struct=" << ItemPrinter(tied_slave_face);
2176 }
2177 Int32 slave_face_owner = tf.face().owner();
2178 if (slave_face_owner != master_face_owner) {
2179 ++nb_error;
2180 if (nb_error < max_print_error)
2181 error() << "master_face and its slave_face do not have the same owner:"
2182 << " master_face=" << ItemPrinter(face)
2183 << " master_cell=" << ItemPrinter(face.cell(0))
2184 << " slave_face=" << ItemPrinter(tf.face())
2185 << " slave_cell=" << ItemPrinter(tf.face().cell(0));
2186 }
2187 if (is_print) {
2188 info() << " face_uid=" << tf.face().uniqueId() << " cell=" << ItemPrinter(tf.face().cell(0));
2189 }
2190 }
2191 }
2192
2193 if (nb_error != 0) {
2194 ARCANE_FATAL("Errors in tied interface nb_error={0}", nb_error);
2195 }
2196}
2197
2198/*---------------------------------------------------------------------------*/
2199/*---------------------------------------------------------------------------*/
2200
2201} // End namespace Arcane::mesh
2202
2203/*---------------------------------------------------------------------------*/
2204/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
Tableau d'items de types quelconques.
void fill(const DataType &data)
Remplissage du tableau.
void clear()
Supprime les éléments du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void copy(Span< const T > rhs)
Copie les valeurs de rhs dans l'instance.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
void put(Span< const Real > values) override
Ajoute le tableau values.
void reserve(eBasicDataType dt, Int64 n) override
Réserve de la mémoire pour n objets de type dt.
void allocateBuffer() override
Alloue la mémoire du sérialiseur.
Integer getInteger() override
Récupère une taille.
void get(ArrayView< Real > values) override
Récupère le tableau values.
void setMode(eMode new_mode) override
Positionne le fonctionnement actuel.
void putInteger(Integer value) override
Ajoute l'entier value.
Maille d'un maillage.
Definition Item.h:1214
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:964
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1665
FaceConnectedListViewType slaveFaces() const
Liste des faces esclaves associées à cette face maître.
Definition Item.h:1143
Informations sur la projection d'un point sur un segment ou un triangle.
static ProjectionInfo projection(Real3 v1, Real3 v2, Real3 v3, Real3 point)
Projection du point point au triangle défini par v1, v2 et v3.
int m_region
Région dans laquelle se situe la projection (0 si intérieur au segment ou au triangle).
static bool isInside(Real3 v1, Real3 v2, Real3 v3, Real3 point)
Indique si un la projection du point point est à l'intérieur du triangle défini par v1,...
Real m_distance
Distance du point à sa projection.
Enumerateur sur un HashTableMap.
Table de hachage pour tableaux associatifs.
Data * lookup(KeyTypeConstRef id)
Recherche la valeur correspondant à la clé id.
bool add(KeyTypeConstRef id, const ValueType &value)
Ajoute la valeur value correspondant à la clé id.
bool hasKey(KeyTypeConstRef id)
true si une valeur avec la clé id est présente
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroup findGroup(const String &name) const =0
Recherche un groupe.
virtual Int32 maxLocalId() const =0
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable contenant le numéro du nouveau sous-domaine propriétaire de l'entité.
virtual IItemFamily * itemFamily(eItemKind ik)=0
Retourne la famille d'entité de type ik.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
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 barrier()=0
Effectue une barière.
@ ModePut
Le sérialiseur attend des reserve().
Interface d'un classe gérant une semi-conformité du maillage.
virtual TiedInterfaceFaceList tiedFaces() const =0
Liste des informations sur les faces esclaves d'une face maître.
virtual FaceGroup masterInterface() const =0
Groupe contenant les faces maîtres.
virtual FaceGroup slaveInterface() const =0
Groupe contenant les faces esclaves.
virtual TiedInterfaceNodeList tiedNodes() const =0
Liste des informations sur les noeuds esclaves d'une face maître.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Definition ItemGroup.cc:190
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:34
Identifiant unique d'une entité.
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
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:582
Classe gérant un vecteur de réel de dimension 2.
Definition Real2.h:121
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Implémentation d'un tampon pour la sérialisation.
Vecteur 1D de données avec sémantique par référence.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
Face semi-conforme du maillage.
Definition TiedFace.h:34
Noeud semi-conforme du maillage.
Definition TiedNode.h:39
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage warning() const
Flot pour un message d'avertissement.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
IntegerUniqueArray m_master_faces_nb_slave_node
Number of slave nodes for each master face.
Real2UniqueArray m_slave_nodes_iso
List of iso-barycentric coordinates of slave nodes.
UniqueArray< ItemUniqueId > m_slave_nodes_uid
List of uniqueId() of slave nodes.
IntegerUniqueArray m_master_faces_nb_slave_face
Number of slave faces for each master face.
UniqueArray< ItemUniqueId > m_slave_faces_uid
List of uniqueId() of slave faces.
UniqueArray< ItemUniqueId > m_master_faces_uid
List of uniqueId() of master faces.
Construction of semi-conformal interface information.
void computeInterfaceConnections(bool allow_communication)
Builds the info for a linked interface.
HashTableMapT< ItemUniqueId, ItemUniqueId > m_slave_faces_master_face_uid
Table indicating for each slave face, the uid of the corresponding master face.
void _computeMasterInterface()
Determines the master surface of the interface.
void changeOwners(Int64Array &linked_cells, Int32Array &linked_owers)
Positions the links between meshes.
void _gatherFaces(ConstArrayView< ItemUniqueId > faces_to_send, TiedInterfaceFaceMap &face_map)
void _gatherAllNodesInfo()
envoie et récupère les informations sur les noeuds de l'interface.
void computeInterfaceInfos(TiedInterfaceBuilderInfos &infos, bool is_structured)
Migrates the meshes on the links.
GeometricUtilities::ProjectionInfo _findProjection(const TiedInterfaceFace &face, Real3 point)
Calculates the projection of a point onto a face.
void _removeMasterFacesWithNoSlave()
Removes from the group of master faces those that are connected to any slave face.
void changeOwnersOld()
Migrates the meshes on the links.
Master or slave face of an interface.
ItemUniqueId m_unique_id
ID of this node.
Real3 m_coord
Coordinates of this node.
SharedArray< ItemUniqueId > m_connected_master_faces
List of uniqueId() of master faces to which this node can be connected.
virtual void addLinkedCells(Int64Array &linked_cells, Int32Array &linked_owners)
Ajoute un ensemble de contraintes sur les mailles.
virtual FaceGroup slaveInterface() const
Group containing the slave faces.
virtual String slaveInterfaceName() const
Nom du groupe contenant les mailles esclaves.
static PartitionConstraintBase * createConstraint(IMesh *mesh, ConstArrayView< FaceGroup > slave_interfaces)
Creates information for the tied interface slave_interface/.
virtual void setPlanarTolerance(Real tol)
Defines the relative acceptance threshold for a point projected onto a candidate face.
virtual String masterInterfaceName() const
Nom du groupe contenant les mailles maîtres.
virtual void build(const FaceGroup &interface, bool is_structured)
Builds the tied interface on the group interface.
virtual TiedInterfaceFaceList tiedFaces() const
Liste des informations sur les faces esclaves d'une face maître.
virtual FaceGroup masterInterface() const
Group containing the master faces.
virtual TiedInterfaceNodeList tiedNodes() const
Liste des informations sur les noeuds esclaves d'une face maître.
__host__ __device__ Real3 vecMul(Real3 u, Real3 v)
Produit vectoriel de u par v. dans .
Definition MathUtils.h:52
__host__ __device__ Real scaMul(Real2 u, Real2 v)
Produit scalaire de u par v dans .
Definition MathUtils.h:113
__host__ __device__ Real3 normalizeReal3(Real3 v)
Normalisation d'un Real3.
Definition MathUtils.h:741
__host__ __device__ Real mixteMul(Real3 u, Real3 v, Real3 w)
Produit mixte de u, v et w.
Definition MathUtils.h:159
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemVectorViewT< Face > FaceVectorView
Vue sur un vecteur de faces.
Definition ItemTypes.h:299
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
@ ReduceSum
Somme des valeurs.
Real normeR3(Real3 v1)
Norme d'un vecteur.
Definition MathUtils.h:653
String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:125
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:339
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
UniqueArray< Real3 > Real3UniqueArray
Tableau dynamique à une dimension de vecteurs de rang 3.
Definition UtilsTypes.h:363
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:349
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Face
Entité de maillage de genre face.
double Real
Type représentant un réel.
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:127
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
@ DT_Real
Donnée de type réel.
Definition DataTypes.h:41
UniqueArray< Real2 > Real2UniqueArray
Tableau dynamique à une dimension de vecteurs de rang 2.
Definition UtilsTypes.h:361
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:347
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:486
Collection< ITiedInterface * > TiedInterfaceCollection
Collection d'interfaces liées.
std::int32_t Int32
Type entier signé sur 32 bits.
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