Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshUtils.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* MeshUtils.cc (C) 2000-2024 */
9/* */
10/* Fonctions diverses sur les éléments du maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/CheckedConvert.h"
15#include "arcane/utils/List.h"
16#include "arcane/utils/ScopedPtr.h"
17#include "arcane/utils/OStringStream.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/JSONWriter.h"
21#include "arcane/utils/IHashAlgorithm.h"
22
24#include "arcane/core/IVariableMng.h"
25#include "arcane/core/VariableTypes.h"
26#include "arcane/core/ISubDomain.h"
27#include "arcane/core/StdNum.h"
28#include "arcane/core/MeshVariableInfo.h"
29#include "arcane/core/Variable.h"
30#include "arcane/core/IMesh.h"
31#include "arcane/core/IMeshSubMeshTransition.h"
33#include "arcane/core/ItemGroup.h"
34#include "arcane/core/Item.h"
35#include "arcane/core/ItemCompare.h"
36#include "arcane/core/ItemPrinter.h"
38#include "arcane/core/XmlNode.h"
39#include "arcane/core/XmlNodeList.h"
40#include "arcane/core/IParallelMng.h"
41#include "arcane/core/IIOMng.h"
42#include "arcane/core/IXmlDocumentHolder.h"
43#include "arcane/core/IItemFamily.h"
44#include "arcane/core/VariableCollection.h"
45#include "arcane/core/ITiedInterface.h"
46#include "arcane/core/SharedVariable.h"
47#include "arcane/core/MeshVisitor.h"
48#include "arcane/core/IVariableSynchronizer.h"
49#include "arcane/core/UnstructuredMeshConnectivity.h"
50#include "arcane/core/datatype/DataAllocationInfo.h"
51
53
54#include <algorithm>
55#include <map>
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60namespace Arcane
61{
62using impl::ItemBase;
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67// #define ARCANE_DEBUG_MESH
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72template <class ValueType> inline void
73_writeValue(ITraceMng* trace, const String& name, ValueType v)
74{
76 trace->pinfo() << name << Trace::Width(wl) << v;
77}
78
79template <> inline void
80_writeValue(ITraceMng* trace, const String& name, Real3 v)
81{
83 trace->pinfo() << name << ".x" << Trace::Width(wl) << v.x;
84 trace->pinfo() << name << ".y" << Trace::Width(wl) << v.y;
85 trace->pinfo() << name << ".z" << Trace::Width(wl) << v.z;
86}
87
88template <> inline void
89_writeValue(ITraceMng* trace, const String& name, Real3x3 v)
90{
92 trace->pinfo() << name << ".xx" << Trace::Width(wl) << v.x.x;
93 trace->pinfo() << name << ".xy" << Trace::Width(wl) << v.x.y;
94 trace->pinfo() << name << ".xz" << Trace::Width(wl) << v.x.z;
95
96 trace->pinfo() << name << ".yx" << Trace::Width(wl) << v.y.x;
97 trace->pinfo() << name << ".yy" << Trace::Width(wl) << v.y.y;
98 trace->pinfo() << name << ".yz" << Trace::Width(wl) << v.y.z;
99
100 trace->pinfo() << name << ".zx" << Trace::Width(wl) << v.z.x;
101 trace->pinfo() << name << ".zy" << Trace::Width(wl) << v.z.y;
102 trace->pinfo() << name << ".zz" << Trace::Width(wl) << v.z.z;
103}
104
105template <class ItemType, class ValueType> inline void
106_writeInfo(ISubDomain* mng, const VariableCollection& variables, const ItemType& item)
107{
108 typedef typename MeshVariableInfoT<ItemType, ValueType, 0>::PrivateType VariableScalarTrueType;
109 typedef typename MeshVariableInfoT<ItemType, ValueType, 1>::PrivateType VariableArrayTrueType;
110
111 ITraceMng* trace = mng->traceMng();
113
114 for (VariableCollection::Enumerator i(variables); ++i;) {
115 IVariable* vp = *i;
116 // Pour l'instant, n'affiche pas les variables partielles
117 if (vp->isPartial())
118 continue;
119 // Vérifie qu'il s'agit bien d'une variable du maillage et du bon genre
120 ItemGroup group = vp->itemGroup();
121 if (group.itemKind() != item_kind)
122 continue;
123
124 const String& name = vp->name();
125 auto* v = dynamic_cast<VariableScalarTrueType*>(vp);
126 if (v) {
127 ConstArrayView<ValueType> values = v->valueView();
128 if (values.size() < item.localId()) {
129 trace->error() << "Invalid dimensions for variable '" << name << "' "
130 << "(size=" << values.size() << " index=" << item.localId();
131 continue;
132 }
133 _writeValue(trace, name, values[item.localId()]);
134 }
135
136 auto* v2 = dynamic_cast<VariableArrayTrueType*>(vp);
137 if (v2) {
138 Array2View<ValueType> values = v2->valueView();
139 Integer lid = item.localId();
140 if (values.dim1Size() < lid) {
141 trace->error() << "Invalid dimensions for variable '" << name << "' "
142 << "(size=" << values.dim1Size() << " index=" << lid;
143 continue;
144 }
145 Integer n = values[lid].size();
146 for (Integer z = 0; z < n; ++z) {
147 _writeValue(trace, name + "[" + z + "]", values[lid][z]);
148 }
149 }
150 }
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156void MeshUtils::
157writeMeshItemInfo(ISubDomain* sd, Cell cell, bool depend_info)
158{
159 ITraceMng* trace = sd->traceMng();
160 Integer sid = sd->subDomainId();
161 StringBuilder buf("Info-");
162 buf += sid;
163 Trace::Setter mci(trace, buf.toString());
164
165 VariableCollection variables(sd->variableMng()->usedVariables());
166
167 Integer nb_node = cell.nbNode();
168 Integer nb_edge = cell.nbEdge();
169 Integer nb_face = cell.nbFace();
170
171 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
172 trace->pinfo() << "** -- Dumping information for cell " << cell.uniqueId();
173 trace->pinfo() << "** -- Structure:";
174 trace->pinfo() << "unique id: " << Trace::Width(5) << cell.uniqueId();
175 trace->pinfo() << "local id: " << Trace::Width(5) << cell.localId();
176 trace->pinfo() << "owner: " << Trace::Width(5) << cell.owner();
177 trace->pinfo() << "type: " << Trace::Width(5) << cell.typeInfo()->typeName();
178
179 trace->pinfo() << "number of nodes: " << Trace::Width(5) << nb_node;
180 for (Integer i = 0; i < nb_node; ++i)
181 trace->pinfo() << "unique id of node " << Trace::Width(2)
182 << i << " : " << Trace::Width(5) << cell.node(i).uniqueId();
183
184 trace->pinfo() << "number of edges: " << Trace::Width(5) << nb_edge;
185 for (Integer i = 0; i < nb_edge; ++i)
186 trace->pinfo() << "unique id of edge " << Trace::Width(2)
187 << i << " : " << Trace::Width(5) << cell.edge(i).uniqueId();
188
189 trace->pinfo() << "number of faces: " << Trace::Width(5) << nb_face;
190 for (Integer i = 0; i < nb_face; ++i)
191 trace->pinfo() << "local id of face " << Trace::Width(2)
192 << i << " : " << Trace::Width(5) << cell.face(i).localId();
193
194 trace->pinfo() << "** -- Variables:";
195 _writeInfo<Cell, Real>(sd, variables, cell);
196 _writeInfo<Cell, Real2>(sd, variables, cell);
197 _writeInfo<Cell, Real3>(sd, variables, cell);
198 _writeInfo<Cell, Real2x2>(sd, variables, cell);
199 _writeInfo<Cell, Real3x3>(sd, variables, cell);
200 _writeInfo<Cell, Int32>(sd, variables, cell);
201 _writeInfo<Cell, Int64>(sd, variables, cell);
202
203 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
204
205 if (depend_info) {
206 for (Integer i = 0; i < nb_node; ++i)
207 writeMeshItemInfo(sd, cell.node(i), false);
208 for (Integer i = 0; i < nb_edge; ++i)
209 writeMeshItemInfo(sd, cell.edge(i), false);
210 for (Integer i = 0; i < nb_face; ++i)
211 writeMeshItemInfo(sd, cell.face(i), false);
212 }
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
218void MeshUtils::
219writeMeshItemInfo(ISubDomain* sd, Node node, bool depend_info)
220{
221 ITraceMng* trace = sd->traceMng();
222 Integer sid = sd->subDomainId();
223 StringBuilder buf("Info-");
224 buf += sid;
225 Trace::Setter mci(trace, buf.toString());
226
227 VariableCollection variables(sd->variableMng()->usedVariables());
228
229 Integer nb_cell = node.nbCell();
230 Integer nb_edge = node.nbEdge();
231 Integer nb_face = node.nbFace();
232
233 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
234 trace->pinfo() << "** -- Dumping information for node " << node.uniqueId();
235 trace->pinfo() << "** -- Structure:";
236 trace->pinfo() << "unique id: " << Trace::Width(5) << node.uniqueId();
237 trace->pinfo() << "local id: " << Trace::Width(5) << node.localId();
238 trace->pinfo() << "owner: " << Trace::Width(5) << node.owner();
239
240 trace->pinfo() << "number of cells: " << Trace::Width(5) << nb_cell;
241 for (Integer i = 0; i < nb_cell; ++i)
242 trace->pinfo() << "unique id of cell " << Trace::Width(2)
243 << i << " : " << Trace::Width(5) << node.cell(i).uniqueId();
244
245 trace->pinfo() << "number of faces: " << Trace::Width(5) << nb_face;
246 for (Integer i = 0; i < nb_face; ++i)
247 trace->pinfo() << "local id of face " << Trace::Width(2)
248 << i << " : " << Trace::Width(5) << node.face(i).localId();
249
250 trace->pinfo() << "** -- Variables:";
251 _writeInfo<Node, Real>(sd, variables, node);
252 _writeInfo<Node, Real2>(sd, variables, node);
253 _writeInfo<Node, Real3>(sd, variables, node);
254 _writeInfo<Node, Real2x2>(sd, variables, node);
255 _writeInfo<Node, Real3x3>(sd, variables, node);
256 _writeInfo<Node, Int32>(sd, variables, node);
257 _writeInfo<Node, Int64>(sd, variables, node);
258
259 if (depend_info) {
260 for (Integer i = 0; i < nb_cell; ++i)
261 writeMeshItemInfo(sd, node.cell(i), false);
262 for (Integer i = 0; i < nb_edge; ++i)
263 writeMeshItemInfo(sd, node.edge(i), false);
264 for (Integer i = 0; i < nb_face; ++i)
265 writeMeshItemInfo(sd, node.face(i), false);
266 }
267}
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
272void MeshUtils::
273writeMeshItemInfo(ISubDomain* sd, Edge edge, bool depend_info)
274{
275 ITraceMng* trace = sd->traceMng();
276 Integer sid = sd->subDomainId();
277 StringBuilder buf("Info-");
278 buf += sid;
279 Trace::Setter mci(trace, buf.toString());
280
281 VariableCollection variables(sd->variableMng()->usedVariables());
282
283 Integer nb_cell = edge.nbCell();
284 Integer nb_face = edge.nbFace();
285 Integer nb_node = edge.nbNode();
286
287 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
288 trace->pinfo() << "** -- Dumping information for face " << edge.localId() << " (localid)";
289 trace->pinfo() << "** -- Structure:";
290 trace->pinfo() << "unique id: " << Trace::Width(5) << "None";
291 trace->pinfo() << "local id: " << Trace::Width(5) << edge.localId();
292 trace->pinfo() << "owner: " << Trace::Width(5) << edge.owner();
293
294 trace->pinfo() << "number of nodes: " << Trace::Width(5) << nb_node;
295 for (Integer i = 0; i < nb_node; ++i)
296 trace->pinfo() << "unique id of node " << Trace::Width(2)
297 << i << " : " << Trace::Width(5) << edge.node(i).uniqueId();
298
299 trace->pinfo() << "number of cells: " << Trace::Width(5) << nb_cell;
300 for (Integer i = 0; i < nb_cell; ++i)
301 trace->pinfo() << "unique id of cell " << Trace::Width(2)
302 << i << " : " << Trace::Width(5) << edge.cell(i).uniqueId();
303
304 trace->pinfo() << "** -- Variables:";
305 _writeInfo<Edge, Real>(sd, variables, edge);
306 _writeInfo<Edge, Real2>(sd, variables, edge);
307 _writeInfo<Edge, Real3>(sd, variables, edge);
308 _writeInfo<Edge, Real2x2>(sd, variables, edge);
309 _writeInfo<Edge, Real3x3>(sd, variables, edge);
310 _writeInfo<Edge, Int32>(sd, variables, edge);
311 _writeInfo<Edge, Int64>(sd, variables, edge);
312
313 if (depend_info) {
314 for (Integer i = 0; i < nb_node; ++i)
315 writeMeshItemInfo(sd, edge.node(i), false);
316 for (Integer i = 0; i < nb_face; ++i)
317 writeMeshItemInfo(sd, edge.face(i), false);
318 for (Integer i = 0; i < nb_cell; ++i)
319 writeMeshItemInfo(sd, edge.cell(i), false);
320 }
321}
322
323/*---------------------------------------------------------------------------*/
324/*---------------------------------------------------------------------------*/
325
326void MeshUtils::
327writeMeshItemInfo(ISubDomain* sd, Face face, bool depend_info)
328{
329 ITraceMng* trace = sd->traceMng();
330 Integer sid = sd->subDomainId();
331 StringBuilder buf("Info-");
332 buf += sid;
333 Trace::Setter mci(trace, buf.toString());
334
335 VariableCollection variables(sd->variableMng()->usedVariables());
336
337 Integer nb_cell = face.nbCell();
338 Integer nb_edge = face.nbEdge();
339 Integer nb_node = face.nbNode();
340
341 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
342 trace->pinfo() << "** -- Dumping information for face " << face.localId() << " (localid)";
343 trace->pinfo() << "** -- Structure:";
344 trace->pinfo() << "unique id: " << Trace::Width(5) << "None";
345 trace->pinfo() << "local id: " << Trace::Width(5) << face.localId();
346 trace->pinfo() << "owner: " << Trace::Width(5) << face.owner();
347
348 trace->pinfo() << "number of nodes: " << Trace::Width(5) << nb_node;
349 for (Integer i = 0; i < nb_node; ++i)
350 trace->pinfo() << "unique id of node " << Trace::Width(2)
351 << i << " : " << Trace::Width(5) << face.node(i).uniqueId();
352
353 trace->pinfo() << "number of cells: " << Trace::Width(5) << nb_cell;
354 for (Integer i = 0; i < nb_cell; ++i)
355 trace->pinfo() << "unique id of cell " << Trace::Width(2)
356 << i << " : " << Trace::Width(5) << face.cell(i).uniqueId();
357
358 trace->pinfo() << "** -- Variables:";
359 _writeInfo<Face, Real>(sd, variables, face);
360 _writeInfo<Face, Real2>(sd, variables, face);
361 _writeInfo<Face, Real3>(sd, variables, face);
362 _writeInfo<Face, Real2x2>(sd, variables, face);
363 _writeInfo<Face, Real3x3>(sd, variables, face);
364 _writeInfo<Face, Int32>(sd, variables, face);
365 _writeInfo<Face, Int64>(sd, variables, face);
366
367 if (depend_info) {
368 for (Integer i = 0; i < nb_node; ++i)
369 writeMeshItemInfo(sd, face.node(i), false);
370 for (Integer i = 0; i < nb_edge; ++i)
371 writeMeshItemInfo(sd, face.edge(i), false);
372 for (Integer i = 0; i < nb_cell; ++i)
373 writeMeshItemInfo(sd, face.cell(i), false);
374 }
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
381{
382 public:
383
384 bool operator()(const Node& node1, const Node& node2)
385 {
386 const Real3& r1 = m_coords[node1];
387 const Real3& r2 = m_coords[node2];
388 return r1 < r2;
389 }
390
391 public:
392
393 _CompareNodes(IMesh* mesh, const SharedVariableNodeReal3& coords)
394 : m_items(mesh->itemsInternal(IK_Node))
395 , m_coords(coords)
396 {
397 }
398 ItemInternalList m_items;
399 const SharedVariableNodeReal3& m_coords;
400};
401
403{
404 public:
405
406 bool operator()(const ItemWithNodes& cell1, const ItemWithNodes& cell2)
407 {
408 Integer nb1 = cell1.nbNode();
409 Integer nb2 = cell2.nbNode();
410 if (nb1 < nb2)
411 return true;
412 if (nb2 < nb1)
413 return false;
414 Integer n = nb1;
415 for (Integer i = 0; i < n; ++i) {
416 Integer n1 = m_nodes_sorted_id[cell1.node(i).localId()];
417 Integer n2 = m_nodes_sorted_id[cell2.node(i).localId()];
418 if (n1 != n2)
419 return n1 < n2;
420 }
421 return false;
422 //return n1<n2;
423 }
424
425 public:
426
428 : m_items(mesh->itemsInternal(ik))
429 , m_nodes_sorted_id(nodes_sorted_id)
430 {
431 }
432 ItemInternalList m_items;
433 Int32ConstArrayView m_nodes_sorted_id;
434};
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
439void _writeItems(std::ostream& ofile, const String& name, Int32ConstArrayView ids)
440{
441 Integer nb_sub_item = ids.size();
442 ofile << " " << name << " " << nb_sub_item << " (";
443 for (Integer i = 0; i < nb_sub_item; ++i)
444 ofile << ' ' << ids[i];
445 ofile << " )";
446}
447
449{
450 public:
451
452 virtual ~IItemFiller() {}
453
454 public:
455
456 virtual Integer nbItem(ItemBase item) const = 0;
457 virtual void fillLocalIds(ItemBase item, Int32ArrayView ids) const = 0;
458};
459
461: public IItemFiller
462{
463 Integer nbItem(ItemBase item) const override { return item.nbEdge(); }
464 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
465 {
466 Integer nb_edge = ids.size();
467 for (Integer i = 0; i < nb_edge; ++i)
468 ids[i] = item.edgeId(i);
469 }
470};
471
473: public IItemFiller
474{
475 Int32 nbItem(ItemBase item) const override { return item.nbCell(); }
476 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
477 {
478 Integer nb_cell = ids.size();
479 for (Integer i = 0; i < nb_cell; ++i)
480 ids[i] = item.cellId(i);
481 }
482};
483
485: public IItemFiller
486{
487 Int32 nbItem(ItemBase item) const override { return item.nbFace(); }
488 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
489 {
490 Integer nb_face = ids.size();
491 for (Integer i = 0; i < nb_face; ++i)
492 ids[i] = item.faceId(i);
493 }
494};
495
497: public IItemFiller
498{
499 virtual Int32 nbItem(ItemBase item) const { return item.nbNode(); }
500 virtual void fillLocalIds(ItemBase item, Int32ArrayView ids) const
501 {
502 Integer nb_node = ids.size();
503 for (Integer i = 0; i < nb_node; ++i)
504 ids[i] = item.nodeId(i);
505 }
506};
507
509{
510 ItemBase item = titem.itemBase();
511 Integer n = filler.nbItem(item);
512 local_ids.resize(n);
513 filler.fillLocalIds(item, local_ids);
514 for (Integer i = 0; i < n; ++i)
516}
517
518/*---------------------------------------------------------------------------*/
519/*---------------------------------------------------------------------------*/
520
521void MeshUtils::
522writeMeshInfosSorted(IMesh* mesh, const String& file_name)
523{
524 if (!mesh)
525 return;
526 std::ofstream ofile(file_name.localstr());
527 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
528 Integer nb_node = mesh->nbNode();
529 Integer nb_edge = mesh->nbEdge();
530 Integer nb_face = mesh->nbFace();
531 Integer nb_cell = mesh->nbCell();
532 ofile << "** Mesh Sorted --> "
533 << " Nodes " << nb_node
534 << " Edges " << nb_edge
535 << " Faces " << nb_face
536 << " Cells " << nb_cell
537 << "\n";
542
547 {
548 // Trie les noeuds par ordre croissant de leur coordonnées
549 NodeInfoListView nodes(mesh->nodeFamily());
550 for (Integer i = 0; i < nb_node; ++i)
551 sorted_nodes[i] = nodes[i];
552 {
555 std::sort(std::begin(sorted_nodes), std::end(sorted_nodes), compare_nodes);
556 }
557 for (Integer i = 0; i < nb_node; ++i)
558 nodes_sorted_id[sorted_nodes[i].localId()] = i;
559
560 // Trie les arêtes
561 EdgeInfoListView edges(mesh->edgeFamily());
562 for (Integer i = 0; i < nb_edge; ++i)
563 sorted_edges[i] = edges[i];
564 {
566 std::sort(std::begin(sorted_edges), std::end(sorted_edges), compare_edges);
567 }
568 for (Integer i = 0; i < nb_edge; ++i)
569 edges_sorted_id[sorted_edges[i].localId()] = i;
570
571 // Trie les faces
572 FaceInfoListView faces(mesh->faceFamily());
573 for (Integer i = 0; i < nb_face; ++i)
574 sorted_faces[i] = faces[i];
575 {
577 std::sort(std::begin(sorted_faces), std::end(sorted_faces), compare_faces);
578 }
579 for (Integer i = 0; i < nb_face; ++i)
580 faces_sorted_id[sorted_faces[i].localId()] = i;
581
582 // Trie les mailles
583 CellInfoListView cells(mesh->cellFamily());
584 for (Integer i = 0; i < nb_cell; ++i)
585 sorted_cells[i] = cells[i];
586 {
588 std::sort(std::begin(sorted_cells), std::end(sorted_cells), compare_cells);
589 }
590 for (Integer i = 0; i < nb_cell; ++i)
591 cells_sorted_id[sorted_cells[i].localId()] = i;
592
594
595 ofile << "** Nodes\n";
597 for (Integer i = 0; i < nb_node; ++i) {
598 const Node& node = sorted_nodes[i];
599 ofile << "Node: " << i << " Coord: " << coords[node];
600
601 _fillSorted(node, lids, edges_sorted_id, EdgeFiller());
602 std::sort(std::begin(lids), std::end(lids));
603 _writeItems(ofile, "Edges", lids);
604
605 _fillSorted(node, lids, faces_sorted_id, FaceFiller());
606 std::sort(std::begin(lids), std::end(lids));
607 _writeItems(ofile, "Faces", lids);
608
609 _fillSorted(node, lids, cells_sorted_id, CellFiller());
610 std::sort(std::begin(lids), std::end(lids));
611 _writeItems(ofile, "Cells", lids);
612
613 ofile << '\n';
614 }
615
616 ofile << "** Edges\n";
617 for (Integer i = 0; i < nb_edge; ++i) {
618 Edge edge = sorted_edges[i];
619 Integer edge_nb_node = edge.nbNode();
620 Integer edge_nb_face = edge.nbFace();
621 Integer edge_nb_cell = edge.nbCell();
622 ofile << "Edge: " << i
623 << " Nodes " << edge_nb_node << " (";
624 for (Integer i_node = 0; i_node < edge_nb_node; ++i_node)
625 ofile << ' ' << nodes_sorted_id[edge.node(i_node).localId()];
626 ofile << " )";
627 ofile << " Faces " << edge_nb_face << " (";
628 for (Integer i_face = 0; i_face < edge_nb_face; ++i_face)
629 ofile << ' ' << faces_sorted_id[edge.face(i_face).localId()];
630 ofile << " )";
631 ofile << " Cells " << edge_nb_cell << " (";
632 for (Integer i_cell = 0; i_cell < edge_nb_cell; ++i_cell)
633 ofile << ' ' << cells_sorted_id[edge.cell(i_cell).localId()];
634 ofile << " )";
635 ofile << '\n';
636 }
637
638 ofile << "** Faces\n";
639 for (Integer i = 0; i < nb_face; ++i) {
640 Face face = sorted_faces[i];
641 Integer face_nb_node = face.nbNode();
642 Integer face_nb_edge = face.nbEdge();
643 Integer face_nb_cell = face.nbCell();
644 ofile << "Face: " << i;
645 ofile << " Nodes " << face.nbNode() << " (";
646 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
647 ofile << ' ' << nodes_sorted_id[face.node(i_node).localId()];
648 ofile << " )";
649
650 ofile << " Edges " << face_nb_edge << " (";
651 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge)
652 ofile << ' ' << edges_sorted_id[face.edge(i_edge).localId()];
653 ofile << " )";
654
655 ofile << " Cells " << face_nb_cell << " (";
656 for (Integer i_cell = 0; i_cell < face_nb_cell; ++i_cell)
657 ofile << ' ' << cells_sorted_id[face.cell(i_cell).localId()];
658
659 const Cell& back_cell = face.backCell();
660 if (!back_cell.null())
661 ofile << " Back " << cells_sorted_id[back_cell.localId()];
662
663 const Cell& front_cell = face.frontCell();
664 if (!front_cell.null())
665 ofile << " Front " << cells_sorted_id[front_cell.localId()];
666
667 ofile << " )";
668 ofile << '\n';
669 }
670
671 ofile << "** Cells\n";
672 for (Integer i = 0; i < nb_cell; ++i) {
673 Cell cell = sorted_cells[i];
674 //Integer cell_nb_node = cell.nbNode();
675 ofile << "Cell: " << i;
676
677 _fillSorted(cell, lids, nodes_sorted_id, NodeFiller());
678 _writeItems(ofile, "Nodes", lids);
679 _fillSorted(cell, lids, edges_sorted_id, EdgeFiller());
680 _writeItems(ofile, "Edges", lids);
681 _fillSorted(cell, lids, faces_sorted_id, FaceFiller());
682 _writeItems(ofile, "Faces", lids);
683 ofile << '\n';
684 }
685 }
686}
687
688/*---------------------------------------------------------------------------*/
689/*---------------------------------------------------------------------------*/
690
691void MeshUtils::
692writeMeshInfos(IMesh* mesh, const String& file_name)
693{
694 if (!mesh)
695 return;
696 std::ofstream ofile(file_name.localstr());
697 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
698 Integer nb_node = mesh->nbNode();
699 Integer nb_edge = mesh->nbEdge();
700 Integer nb_face = mesh->nbFace();
701 Integer nb_cell = mesh->nbCell();
702 ofile << "** Mesh --> "
703 << " Nodes " << nb_node
704 << " Edges " << nb_edge
705 << " Faces " << nb_face
706 << " Cells " << nb_cell
707 << "\n";
708
709 NodeInfoListView nodes(mesh->nodeFamily());
710 FaceInfoListView faces(mesh->faceFamily());
711 CellInfoListView cells(mesh->cellFamily());
712 //TODO pouvoir afficher les infos même si on n'est pas un maillage primaire
713 VariableNodeReal3& coords(mesh->toPrimaryMesh()->nodesCoordinates());
714
715 ofile << "** Nodes\n";
716 for (Integer i = 0; i < nb_node; ++i) {
717 Node node = nodes[i];
718 Integer node_nb_face = node.nbFace();
719 Integer node_nb_cell = node.nbCell();
720 ofile << "Node: " << i << " Coord: " << coords[node];
721 ofile << " Faces " << node_nb_face << " (";
722 for (Integer i_face = 0; i_face < node_nb_face; ++i_face)
723 ofile << ' ' << node.face(i_face).localId();
724 ofile << " )";
725 ofile << " Cells " << node_nb_cell << " (";
726 for (Integer i_cell = 0; i_cell < node_nb_cell; ++i_cell)
727 ofile << ' ' << node.cell(i_cell).localId();
728 ofile << " )";
729 ofile << '\n';
730 }
731
732 ofile << "** Faces\n";
733 for (Integer i = 0; i < nb_face; ++i) {
734 Face face = faces[i];
735 Integer face_nb_node = face.nbNode();
736 Integer face_nb_cell = face.nbCell();
737 ofile << "Face: " << i
738 << " Nodes " << face_nb_node << " (";
739 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
740 ofile << ' ' << face.node(i_node).localId();
741 ofile << " )";
742 ofile << " Cells " << face_nb_cell << " (";
743
744 for (Integer i_cell = 0; i_cell < face_nb_cell; ++i_cell)
745 ofile << ' ' << face.cell(i_cell).localId();
746
747 const Cell& back_cell = face.backCell();
748 if (!back_cell.null())
749 ofile << " Back " << back_cell.localId();
750
751 const Cell& front_cell = face.frontCell();
752 if (!front_cell.null())
753 ofile << " Front " << front_cell.localId();
754
755 ofile << " )";
756 ofile << '\n';
757 }
758
759 ofile << "** Cells\n";
760 for (Integer i = 0; i < nb_cell; ++i) {
761 Cell cell = cells[i];
762 Integer cell_nb_node = cell.nbNode();
763 Integer cell_nb_face = cell.nbFace();
764 ofile << "Cell: " << i
765 << " Nodes " << cell_nb_node << " (";
766 for (Integer i_node = 0; i_node < cell_nb_node; ++i_node)
767 ofile << ' ' << cell.node(i_node).localId();
768 ofile << " )";
769 ofile << " Faces " << cell_nb_face << " (";
770 for (Integer i_face = 0; i_face < cell_nb_face; ++i_face)
771 ofile << ' ' << cell.face(i_face).localId();
772 ofile << " )";
773 ofile << '\n';
774 }
775}
776
777/*---------------------------------------------------------------------------*/
778/*---------------------------------------------------------------------------*/
779
780namespace
781{
782 template <typename ItemType> void
783 _sortByUniqueIds(IMesh* mesh, eItemKind ik, Array<ItemType>& items)
784 {
785 ItemGroup all_items(mesh->itemFamily(ik)->allItems());
786 items.resize(all_items.size());
787
788 Integer index = 0;
789 ENUMERATE_ (ItemType, i, all_items) {
790 ItemType item = *i;
791 items[index] = item;
792 ++index;
793 }
794 std::sort(std::begin(items), std::end(items), ItemCompare());
795 }
796
797 void
798 _stringToIds(const String& str, Int64Array& ids)
799 {
800 ids.clear();
801 std::istringstream istr(str.localstr());
802 Integer z = 0;
803 while (istr.good()) {
804 istr >> z;
805 if (!istr)
806 break;
807 ids.add(z);
808 }
809 }
810
811 template <typename SubItemType> void
812 _writeSubItems(std::ostream& ofile, const char* item_name, ItemConnectedListViewT<SubItemType> sub_list)
813 {
814 Int32 n = sub_list.size();
815 if (n == 0)
816 return;
817 ofile << "<" << item_name << " count='" << n << "'>";
818 for (SubItemType sub_item : sub_list)
819 ofile << ' ' << sub_item.uniqueId();
820 ofile << "</" << item_name << ">";
821 }
822} // namespace
823
824/*---------------------------------------------------------------------------*/
825/*---------------------------------------------------------------------------*/
826
827void MeshUtils::
828writeMeshConnectivity(IMesh* mesh, const String& file_name)
829{
830 std::ofstream ofile(file_name.localstr());
831 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
832 if (!mesh)
833 return;
834
835 ITraceMng* trace = mesh->traceMng();
836
837 trace->info() << "Writing mesh connectivity in '" << file_name << "'";
838
839 ofile << "<?xml version='1.0' ?>\n";
840 ofile << "<mesh-connectivity>\n";
841 UniqueArray<Node> nodes;
842 UniqueArray<Edge> edges;
843 UniqueArray<Face> faces;
844 UniqueArray<Cell> cells;
845
846 _sortByUniqueIds(mesh, IK_Node, nodes);
847 _sortByUniqueIds(mesh, IK_Edge, edges);
848 _sortByUniqueIds(mesh, IK_Face, faces);
849 _sortByUniqueIds(mesh, IK_Cell, cells);
850
851 // Écrit les noeuds
852 {
853 ofile << "<nodes count='" << nodes.size() << "'>\n";
854 for (Node item : nodes) {
855 ofile << " <node uid='" << item.uniqueId() << "' owner='" << item.owner() << "'>";
856 _writeSubItems(ofile, "cells", item.cells());
857 _writeSubItems(ofile, "faces", item.faces());
858 _writeSubItems(ofile, "edges", item.edges());
859 ofile << "</node>\n";
860 }
861 ofile << "</nodes>\n";
862 }
863
864 // Écrit les arêtes
865 {
866 ofile << "<edges count='" << edges.size() << "'>\n";
867 for (Edge edge : edges) {
868 ofile << " <edge uid='" << edge.uniqueId() << "' owner='" << edge.owner() << "'>";
869 _writeSubItems(ofile, "nodes", edge.nodes());
870 _writeSubItems(ofile, "cells", edge.cells());
871 _writeSubItems(ofile, "faces", edge.faces());
872 ofile << "</edge>\n";
873 }
874 ofile << "</edges>\n";
875 }
876
877 // Écrit les faces
878 {
879 ofile << "<faces count='" << faces.size() << "'>\n";
880 for (Face face : faces) {
881 // Integer item_nb_face = item.nbFace();
882 ofile << " <face uid='" << face.uniqueId()
883 << "' typeid='" << face.type()
884 << "' owner='" << face.owner() << "'>";
885 _writeSubItems(ofile, "nodes", face.nodes());
886 _writeSubItems(ofile, "edges", face.edges());
887 {
888 // Infos sur les mailles
889 ofile << "<cells";
890 Cell back_cell = face.backCell();
891 if (!back_cell.null())
892 ofile << " back='" << back_cell.uniqueId() << "'";
893 Cell front_cell = face.frontCell();
894 if (!front_cell.null())
895 ofile << " front='" << front_cell.uniqueId() << "'";
896 ofile << "/>";
897 }
898
899 // Infos sur les maitres/esclaves
900 if (face.isSlaveFace())
901 _writeSubItems(ofile, "slave-faces", face.slaveFaces());
902 if (face.isMasterFace()) {
903 ofile << "<faces count='1'>";
904 ofile << ' ' << face.masterFace().uniqueId();
905 ofile << "</faces>";
906 }
907
908 ofile << "</face>\n";
909 }
910 ofile << "</faces>\n";
911 }
912
913 // Écrit les mailles
914 {
915 ofile << "<cells count='" << cells.size() << "'>\n";
916 // Pour les mailles autour d'une maille.
917 // Une maille est autour d'une autre, si elle est connectée par
918 // au moins un noeud
920 ghost_cells_layer1.reserve(100);
921 for (Cell cell : cells) {
922 ofile << " <cell uid='" << cell.uniqueId()
923 << "' typeid='" << cell.type()
924 << "' owner='" << cell.owner() << "'>";
925 _writeSubItems(ofile, "nodes", cell.nodes());
926 _writeSubItems(ofile, "edges", cell.edges());
927 _writeSubItems(ofile, "faces", cell.faces());
928 if (mesh->isAmrActivated()) {
929 ofile << "<amr level='" << cell.level() << "'>";
930 // {
931 // ofile << "<parent count='" << item.nbHParent() << "'>";
932 // trace->info() << "Truc : " << item.nbHParent();
933 // for (Integer j = 0; j < item.nbHParent(); ++j) {
934 // ofile << ' ' << item.parent(j).uniqueId();
935 // }
936 // ofile << "</parent>";
937 // }
938 {
939 ofile << "<child count='" << cell.nbHChildren() << "'>";
940 for (Integer j = 0; j < cell.nbHChildren(); ++j) {
941 ofile << ' ' << cell.hChild(j)->uniqueId();
942 }
943 ofile << "</child>";
944 }
945 ofile << "</amr>";
946 }
947 {
948 ghost_cells_layer1.clear();
949 for (Node node : cell.nodes()) {
950 for (Cell sub_cell : node.cells()) {
951 ghost_cells_layer1.add(sub_cell.uniqueId().asInt64());
952 }
953 }
954
955 {
956 // Trie la liste des mailles fantômes et retire les doublons.
957 std::sort(std::begin(ghost_cells_layer1), std::end(ghost_cells_layer1));
958 auto new_end = std::unique(std::begin(ghost_cells_layer1), std::end(ghost_cells_layer1));
960 ofile << "<ghost1 count='" << ghost_cells_layer1.size() << "'>";
961 for (auto j : ghost_cells_layer1)
962 ofile << ' ' << j;
963 ofile << "</ghost1>\n";
964 }
965 }
966 ofile << "</cell>\n";
967 }
968 ofile << "</cells>\n";
969 }
970
971 // Sauve les groupes
972
973 {
974 ofile << "<groups>\n";
975 // Trie les groupes par ordre alphabétique pour être certains qu'ils sont
976 // toujours écrits dans le même ordre.
977 std::map<String,ItemGroup> sorted_groups;
979 const ItemGroup& group = *i_group;
980 if (group.isLocalToSubDomain())
981 continue;
982 sorted_groups.insert(std::make_pair(group.name(),group));
983 }
984 for ( const auto& [name,group] : sorted_groups ){
985 ofile << "<group name='" << group.name()
986 << "' kind='" << itemKindName(group.itemKind())
987 << "' count='" << group.size() << "'>\n";
988 ENUMERATE_ (Item, i_item, group) {
989 ofile << ' ' << i_item->uniqueId();
990 }
991 ofile << "\n</group>\n";
992 }
993 ofile << "</groups>\n";
994 }
995
996 // Sauve les interfaces liées
997 {
998 ofile << "<tied-interfaces>\n";
999 TiedInterfaceCollection tied_interfaces(mesh->tiedInterfaces());
1000 for (TiedInterfaceCollection::Enumerator itied(tied_interfaces); ++itied;) {
1001 ITiedInterface* interface = *itied;
1002 FaceGroup slave_group = interface->slaveInterface();
1003 FaceGroup master_group = interface->masterInterface();
1004 ofile << "<tied-interface master_name='" << master_group.name()
1005 << "' slave_name='" << slave_group.name() << "'>\n";
1006 TiedInterfaceNodeList tied_nodes(interface->tiedNodes());
1007 TiedInterfaceFaceList tied_faces(interface->tiedFaces());
1009 Face face = *iface;
1010 //FaceVectorView slave_faces = face.slaveFaces();
1011 ofile << "<master-face uid='" << face.uniqueId() << "'>\n";
1012 for (Integer zz = 0, zs = tied_nodes[iface.index()].size(); zz < zs; ++zz) {
1013 TiedNode tn = tied_nodes[iface.index()][zz];
1014 ofile << "<node uid='" << tn.node().uniqueId() << "' iso='" << tn.isoCoordinates() << "' />\n";
1015 }
1016 for (Integer zz = 0, zs = tied_faces[iface.index()].size(); zz < zs; ++zz) {
1017 TiedFace tf = tied_faces[iface.index()][zz];
1018 ofile << "<face uid='" << tf.face().uniqueId() << "'/>\n";
1019 }
1020 ofile << "</master-face>\n";
1021 }
1022 ofile << "</tied-interface>\n";
1023 }
1024 ofile << "</tied-interfaces>\n";
1025 }
1026 ofile << "</mesh-connectivity>\n";
1027}
1028
1029/*---------------------------------------------------------------------------*/
1030/*---------------------------------------------------------------------------*/
1031
1032/*---------------------------------------------------------------------------*/
1033/*---------------------------------------------------------------------------*/
1034
1036{
1037 public:
1038
1040 {
1041 public:
1042
1043 ItemInternalXml() {}
1044 explicit ItemInternalXml(Item item)
1045 : m_item(item)
1046 {}
1047
1048 public:
1049
1050 bool operator<(const ItemInternalXml& i2) const
1051 {
1052 return m_item.uniqueId() < i2.m_item.uniqueId();
1053 }
1054 bool operator<(Int64 uid) const
1055 {
1056 return m_item.uniqueId() < uid;
1057 }
1058
1059 public:
1060
1061 Item m_item;
1062 XmlNode m_element;
1063 };
1064 typedef std::map<Int64, ItemInternalXml> ItemInternalXmlMap;
1065
1066 public:
1067
1069 : m_mesh(mesh)
1070 , m_doc_node(doc_node)
1071 , m_has_error(false)
1072 , m_check_sub_domain(check_sub_domain)
1073 {
1074 }
1075
1076 public:
1077
1078 void doCheck();
1079
1080 public:
1081
1082 IMesh* m_mesh;
1083 XmlNode m_doc_node;
1084 bool m_has_error;
1085 bool m_check_sub_domain;
1086 ItemInternalXmlMap m_nodes_internal;
1087 ItemInternalXmlMap m_edges_internal;
1088 ItemInternalXmlMap m_faces_internal;
1089 ItemInternalXmlMap m_cells_internal;
1090 Int64UniqueArray m_items_unique_id;
1091
1092 private:
1093
1094 /*void _sortByUniqueIds(eItemKind ik,Array<ItemInternalXml>& items_internal)
1095 {
1096 ItemGroup all_items(m_mesh->allItems(ik));
1097 items_internal.resize(all_items.size());
1098
1099 Integer index = 0;
1100 ENUMERATE_ITEM(i,all_items){
1101 const Item& item = *i;
1102 items_internal[index].m_item = item.internal();
1103 ++index;
1104 }
1105 std::sort(items_internal.begin(),items_internal.end());
1106 }*/
1107 void _read(eItemKind ik, ItemInternalXmlMap& items_internal,
1109
1110 /*ItemInternalXml* _find(Array<ItemInternalXml>& items_internal,Integer uid)
1111 {
1112 ItemInternalXmlIterator z = std::lower_bound(items_internal.begin(),items_internal.end(),uid);
1113 if (z==items_internal.end())
1114 return 0;
1115 ItemInternalXml* ixml = &(*z);
1116 if (ixml->m_item->uniqueId()!=uid)
1117 return 0;
1118 return ixml;
1119 //cout << "NOT IMPLEMENTED!\n";
1120 //return 0;
1121 }*/
1122};
1123
1124/*---------------------------------------------------------------------------*/
1125/*---------------------------------------------------------------------------*/
1126
1127void MeshUtils::
1128checkMeshConnectivity(IMesh* mesh, const XmlNode& doc_node, bool check_sub_domain)
1129{
1130 if (!mesh)
1131 return;
1132 MeshUtilsCheckConnectivity v(mesh, doc_node, check_sub_domain);
1133 v.doCheck();
1134}
1135
1136void MeshUtils::
1137checkMeshConnectivity(IMesh* mesh, const String& file_name, bool check_sub_domain)
1138{
1139 ITraceMng* tm = mesh->traceMng();
1140 ScopedPtrT<IXmlDocumentHolder> doc(IXmlDocumentHolder::loadFromFile(file_name, tm));
1141 //IXmlDocumentHolder* doc = io_mng->parseXmlFile(file_name);
1142 XmlNode root = doc->documentNode();
1143 checkMeshConnectivity(mesh, root, check_sub_domain);
1144}
1145
1146void MeshUtilsCheckConnectivity::
1147_read(eItemKind ik, ItemInternalXmlMap& items_internal, XmlNode root_node,
1148 const String& lower_case_kind_name)
1149{
1150 ITraceMng* trace = m_mesh->traceMng();
1151
1152 //_sortByUniqueIds(ik,items_internal);
1153
1154 String ustr_uid("uid");
1155 String ustr_cells("cells");
1156 String ustr_count("count");
1157 String ustr_nodes("nodes");
1158 String ustr_ghost1("ghost1");
1159
1160 String kind_name(itemKindName(ik));
1161
1162 ENUMERATE_ITEM (iitem, m_mesh->itemFamily(ik)->allItems()) {
1163 Item item = *iitem;
1164 ItemInternalXml ixml(item);
1165 items_internal.insert(ItemInternalXmlMap::value_type(item.uniqueId().asInt64(), ixml));
1166 }
1167
1168#ifdef ARCANE_DEBUG_MESH
1169 for (Integer i = 0; i < items_internal.size(); ++i) {
1170 const ItemInternalXml& item_xml = items_internal[i];
1171 trace->info() << "Item " << kind_name << ":" << item_xml.m_item->uniqueId()
1172 << ' ' << i << ' ' << item_xml.m_item;
1173 }
1174#endif
1175
1176 XmlNodeList xml_items(root_node.children(lower_case_kind_name));
1177 for (const auto& xml_node : xml_items) {
1178 Integer uid = xml_node.attr(ustr_uid).valueAsInteger();
1179 ItemInternalXmlMap::iterator iixml = items_internal.find(uid);
1180 if (iixml != items_internal.end()) {
1181 iixml->second.m_element = xml_node;
1182 }
1183#if 0
1184 ItemInternalXml* ixml = _find(items_internal,uid);
1185 if (ixml){
1186 ixml->m_element = xml_node;
1187#ifdef ARCANE_DEBUG_MESH
1188 trace->info() << "FOUND " << uid << ' ' << z->m_item->uniqueId() << ' ' << z->m_element.name()
1189 << ' ' << z->m_item;
1190#endif
1191 }
1192#ifdef ARCANE_DEBUG_MESH
1193 else
1194 trace->info() << "FOUND " << uid << " NOT HERE";
1195#endif
1196#endif
1197 }
1198
1199 Int32UniqueArray local_ids;
1200 local_ids.reserve(100);
1201 for (ItemInternalXmlMap::const_iterator i(items_internal.begin()); i != items_internal.end(); ++i) {
1202 const ItemInternalXml& item_xml = i->second;
1203 Item item = item_xml.m_item;
1204 const XmlNode& xitem = item_xml.m_element;
1205 if (xitem.null()) {
1206 trace->error() << "Item " << kind_name << ":" << item.uniqueId()
1207 << "unknown in reference mesh";
1208 m_has_error = true;
1209 continue;
1210 }
1211 if (ik != IK_Node) {
1212 ItemWithNodes item_with_node(item);
1213 XmlNode xitem_node = xitem.child(ustr_nodes);
1214 Integer ref_nb_node = xitem_node.attr(ustr_count).valueAsInteger();
1215 Integer nb_node = item_with_node.nbNode();
1216 if (ref_nb_node != nb_node) {
1217 trace->error() << "Item " << kind_name << ":" << item.uniqueId()
1218 << ": number of nodes (" << nb_node << ") "
1219 << "different than reference (" << ref_nb_node << ")";
1220 m_has_error = true;
1221 continue;
1222 }
1223
1224 m_items_unique_id.reserve(ref_nb_node);
1225 String s = xitem_node.value();
1226 _stringToIds(s, m_items_unique_id);
1227 bool is_bad = false;
1228 for (NodeEnumerator i_node(item_with_node.nodes()); i_node(); ++i_node) {
1229 if (m_items_unique_id[i_node.index()] != i_node->uniqueId()) {
1230 is_bad = true;
1231 break;
1232 }
1233 }
1234 if (is_bad) {
1235 m_has_error = true;
1236 OStringStream ostr;
1237 ostr() << "Item " << kind_name << ":" << item.uniqueId()
1238 << ": nodes (";
1239 for (NodeEnumerator i_node(item_with_node.nodes()); i_node(); ++i_node) {
1240 ostr() << ' ' << i_node->uniqueId();
1241 }
1242 ostr() << ") different than reference (" << s << ")";
1243 trace->error() << ostr.str();
1244 }
1245 }
1246 if (item.isOwn()) {
1247 // Si c'est une maille, recherche si les mailles qui doivent être
1248 // fantômes sont bien présentes dans le maillage.
1249 // Si c'est un noeud, recherche si les mailles autour de ce noeud
1250 // sont bien présentes dans le maillage.
1251 XmlNode elem;
1252 if (ik == IK_Cell)
1253 elem = xitem.child(ustr_ghost1);
1254 else if (ik == IK_Node)
1255 elem = xitem.child(ustr_cells);
1256 if (!elem.null()) {
1257 _stringToIds(elem.value(), m_items_unique_id);
1258 local_ids.resize(m_items_unique_id.size());
1259 m_mesh->cellFamily()->itemsUniqueIdToLocalId(local_ids, m_items_unique_id, false);
1260 StringBuilder not_found;
1261 bool has_not_found = false;
1262 for (Integer uui = 0, uuis = m_items_unique_id.size(); uui < uuis; ++uui) {
1263 if (local_ids[uui] == NULL_ITEM_ID) {
1264 not_found += " ";
1265 not_found += m_items_unique_id[uui];
1266 m_has_error = true;
1267 has_not_found = true;
1268 }
1269 }
1270 if (has_not_found) {
1271 if (ik == IK_Cell)
1272 trace->info() << "ERROR: One or more ghost cells of cell "
1273 << ItemPrinter(item) << " are not in the sub-domain"
1274 << " ref='" << elem.value() << "' not_found='" << not_found << '\'';
1275 else if (ik == IK_Node) {
1276 trace->info() << "ERROR: One or more cells with node "
1277 << ItemPrinter(item) << " are not in the sub-domain"
1278 << " ref='" << elem.value() << "' not_found='" << not_found << '\'';
1279 }
1280 }
1281 }
1282 }
1283 }
1284}
1285
1286/*---------------------------------------------------------------------------*/
1287/*---------------------------------------------------------------------------*/
1288
1289/*---------------------------------------------------------------------------*/
1290/*---------------------------------------------------------------------------*/
1291
1292void MeshUtilsCheckConnectivity::
1293doCheck()
1294{
1295 ITraceMng* trace = m_mesh->traceMng();
1296
1297 trace->info() << "Checking mesh checkMeshConnectivity()";
1298
1299 XmlNode root_node = m_doc_node.child(String("mesh-connectivity"));
1300 if (!root_node) {
1301 trace->warning() << "Incorrect connectivity file";
1302 return;
1303 }
1304 XmlNode nodes_root = root_node.child("nodes");
1305 XmlNode faces_root = root_node.child("faces");
1306 XmlNode cells_root = root_node.child("cells");
1307
1308 _read(IK_Node, m_nodes_internal, nodes_root, "node");
1309 _read(IK_Face, m_faces_internal, faces_root, "face");
1310 _read(IK_Cell, m_cells_internal, cells_root, "cell");
1311
1312 String ustr_groups("groups");
1313 String ustr_group("group");
1314 String ustr_count("count");
1315
1316 XmlNode groups_root = root_node.child(ustr_groups);
1317 for (ItemGroupCollection::Enumerator i_group(m_mesh->groups()); ++i_group;) {
1318 const ItemGroup& group = *i_group;
1319 if (group.isLocalToSubDomain() || group.isOwn())
1320 continue;
1321 XmlNode group_elem = groups_root.childWithNameAttr(ustr_group, String(group.name()));
1322 if (group_elem.null()) {
1323 m_has_error = true;
1324 trace->error() << "Unable to find group <" << group.name()
1325 << "> in reference file";
1326 continue;
1327 }
1328 Integer size = group_elem.attr(ustr_count).valueAsInteger();
1329 m_items_unique_id.reserve(size);
1330 _stringToIds(group_elem.value(), m_items_unique_id);
1331 Integer ref_size = m_items_unique_id.size();
1332 if (ref_size != size) {
1333 trace->error() << "Number of items in group <" << group.name()
1334 << "> (" << size << " different than reference (" << ref_size;
1335 }
1336 // TODO: vérifier que les toutes les entités du groupe dans le maillage
1337 // de référence sont aussi dans le groupe correspondant de ce maillage.
1338 }
1339
1340 if (m_has_error) {
1341 trace->fatal() << "Error(s) while checking mesh";
1342 }
1343}
1344
1345/*---------------------------------------------------------------------------*/
1346/*---------------------------------------------------------------------------*/
1347
1348/*---------------------------------------------------------------------------*/
1349/*---------------------------------------------------------------------------*/
1350
1351void MeshUtils::
1352checkMeshProperties(IMesh* mesh, bool is_sorted, bool has_no_hole, bool check_faces)
1353{
1354 if (!mesh)
1355 return;
1356 if (has_no_hole)
1357 throw NotImplementedException(A_FUNCINFO, "Has no hole");
1358
1359 ITraceMng* trace = mesh->traceMng();
1360 bool has_error = false;
1361 if (is_sorted) {
1362 //for( Integer iki=0; iki<NB_ITEM_KIND; ++iki ){
1363 // eItemKind ik = static_cast<eItemKind>(iki);
1364 for (IItemFamilyCollection::Enumerator i(mesh->itemFamilies()); ++i;) {
1365 eItemKind ik = (*i)->itemKind();
1366 if (!check_faces && ik == IK_Face)
1367 continue;
1368 // Il est normal que les particules ne soient pas triées
1369 if (ik == IK_Particle)
1370 continue;
1371 //ItemGroup all_items = mesh->itemFamily(ik)->allItems();
1372 ItemGroup all_items = (*i)->allItems();
1375 Item item = *iitem;
1376
1377 if (!last_item.null() && (last_item.uniqueId() >= item.uniqueId() || last_item.localId() >= item.localId())) {
1378 trace->error() << "Item not sorted " << ItemPrinter(item, ik)
1379 << " Last item " << ItemPrinter(last_item, ik);
1380 has_error = true;
1381 }
1382 last_item = item;
1383 }
1384 }
1385 }
1386 if (has_error) {
1387 ARCANE_FATAL("Missing required mesh properties (sorted and/or no hole)");
1388 }
1389}
1390
1391/*---------------------------------------------------------------------------*/
1392/*---------------------------------------------------------------------------*/
1393
1394void MeshUtils::
1395printItems(std::ostream& ostr, const String& name, ItemGroup item_group)
1396{
1397 ostr << " ------- " << name << '\n';
1399 ostr << FullItemPrinter((*iitem)) << "\n";
1400 }
1401}
1402
1403/*---------------------------------------------------------------------------*/
1404/*---------------------------------------------------------------------------*/
1405
1406bool MeshUtils::
1408{
1409 // \a true s'il faut réorienter les faces pour que leur orientation
1410 // soit indépendante du partitionnement du maillage initial.
1411 bool need_swap_orientation = false;
1412 Integer min_node_index = 0;
1413 Integer nb_node = before_ids.size();
1414
1415 // Traite directement le cas des arêtes
1416 if (nb_node == 2) {
1417 if (before_ids[0] < before_ids[1]) {
1418 after_ids[0] = before_ids[0];
1419 after_ids[1] = before_ids[1];
1420 return false;
1421 }
1422 after_ids[0] = before_ids[1];
1423 after_ids[1] = before_ids[0];
1424 return true;
1425 }
1426
1427 // L'algorithme suivant oriente les faces en tenant compte uniquement
1428 // de l'ordre de la numérotation de ces noeuds. Si cet ordre est
1429 // conservé lors du partitionnement, alors l'orientation des faces
1430 // sera aussi conservée.
1431
1432 // L'algorithme est le suivant:
1433 // - Recherche le noeud n de plus petit indice.
1434 // - Recherche n-1 et n+1 les indices de ses 2 noeuds voisins.
1435 // - Si (n+1) est inférieur à (n-1), l'orientation n'est pas modifiée.
1436 // - Si (n+1) est supérieur à (n-1), l'orientation est inversée.
1437
1438 // Recherche le noeud de plus petit indice
1439
1440 Int64 min_node = INT64_MAX;
1441 for (Integer k = 0; k < nb_node; ++k) {
1442 Int64 id = before_ids[k];
1443 if (id < min_node) {
1444 min_node = id;
1445 min_node_index = k;
1446 }
1447 }
1448 Int64 next_node = before_ids[(min_node_index + 1) % nb_node];
1449 Int64 prev_node = before_ids[(min_node_index + (nb_node - 1)) % nb_node];
1450 Integer incr = 0 ;
1451 Integer incr2 = 0 ;
1452 if(next_node==min_node)
1453 {
1455 incr = 1 ;
1456 }
1457 if(prev_node==min_node)
1458 {
1460 incr2 = nb_node - 1 ;
1461 }
1462 if (next_node > prev_node)
1463 need_swap_orientation = true;
1465 for (Integer k = 0; k < nb_node; ++k) {
1466 Integer index = (nb_node - k + min_node_index + incr) % nb_node;
1467 after_ids[k] = before_ids[index];
1468 }
1469 }
1470 else {
1471 for (Integer k = 0; k < nb_node; ++k) {
1472 Integer index = (k + min_node_index + incr2) % nb_node;
1473 after_ids[k] = before_ids[index];
1474 }
1475 }
1476 return need_swap_orientation;
1477}
1478
1479/*---------------------------------------------------------------------------*/
1480/*---------------------------------------------------------------------------*/
1481
1482bool MeshUtils::
1483reorderNodesOfFace2(Int64ConstArrayView nodes_unique_id, IntegerArrayView new_index)
1484{
1485 // \a true s'il faut réorienter les faces pour que leur orientation
1486 // soit indépendante du partitionnement du maillage initial.
1487 bool need_swap_orientation = false;
1488 Integer min_node_index = 0;
1489 Integer nb_node = nodes_unique_id.size();
1490
1491 // Traite directement le cas des arêtes
1492 if (nb_node == 2) {
1493 if (nodes_unique_id[0] < nodes_unique_id[1]) {
1494 new_index[0] = 0;
1495 new_index[1] = 1;
1496 return false;
1497 }
1498 new_index[0] = 1;
1499 new_index[1] = 0;
1500 return true;
1501 }
1502
1503 // L'algorithme suivant oriente les faces en tenant compte uniquement
1504 // de l'ordre de la numérotation de ces noeuds. Si cet ordre est
1505 // conservé lors du partitionnement, alors l'orientation des faces
1506 // sera aussi conservée.
1507
1508 // L'algorithme est le suivant:
1509 // - Recherche le noeud n de plus petit indice.
1510 // - Recherche n-1 et n+1 les indices de ses 2 noeuds voisins.
1511 // - Si (n+1) est inférieur à (n-1), l'orientation n'est pas modifiée.
1512 // - Si (n+1) est supérieur à (n-1), l'orientation est inversée.
1513
1514 // Recherche le noeud de plus petit indice
1515
1516 Int64 min_node = INT64_MAX;
1517 for (Integer k = 0; k < nb_node; ++k) {
1518 Int64 id = nodes_unique_id[k];
1519 if (id < min_node) {
1520 min_node = id;
1521 min_node_index = k;
1522 }
1523 }
1524 Int64 next_node = nodes_unique_id[(min_node_index + 1) % nb_node];
1525 Int64 prev_node = nodes_unique_id[(min_node_index + (nb_node - 1)) % nb_node];
1526 Integer incr = 0 ;
1527 Integer incr2 = 0 ;
1528 if(next_node==min_node)
1529 {
1530 next_node = nodes_unique_id[(min_node_index + 2) % nb_node];
1531 incr = 1 ;
1532 }
1533 if(prev_node==min_node)
1534 {
1535 prev_node = nodes_unique_id[(min_node_index + (nb_node - 2)) % nb_node];
1536 incr2 = nb_node - 1 ;
1537 }
1538 if (next_node > prev_node)
1539 need_swap_orientation = true;
1541 for (Integer k = 0; k < nb_node; ++k) {
1542 Integer index = (nb_node - k + min_node_index + incr) % nb_node;
1543 new_index[k] = index;
1544 }
1545 }
1546 else {
1547 for (Integer k = 0; k < nb_node; ++k) {
1548 Integer index = (k + min_node_index + incr2) % nb_node;
1549 new_index[k] = index;
1550 }
1551 }
1552 return need_swap_orientation;
1553}
1554
1555/*---------------------------------------------------------------------------*/
1556/*---------------------------------------------------------------------------*/
1557
1558Face MeshUtils::
1559getFaceFromNodesLocal(Node node, Int32ConstArrayView face_nodes_local_id)
1560{
1561 Integer n = face_nodes_local_id.size();
1562 for (Integer i = 0, s = node.nbFace(); i < s; ++i) {
1563 Face f(node.face(i));
1564 Integer fn = f.nbNode();
1565 if (fn == n) {
1566 bool same_face = true;
1567 for (Integer zz = 0; zz < n; ++zz)
1568 if (f.node(zz).localId() != face_nodes_local_id[zz]) {
1569 same_face = false;
1570 break;
1571 }
1572 if (same_face)
1573 return f;
1574 }
1575 }
1576 return Face();
1577}
1578
1579/*---------------------------------------------------------------------------*/
1580/*---------------------------------------------------------------------------*/
1581
1582Face MeshUtils::
1583getFaceFromNodesUnique(Node node, Int64ConstArrayView face_nodes_unique_id)
1584{
1585 Integer n = face_nodes_unique_id.size();
1586 for (Integer i = 0, s = node.nbFace(); i < s; ++i) {
1587 Face f(node.face(i));
1588 Integer fn = f.nbNode();
1589 if (fn == n) {
1590 bool same_face = true;
1591 for (Integer zz = 0; zz < n; ++zz)
1592 if (f.node(zz).uniqueId() != face_nodes_unique_id[zz]) {
1593 same_face = false;
1594 break;
1595 }
1596 if (same_face)
1597 return f;
1598 }
1599 }
1600 return Face();
1601}
1602
1603/*---------------------------------------------------------------------------*/
1604/*---------------------------------------------------------------------------*/
1605
1606void MeshUtils::
1607removeItemAndKeepOrder(Int32ArrayView items, Int32 local_id)
1608{
1609 Integer n = items.size();
1610 if (n <= 0)
1611 ARCANE_FATAL("Can not remove item lid={0} because list is empty", local_id);
1612
1613 --n;
1614 if (n == 0) {
1615 if (items[0] == local_id)
1616 return;
1617 }
1618 else {
1619 // Si l'élément est le dernier, ne fait rien.
1620 if (items[n] == local_id)
1621 return;
1622 for (Integer i = 0; i < n; ++i) {
1623 if (items[i] == local_id) {
1624 for (Integer z = i; z < n; ++z)
1625 items[z] = items[z + 1];
1626 return;
1627 }
1628 }
1629 }
1630 // TODO: Il faut activer cela mais pour l'instant cela fait planter un test.
1631 //ARCANE_FATAL("No entity with local_id={0} found in list {1}",local_id,items);
1632}
1633
1634/*---------------------------------------------------------------------------*/
1635/*---------------------------------------------------------------------------*/
1636
1637void MeshUtils::
1638shrinkMeshGroups(IMesh* mesh)
1639{
1640 auto f = [&](ItemGroup& group) {
1641 group.internal()->shrinkMemory();
1642 };
1643 meshvisitor::visitGroups(mesh, f);
1644}
1645
1646/*---------------------------------------------------------------------------*/
1647/*---------------------------------------------------------------------------*/
1648
1649Int64 MeshUtils::
1650printMeshGroupsMemoryUsage(IMesh* mesh, Int32 print_level)
1651{
1652 ITraceMng* tm = mesh->traceMng();
1653 Int64 total_capacity = 0;
1654 Int64 total_computed_capacity = 0;
1655 auto f = [&](ItemGroup& group) {
1656 ItemGroupImpl* p = group.internal();
1657 // Attention à bien prendre la taille du groupe via \a p
1658 // car sinon pour un groupe calculé on le reconstruit.
1659 Int64 c = p->capacity();
1660 bool is_computed = p->hasComputeFunctor();
1661 total_capacity += c;
1662 if (is_computed)
1664 if (print_level >= 1)
1665 tm->info() << "GROUP Name=" << group.name() << " computed?=" << p->hasComputeFunctor()
1666 << " nb_ref=" << p->nbRef() << " size=" << p->size()
1667 << " capacity=" << c;
1668 };
1669 meshvisitor::visitGroups(mesh, f);
1670 tm->info() << "MeshGroupsMemoryUsage: capacity = " << total_capacity
1671 << " computed_capacity=" << total_computed_capacity;
1672 return total_capacity * sizeof(Int32);
1673}
1674
1675/*---------------------------------------------------------------------------*/
1676/*---------------------------------------------------------------------------*/
1677
1678void MeshUtils::
1679dumpSynchronizerTopologyJSON(IVariableSynchronizer* var_syncer, const String& filename)
1680{
1681 IParallelMng* pm = var_syncer->parallelMng();
1682 ITraceMng* tm = pm->traceMng();
1683 Int32 nb_rank = pm->commSize();
1684 Int32 my_rank = pm->commRank();
1685 Int32ConstArrayView comm_ranks = var_syncer->communicatingRanks();
1686
1687 tm->info(4) << "Dumping VariableSynchronizerTopology filename=" << filename;
1688 Int32 nb_comm_rank = comm_ranks.size();
1689
1691 for (Integer i = 0; i < nb_comm_rank; ++i)
1692 nb_items_by_rank[i] = var_syncer->sharedItems(i).size();
1693
1694 JSONWriter json_writer(JSONWriter::FormatFlags::None);
1695 json_writer.beginObject();
1696
1697 if (my_rank == 0) {
1700 json_writer.write("NbNeighbor", all_nb_comm_ranks);
1701
1702 {
1705 json_writer.write("NeighborsRank", all_neighbor_ranks);
1706 }
1707 {
1710 json_writer.write("NeighborsSize", all_nb_items_by_rank);
1711 }
1712 }
1713 else {
1714 pm->gather(Int32ConstArrayView(1, &nb_comm_rank), {}, 0);
1718 }
1719
1720 json_writer.endObject();
1721
1722 if (my_rank == 0) {
1723 std::ofstream ofile(filename.localstr());
1724 auto bytes = json_writer.getBuffer().bytes();
1725 ofile.write(reinterpret_cast<const char*>(bytes.data()), bytes.size());
1726 }
1727}
1728
1729/*---------------------------------------------------------------------------*/
1730/*---------------------------------------------------------------------------*/
1731
1732namespace
1733{
1734 class MyIdsToTest
1735 {
1736 public:
1737
1738 friend bool operator<(const MyIdsToTest& a, const MyIdsToTest& b)
1739 {
1740 return a.ids < b.ids;
1741 }
1742 static constexpr int MAX_SIZE = 16;
1743
1744 public:
1745
1746 std::array<Int32, MAX_SIZE> ids = {};
1747 };
1748
1749 void _computePatternOccurence(const ItemGroup& items, const String& message,
1750 IndexedItemConnectivityViewBase2 cty)
1751 {
1752 std::map<MyIdsToTest, Int32> occurence_map;
1753 Int32 nb_skipped = 0;
1754 ENUMERATE_ (Item, iitem, items) {
1755 Item item = *iitem;
1756 MyIdsToTest diff_ids;
1757
1758 Int32 index = 0;
1759 Int32 lid0 = 0;
1760 bool is_skipped = false;
1761 for (ItemLocalId sub_item : cty.items(item)) {
1762 if (index >= MyIdsToTest::MAX_SIZE) {
1763 is_skipped = true;
1764 break;
1765 }
1766 if (index == 0)
1767 lid0 = sub_item.localId();
1768 diff_ids.ids[index] = sub_item.localId() - lid0;
1769 //info() << " Cell lid=" << item.localId() << " I=" << index << " diff_lid=" << diff_ids.ids[index];
1770 ++index;
1771 }
1772 if (is_skipped)
1773 ++nb_skipped;
1774 else
1775 ++occurence_map[diff_ids];
1776 }
1777 ITraceMng* tm = items.mesh()->traceMng();
1778 tm->info() << "Occurence: " << message << " group=" << items.name()
1779 << " nb=" << items.size() << " map_size=" << occurence_map.size()
1780 << " nb_skipped=" << nb_skipped;
1781 }
1782} // namespace
1783
1784void MeshUtils::
1785computeConnectivityPatternOccurence(IMesh* mesh)
1786{
1788
1790
1791 _computePatternOccurence(mesh->allNodes(), "NodeCells", cty.nodeCell());
1792 _computePatternOccurence(mesh->allNodes(), "NodeFaces", cty.nodeFace());
1793 _computePatternOccurence(mesh->allFaces(), "FaceCells", cty.faceCell());
1794 _computePatternOccurence(mesh->allFaces(), "FaceNodes", cty.faceNode());
1795 _computePatternOccurence(mesh->allCells(), "CellNodes", cty.cellNode());
1796 _computePatternOccurence(mesh->allCells(), "CellFaces", cty.cellFace());
1797}
1798
1799/*---------------------------------------------------------------------------*/
1800/*---------------------------------------------------------------------------*/
1801
1802void MeshUtils::
1803markMeshConnectivitiesAsMostlyReadOnly(IMesh* mesh, RunQueue* queue, bool do_prefetch)
1804{
1805 if (!mesh)
1806 return;
1807 IVariableMng* vm = mesh->variableMng();
1808 VariableCollection used_variables = vm->usedVariables();
1809 const String tag_name = "ArcaneConnectivity";
1810 DataAllocationInfo alloc_info(eMemoryLocationHint::HostAndDeviceMostlyRead);
1811
1812 // Les variables associées à la connectivité ont le tag 'ArcaneConnectivity'.
1814 IVariable* v = *iv;
1815 if (!v->hasTag(tag_name))
1816 continue;
1817 if (v->meshHandle().meshOrNull() == mesh) {
1819 if (do_prefetch)
1820 VariableUtils::prefetchVariableAsync(v, queue);
1821 }
1822 }
1823}
1824
1825/*---------------------------------------------------------------------------*/
1826/*---------------------------------------------------------------------------*/
1827
1828impl::ItemBase MeshUtils::
1829findOneItem(IItemFamily* family, Int64 unique_id)
1830{
1831 ItemInternal* v = family->findOneItem(unique_id);
1832 if (v)
1833 return { v };
1834 return {};
1835}
1836
1837/*---------------------------------------------------------------------------*/
1838/*---------------------------------------------------------------------------*/
1839
1840impl::ItemBase MeshUtils::
1841findOneItem(IItemFamily* family, ItemUniqueId unique_id)
1842{
1843 ItemInternal* v = family->findOneItem(unique_id);
1844 if (v)
1845 return { v };
1846 return {};
1847}
1848
1849/*---------------------------------------------------------------------------*/
1850/*---------------------------------------------------------------------------*/
1851
1852namespace MeshUtils::impl
1853{
1855 Int64 _getMaxUniqueId(const ItemGroup& group, Int64 max_uid)
1856 {
1857 ENUMERATE_ (Item, iitem, group) {
1858 Item item = *iitem;
1859 if (max_uid < item.uniqueId())
1860 max_uid = item.uniqueId();
1861 }
1862 return max_uid;
1863 }
1864} // namespace MeshUtils::impl
1865
1866/*---------------------------------------------------------------------------*/
1867/*---------------------------------------------------------------------------*/
1868
1869ItemUniqueId MeshUtils::
1870getMaxItemUniqueIdCollective(IMesh* mesh)
1871{
1872 Int64 max_uid = NULL_ITEM_UNIQUE_ID;
1873 max_uid = impl::_getMaxUniqueId(mesh->allNodes(), max_uid);
1874 max_uid = impl::_getMaxUniqueId(mesh->allEdges(), max_uid);
1875 max_uid = impl::_getMaxUniqueId(mesh->allCells(), max_uid);
1876 max_uid = impl::_getMaxUniqueId(mesh->allFaces(), max_uid);
1877 Int64 global_max = mesh->parallelMng()->reduce(Parallel::ReduceMax, max_uid);
1878 return ItemUniqueId(global_max);
1879}
1880
1881/*---------------------------------------------------------------------------*/
1882/*---------------------------------------------------------------------------*/
1883
1884void MeshUtils::
1885checkUniqueIdsHashCollective(IItemFamily* family, IHashAlgorithm* hash_algo,
1886 const String& expected_hash, bool print_hash,
1887 bool include_ghost)
1888{
1889 ARCANE_CHECK_POINTER(family);
1891
1892 IParallelMng* pm = family->parallelMng();
1893 ITraceMng* tm = family->traceMng();
1894
1896 ItemGroup own_items_group = (include_ghost ? family->allItems() : family->allItems().own());
1898 Item item{ *iitem };
1899 own_items_uid.add(item.uniqueId());
1900 }
1903 std::sort(global_items_uid.begin(), global_items_uid.end());
1904
1906 hash_algo->computeHash64(asBytes(global_items_uid.constSpan()), hash_result);
1908 if (print_hash)
1909 tm->info() << "HASH_RESULT family=" << family->name()
1910 << " v=" << hash_str << " expected=" << expected_hash;
1911 if (!expected_hash.empty() && hash_str != expected_hash)
1912 ARCANE_FATAL("Bad hash for uniqueId() for family '{0}' v={1} expected='{2}'",
1913 family->fullName(), hash_str, expected_hash);
1914}
1915
1916/*---------------------------------------------------------------------------*/
1917/*---------------------------------------------------------------------------*/
1918
1919void MeshUtils::
1920fillUniqueIds(ItemVectorView items,Array<Int64>& uids)
1921{
1922 Integer nb_item = items.size();
1923 uids.resize(nb_item);
1924 ENUMERATE_ITEM (iitem, items)
1925 uids[iitem.index()] = iitem->uniqueId();
1926}
1927
1928/*---------------------------------------------------------------------------*/
1929/*---------------------------------------------------------------------------*/
1930
1931Int64 MeshUtils::
1932generateHashUniqueId(SmallSpan<const Int64> nodes_unique_id)
1933{
1934 // Prend les 30 premiers bits du premier nœud pour former
1935 // les 30 premiers bits de la fonction de hash.
1936 // Les 32 bits suivants sont formées avec la fonction de hash.
1937 // Le uniqueId() généré doit toujours être strictement positif
1938 // sauf pour l'entité nulle.
1939 Int32 nb_node = nodes_unique_id.size();
1940 if (nb_node == 0)
1941 return -1;
1943 Int64 uid0 = nodes_unique_id[0];
1944 Int64 hash = Hasher::hashfunc(uid0);
1945 for (Int32 i = 1; i < nb_node; ++i) {
1946 Int64 next_hash = Hasher::hashfunc(nodes_unique_id[i]);
1947 hash ^= next_hash + 0x9e3779b9 + (hash << 6) + (hash >> 2);
1948 }
1949 Int64 truncated_uid0 = uid0 & ((1 << 30) - 1);
1950 Int64 truncated_hash = hash & ((1LL << 31) - 1);
1951 Int64 new_uid = truncated_uid0 + (truncated_hash << 31);
1952 ARCANE_ASSERT(new_uid > 0, ("UniqueId is not > 0"));
1953 return new_uid;
1954}
1955
1956/*---------------------------------------------------------------------------*/
1957/*---------------------------------------------------------------------------*/
1958
1959} // End namespace Arcane
1960
1961/*---------------------------------------------------------------------------*/
1962/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#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.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions mathématiques diverses.
Fonctions utilitaires sur le maillage.
Fonctions utilitaires sur les variables.
File d'exécution pour un accélérateur.
Tableau d'items de types quelconques.
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1178
EnumeratorT< ItemGroup > Enumerator
Type d'un itérateur sur toute la collection.
Definition Collection.h:129
Informations sur l'allocation d'une donnée.
Vue sur les informations des arêtes.
Arête d'une maille.
Definition Item.h:798
Cell cell(Int32 i) const
i-ème maille de l'arête
Definition Item.h:1583
Face face(Int32 i) const
i-ème face de l'arête
Definition Item.h:1577
Int32 nbFace() const
Nombre de faces connectées à l'arête.
Definition Item.h:875
Int32 nbNode() const
Nombre de sommets de l'arête.
Definition Item.h:872
Int32 nbCell() const
Nombre de mailles connectées à l'arête.
Definition Item.h:878
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:932
Cell frontCell() const
Maille devant la face (maille nulle si aucune)
Definition Item.h:1604
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1617
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
Definition Item.h:1006
Edge edge(Int32 i) const
i-ème arête de la face
Definition Item.h:1120
Int32 nbEdge() const
Nombre d'arêtes de la face.
Definition Item.h:1117
Cell backCell() const
Maille derrière la face (maille nulle si aucune)
Definition Item.h:1598
Informations sur le type flottant.
Definition Limits.h:48
Interface d'un algorithme de hashage.
Interface d'une famille d'entités.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual ItemInternal * findOneItem(Int64 unique_id)=0
Entité de numéro unique unique_id.
virtual IParallelMng * parallelMng() const =0
Gestionnaire de parallélisme associé
virtual String name() const =0
Nom de la famille.
virtual ITraceMng * traceMng() const =0
Gestionnaire de trace associé
virtual String fullName() const =0
Nom complet de la famille (avec celui du maillage)
virtual ITraceMng * traceMng()=0
Gestionnaire de message associé
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual Integer nbCell()=0
Nombre de mailles du maillage.
virtual FaceGroup allFaces()=0
Groupe de toutes les faces.
virtual Integer nbEdge()=0
Nombre d'arêtes du maillage.
virtual IItemFamily * itemFamily(eItemKind ik)=0
Retourne la famille d'entité de type ik.
virtual IItemFamily * edgeFamily()=0
Retourne la famille des arêtes.
virtual Integer nbNode()=0
Nombre de noeuds du maillage.
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual Integer nbFace()=0
Nombre de faces du maillage.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual EdgeGroup allEdges()=0
Groupe de toutes les arêtes.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual ItemInternalList itemsInternal(eItemKind)=0
Tableau interne des éléments du maillage de type type.
virtual TiedInterfaceCollection tiedInterfaces()=0
Liste des interfaces semi-conformes.
virtual SharedVariableNodeReal3 sharedNodesCoordinates()=0
Coordonnées des noeuds.
virtual ItemGroupCollection groups()=0
Liste des groupes.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
virtual IVariableMng * variableMng() const =0
Gestionnaire de variable associé
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual void gatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf, Int32 rank)=0
Effectue un regroupement sur tous les processeurs.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void gather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Int32 rank)=0
Effectue un regroupement sur un processeurs. Il s'agit d'une opération collective....
Interface d'un classe gérant une semi-conformité du maillage.
Interface du gestionnaire de variables.
Interface d'un service de synchronisation de variable.
Interface d'une variable.
Definition IVariable.h:54
virtual bool hasTag(const String &tagname)=0
true si la variable possède le tag tagname
virtual void setAllocationInfo(const DataAllocationInfo &v)=0
Positionne les informations sur l'allocation.
virtual MeshHandle meshHandle() const =0
Maillage auquel est associé la variable.
static IXmlDocumentHolder * loadFromFile(const String &filename, ITraceMng *tm)
Charge un document XML.
Definition DomUtils.cc:445
Classe de base pour les entités du maillage.
Integer nbEdge() const
Nombre d'arêtes de l'entité ou nombre d'arêtes connectés à l'entités (pour les noeuds)
ItemUniqueId uniqueId() const
Numéro unique de l'entité
Integer nbCell() const
Nombre de mailles connectées à l'entité (pour les noeuds, arêtes et faces)
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Integer nbFace() const
Nombre de faces de l'entité ou nombre de faces connectés à l'entités (pour les noeuds et arêtes)
Integer nbNode() const
Nombre de noeuds de l'entité
Implémentation d'un groupe d'entités de maillage.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isLocalToSubDomain() const
Vrai si le groupe est local au sous-domaine.
Definition ItemGroup.h:225
Structure interne d'une entité de maillage.
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:35
static eItemKind kind()
Genre de l'entité
Definition ItemTypes.h:624
Identifiant unique d'une entité.
Vue sur un vecteur d'entités.
Int32 size() const
Nombre d'éléments du vecteur.
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:714
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
Classe de base d'un élément de maillage.
Definition Item.h:83
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Ecrivain au format JSON.
Definition JSONWriter.h:33
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Dom.h:204
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1568
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:670
Face face(Int32 i) const
i-ème face du noeud
Definition Item.h:1562
Int32 nbFace() const
Nombre de faces connectées au noeud.
Definition Item.h:640
Int32 nbCell() const
Nombre de mailles connectées au noeud.
Definition Item.h:643
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Face semi-conforme du maillage.
Definition TiedFace.h:35
Noeud semi-conforme du maillage.
Definition TiedNode.h:41
Vue sur les connectivités standards d'un maillage non structuré.
Collection de variables.
Noeud d'un arbre DOM.
Definition XmlNode.h:51
XmlNode child(const String &name) const
Noeud fils de celui-ci de nom name.
Definition XmlNode.cc:64
Classe pour calculer le hash d'un tableau.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
constexpr Integer length() const noexcept
Nombre d'éléments du tableau.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual TraceMessage error()=0
Flot pour un message d'erreur.
Exception lorsqu'une fonction n'est pas implémentée.
Chaîne de caractères unicode.
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
Definition String.cc:315
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage info() const
Flot pour un message d'information.
Positionne une classe de message.
Formattage du flot en longueur.
Vecteur 1D de données avec sémantique par valeur (style STL).
ItemEnumeratorT< Node > NodeEnumerator
Enumérateurs sur des noeuds.
Definition ItemTypes.h:254
Integer toInteger(Real r)
Converti un Int64 en un Integer.
String toHexaString(ByteConstArrayView input)
Converti un tableau d'octet en sa représentation hexadécimale.
Definition Convert.cc:388
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:325
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
bool operator<(const Item &item1, const Item &item2)
Compare deux entités.
Definition Item.h:533
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
eItemKind
Genre d'entité de maillage.
@ IK_Particle
Entité de maillage de genre particule.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
const char * itemKindName(eItemKind kind)
Nom du genre d'entité.
Int32 Integer
Type représentant un entier.