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