Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
VoronoiMeshIOService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* VoronoiMeshIOService.cc (C) 2000-2009 */
9/* */
10/* Reading/Writing a Voronoi mesh. Provisional format. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/StdHeader.h"
18#include "arcane/utils/HashTableMap.h"
19#include "arcane/utils/ValueConvert.h"
20#include "arcane/utils/ScopedPtr.h"
21#include "arcane/utils/ITraceMng.h"
22#include "arcane/utils/String.h"
23#include "arcane/utils/IOException.h"
24#include "arcane/utils/Collection.h"
25#include "arcane/utils/Enumerator.h"
26
27#include "arcane/utils/Real3.h"
28
29#include "arcane/core/FactoryService.h"
30#include "arcane/core/IMeshReader.h"
31#include "arcane/core/ISubDomain.h"
32#include "arcane/core/IMeshSubMeshTransition.h"
33#include "arcane/core/IItemFamily.h"
34#include "arcane/core/Item.h"
36#include "arcane/core/VariableTypes.h"
37#include "arcane/core/IVariableAccessor.h"
38#include "arcane/core/IParallelMng.h"
39#include "arcane/core/IIOMng.h"
40#include "arcane/core/IMeshUtilities.h"
41#include "arcane/core/IMeshWriter.h"
42#include "arcane/core/BasicService.h"
43#include "arcane/core/XmlNode.h"
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48namespace Arcane
49{
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54class VoronoiFile;
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58
70class VoronoiMeshIOService
71: public BasicService
72, public IMeshReader
73{
74 public:
75
76 VoronoiMeshIOService(const ServiceBuildInfo& sbi);
77
78 ~VoronoiMeshIOService();
79
80 public:
81
82 virtual void build() {}
83
84 public:
85
86 virtual bool allowExtension(const String& str)
87 {
88 return str == "vor";
89 }
90
91 public:
92
93 virtual eReturnType readMeshFromFile(IPrimaryMesh* mesh, const XmlNode& mesh_node, const String& file_name,
94 const String& dir_name, bool use_internal_partition);
95
96 virtual bool hasCutInfos() const { return false; }
97 virtual ConstArrayView<Integer> communicatingSubDomains() const { return ConstArrayView<Integer>(); }
98
99 private:
100
101 bool _readMesh(IPrimaryMesh* mesh, const String& file_name, const String& dir_name, bool use_internal_partition);
102 bool _readHybridGrid(IPrimaryMesh* mesh, VoronoiFile& voronoi_file, bool use_internal_partition);
103 void _readCellVariable(IMesh* mesh, VoronoiFile& voronoi_file, const String& name_str, Integer nb_cell);
104 void _readItemGroup(IMesh* mesh, VoronoiFile& voronoi_file, const String& name_str, Integer nb_item,
105 eItemKind ik, ConstArrayView<Integer> local_ids);
106 void _createFaceGroup(IMesh* mesh, const String& name, ConstArrayView<Integer> faces_lid);
107 bool _readData(IMesh* mesh, VoronoiFile& voronoi_file, bool use_internal_partition, eItemKind cell_kind,
108 ConstArrayView<Integer> local_ids);
109 void _readNodesHybridGrid(IMesh* mesh, VoronoiFile& voronoi_file, Array<Real3>& node_coords);
110 void _readCellsHybridGrid(IMesh* mesh, VoronoiFile& voronoi_file,
111 Array<Integer>& cells_nb_node,
112 Array<Integer>& cells_type,
113 Array<Int64>& cells_connectivity,
114 Integer& mesh_dimension);
115 void _readFacesMesh(IMesh* mesh, const String& file_name,
116 const String& dir_name, bool use_internal_partition);
117
118 private:
119
122};
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
127class VoronoiFile
128{
129 public:
130
131 static const int BUFSIZE = 10000;
132
133 public:
134
135 VoronoiFile(std::istream* stream)
136 : m_stream(stream)
137 {}
138 const char* getNextLine();
139 Real getReal();
140 Integer getInteger();
141 bool isEnd()
142 {
143 (*m_stream) >> ws;
144 return m_stream->eof();
145 }
146
147 private:
148
149 std::istream* m_stream;
150 char m_buf[BUFSIZE];
151};
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156const char* VoronoiFile::
157getNextLine()
158{
159 while (m_stream->good()) {
160 m_stream->getline(m_buf, sizeof(m_buf) - 1);
161 if (m_stream->eof())
162 break;
163 bool is_comment = true;
164 if (m_buf[0] == '\n' || m_buf[0] == '\r')
165 continue;
166 // Regarde si un caractère de commentaire est présent
167 for (int i = 0; i < BUFSIZE && m_buf[i] != '\0'; ++i) {
168 if (!isspace(m_buf[i])) {
169 is_comment = (m_buf[i] == '#');
170 break;
171 }
172 }
173 if (!is_comment) {
174
175 // Supprime le '\n' ou '\r' final
176 for (int i = 0; i < BUFSIZE && m_buf[i] != '\0'; ++i) {
177 //cout << " V=" << m_buf[i] << " I=" << (int)m_buf[i] << "\n";
178 if (m_buf[i] == '\n' || m_buf[i] == '\r') {
179 m_buf[i] = '\0';
180 break;
181 }
182 }
183 return m_buf;
184 }
185 }
186 throw IOException("VoronoiFile::getNexLine()", "Unexpected EndOfFile");
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191
192Real VoronoiFile::
193getReal()
194{
195 Real v = 0.;
196 (*m_stream) >> ws >> v;
197 if (m_stream->good())
198 return v;
199 throw IOException("VoronoiFile::getReal()", "Bad Real");
200}
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
205Integer VoronoiFile::
206getInteger()
207{
208 Integer v = 0;
209 (*m_stream) >> ws >> v;
210 if (m_stream->good())
211 return v;
212 throw IOException("VoronoiFile::getInteger()", "Bad Integer");
213}
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
219
220/*---------------------------------------------------------------------------*/
221/*---------------------------------------------------------------------------*/
222
223VoronoiMeshIOService::
224VoronoiMeshIOService(const ServiceBuildInfo& sbi)
225: BasicService(sbi)
226{
227}
228
229/*---------------------------------------------------------------------------*/
230/*---------------------------------------------------------------------------*/
231
232VoronoiMeshIOService::
233~VoronoiMeshIOService()
234{
235 const Integer size = m_variables.size();
236 for (Integer i = 0; i < size; ++i) {
237 delete m_variables[i];
238 m_variables[i] = NULL;
239 }
240}
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
249readMeshFromFile(IPrimaryMesh* mesh, const XmlNode& mesh_node,
250 const String& filename, const String& dir_name,
251 bool use_internal_partition)
252{
253 ARCANE_UNUSED(mesh_node);
254 ARCANE_UNUSED(use_internal_partition);
255
256 bool ret = _readMesh(mesh, filename, dir_name, use_internal_partition);
257 if (ret)
258 return RTError;
259
260 return RTOk;
261}
262
263/*---------------------------------------------------------------------------*/
264/*---------------------------------------------------------------------------*/
265
266bool VoronoiMeshIOService::
267_readMesh(IPrimaryMesh* mesh, const String& file_name, const String& dir_name,
268 bool use_internal_partition)
269{
270 ARCANE_UNUSED(dir_name);
271
272 std::ifstream ifile(file_name.localstr());
273 if (!ifile) {
274 error() << "Unable to read file '" << file_name << "'";
275 return true;
276 }
277 VoronoiFile voronoi_file(&ifile);
278
279 // Lecture du type de maillage
280 // TODO: en parallèle, avec use_internal_partition vrai, seul le processeur 0
281 // lit les données. Dans ce cas, inutile que les autres ouvre le fichier.
282
283 bool ret = true;
284 ret = _readHybridGrid(mesh, voronoi_file, use_internal_partition);
285 return ret;
286}
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
295_readNodesHybridGrid(IMesh* mesh, VoronoiFile& voronoi_file, Array<Real3>& node_coords)
296{
297 ARCANE_UNUSED(mesh);
298
299 const char* func_name = "VoronoiMeshIOService::_readNodesHybridGrid()";
300 const char* buf = voronoi_file.getNextLine();
301 std::istringstream iline(buf);
302 std::string points_str;
303 std::string data_type_str;
304 Integer nb_node = 0;
305 iline >> ws >> nb_node;
306 if (!iline)
307 throw IOException(func_name, "Syntax error while reading number of nodes");
308 if (nb_node < 0) {
309 String msg = String("Invalid number of nodes: n=") + nb_node;
310 throw IOException(func_name, msg);
311 }
312
313 info() << " Info: " << nb_node;
314
315 // Reading coordinates
316 node_coords.resize(nb_node);
317 {
318 for (Integer i = 0; i < nb_node; ++i) {
319 Real nx = voronoi_file.getReal();
320 Real ny = voronoi_file.getReal();
321 Real nz = voronoi_file.getReal();
322 node_coords[i] = Real3(nx, ny, nz);
323 }
324 }
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
337 Array<Integer>& cells_nb_node,
338 Array<Integer>& cells_type,
339 Array<Int64>& cells_connectivity,
340 Integer& mesh_dimension)
341{
342 ARCANE_UNUSED(mesh);
343
344 const char* func_name = "VoronoiMeshIOService::_readCellsHybridGrid()";
345 const char* buf = voronoi_file.getNextLine();
346 std::istringstream iline(buf);
347 std::string cells_str;
348 Integer nb_cell = 0;
349 Integer nb_cell_node = 0;
350 iline >> ws >> nb_cell >> ws >> nb_cell_node;
351 if (!iline)
352 throw IOException(func_name, "Syntax error while reading cells");
353 if (nb_cell < 0 || nb_cell_node < 0) {
354 throw IOException(func_name, String::format("Invalid dimensions: nb_cell={0} nb_cell_node={1}", nb_cell, nb_cell_node));
355 }
356
357 ItemTypeMng* item_type_mng = mesh->itemTypeMng();
358
359 mesh_dimension = 3; // will be set to two if for all types, nb_edges == nb_faces
360 bool is_mesh_2d = true;
361
362 cells_nb_node.resize(nb_cell);
363 cells_type.resize(nb_cell);
364 cells_connectivity.resize(nb_cell_node);
365 {
366 Integer connectivity_index = 0;
367 for (Integer i = 0; i < nb_cell; ++i) {
368 const Integer user_cell_type = voronoi_file.getInteger();
369 const Integer internal_cell_type = user_cell_type + ItemTypeMng::nbBuiltInItemType();
370 cells_type[i] = internal_cell_type;
371 if (user_cell_type < 0 || internal_cell_type >= ItemTypeMng::nbBasicItemType())
372 fatal() << "Bad item type " << user_cell_type;
373 /* const Integer n_check = */ voronoi_file.getInteger();
374 ItemTypeInfo* item_type = item_type_mng->typeFromId(internal_cell_type);
375 is_mesh_2d = is_mesh_2d && (item_type->nbLocalEdge() == item_type->nbLocalFace());
376 // optimizable with a local cache
377 const Integer n = item_type->nbLocalNode();
378 cells_nb_node[i] = n;
379 for (Integer j = 0; j < n; ++j) {
380 const Integer node_id = voronoi_file.getInteger();
381 cells_connectivity[connectivity_index] = node_id;
382 ++connectivity_index;
383 }
384 }
385 }
386 if (is_mesh_2d)
387 mesh_dimension = 2;
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
393bool VoronoiMeshIOService::
394_readHybridGrid(IPrimaryMesh* mesh, VoronoiFile& voronoi_file, bool use_internal_partition)
395{
396 // const char* func_name = "VoronoiMeshIOService::_readUnstructuredGrid()";
397 //IParallelMng* pm = subDomain()->parallelMng();
398 Integer nb_cell = 0;
399 Integer nb_cell_node = 0;
400 Integer sid = subDomain()->subDomainId();
401 UniqueArray<Real3> node_coords;
402 UniqueArray<Int64> cells_infos;
403 UniqueArray<Integer> cells_local_id;
404 UniqueArray<Integer> faces_local_id;
405 // If we use the internal partitioner, only the subdomain reads the mesh
406 bool need_read = true;
407 Integer mesh_dimension(-1);
408 if (use_internal_partition)
409 need_read = (sid == 0);
410
411 if (need_read) {
412 _readNodesHybridGrid(mesh, voronoi_file, node_coords);
413 //nb_node = node_coords.size();
414
415 // Reading cell info
416 // Reading connectivity
417 UniqueArray<Integer> cells_nb_node;
418 UniqueArray<Int64> cells_connectivity;
419 UniqueArray<Integer> cells_type;
420 _readCellsHybridGrid(mesh, voronoi_file, cells_nb_node, cells_type, cells_connectivity, mesh_dimension);
421 nb_cell = cells_nb_node.size();
422 nb_cell_node = cells_connectivity.size();
423 cells_local_id.resize(nb_cell);
424
425 // Cell creation
426 // Info for cell creation
427 // per cell: 1 for its unique id,
428 // 1 for its type,
429 // 1 for each node
430 cells_infos.resize(nb_cell * 2 + nb_cell_node);
431 {
432 Integer cells_infos_index = 0;
433 Integer connectivity_index = 0;
434 for (Integer i = 0; i < nb_cell; ++i) {
435 Integer current_cell_nb_node = cells_nb_node[i];
436 Integer cell_unique_id = i;
437
438 cells_local_id[i] = i;
439
440 cells_infos[cells_infos_index] = cells_type[i];
441 ++cells_infos_index;
442
443 cells_infos[cells_infos_index] = cell_unique_id;
444 ++cells_infos_index;
445
446 for (Integer z = 0; z < current_cell_nb_node; ++z) {
447 cells_infos[cells_infos_index + z] = cells_connectivity[connectivity_index + z];
448 }
449 cells_infos_index += current_cell_nb_node;
450 connectivity_index += current_cell_nb_node;
451 }
452 }
453 }
454
455 Integer dimension = subDomain()->parallelMng()->reduce(Parallel::ReduceMax, mesh_dimension);
456 mesh->setDimension(dimension);
457 mesh->allocateCells(nb_cell, cells_infos, false);
458 mesh->endAllocate();
459
460 // Positions the coordinates
461 {
462 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
463 ENUMERATE_NODE (inode, mesh->allNodes()) {
464 Node node = *inode;
465 Int32 node_uid = node.uniqueId().asInt32();
466 nodes_coord_var[inode] = node_coords[node_uid];
467 }
468 }
469
470 // Now, check if there are data associated with the file
471 bool r = _readData(mesh, voronoi_file, use_internal_partition, IK_Cell, cells_local_id);
472 if (r)
473 return r;
474
475 return false;
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
480
481bool VoronoiMeshIOService::
482_readData(IMesh* mesh, VoronoiFile& voronoi_file, bool use_internal_partition,
483 eItemKind cell_kind, ConstArrayView<Integer> local_ids)
484{
485 ARCANE_UNUSED(use_internal_partition);
486 ARCANE_UNUSED(local_ids);
487
488 // Only the master subdomain reads the values. However, the other
489 // subdomains must know the list of variables
490 Integer sid = subDomain()->subDomainId();
491 Integer nb_cell_kind = mesh->nbItem(cell_kind);
492 if (sid == 0) {
493 _readCellVariable(mesh, voronoi_file, "CellCenter", nb_cell_kind);
494 }
495 if (sid != 0) {
496 VariableCellReal3* var = new VariableCellReal3(VariableBuildInfo(mesh, "CellCenter"));
497 m_variables.add(var);
498 }
499
500 return false;
501}
502
503/*---------------------------------------------------------------------------*/
504/*---------------------------------------------------------------------------*/
505
506void VoronoiMeshIOService::
507_readCellVariable(IMesh* mesh, VoronoiFile& voronoi_file, const String& var_name, Integer nb_cell)
508{
509 //TODO Perform the correct conversion from uniqueId() to localId()
510 Real cx, cy, cz;
511 info() << "Reading values for variable: " << var_name << " n=" << nb_cell;
512 VariableCellReal3* var = new VariableCellReal3(VariableBuildInfo(mesh, var_name));
513 m_variables.add(var);
514 Real3ArrayView values(var->asArray());
515 for (Integer i = 0; i < nb_cell; ++i) {
516 cx = voronoi_file.getReal();
517 cy = voronoi_file.getReal();
518 cz = voronoi_file.getReal();
519 values[i] = Real3(cx, cy, cz);
520 }
521 info() << "Variable build done: " << voronoi_file.isEnd();
522}
523
524/*---------------------------------------------------------------------------*/
525/*---------------------------------------------------------------------------*/
526
527void VoronoiMeshIOService::
528_readItemGroup(IMesh* mesh, VoronoiFile& voronoi_file, const String& name, Integer nb_item,
530{
531 IItemFamily* item_family = mesh->itemFamily(ik);
532 info() << "Reading group info for group: " << name;
533
535 for (Integer i = 0; i < nb_item; ++i) {
536 Integer v = voronoi_file.getInteger();
537 if (v != 0)
538 ids.add(local_ids[i]);
539 }
540 info() << "Building group: " << name << " nb_element=" << ids.size();
541
542 item_family->createGroup(name, ids);
543}
544
545/*---------------------------------------------------------------------------*/
546/*---------------------------------------------------------------------------*/
547
548} // namespace Arcane
549
550/*---------------------------------------------------------------------------*/
551/*---------------------------------------------------------------------------*/
Types and macros for iterating over mesh entities.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
#define ARCANE_REGISTER_SUB_DOMAIN_FACTORY(aclass, ainterface, aname)
Registers a factory service for the class aclass.
Integer size() const
Number of elements in the vector.
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
Base class of a service linked to a subdomain.
Constant view of an array of type T.
Interface of the service managing the reading of a mesh.
Definition IMeshReader.h:33
eReturnType
Types of return codes for a read or write operation.
Definition IMeshReader.h:38
@ RTError
Error during the operation.
Definition IMeshReader.h:40
@ RTOk
Operation successfully performed.
Definition IMeshReader.h:39
Exception when an input/output error is detected.
Definition IOException.h:34
virtual Int32 subDomainId() const =0
Subdomain ID associated with this manager.
Info on a mesh entity type.
Integer nbLocalEdge() const
Number of edges of the entity.
Integer nbLocalNode() const
Number of nodes of the entity.
Integer nbLocalFace() const
Number of faces of the entity.
Mesh entity type manager.
Definition ItemTypeMng.h:66
static Integer nbBasicItemType()
number of available types
ItemTypeInfo * typeFromId(Integer id) const
Type corresponding to the number id.
static Integer nbBuiltInItemType()
number of built-in types (excluding additional types)
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Structure containing the information to create a service.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
1D data vector with value semantics (STL style).
Reader for IFP internal Voronoi mesh files.
virtual void build()
Build-level construction of the service.
virtual eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_node, const String &file_name, const String &dir_name, bool use_internal_partition)
UniqueArray< VariableCellReal3 * > m_variables
Table of variables created locally by reading the mesh.
void _readCellsHybridGrid(IMesh *mesh, VoronoiFile &voronoi_file, Array< Integer > &cells_nb_node, Array< Integer > &cells_type, Array< Int64 > &cells_connectivity, Integer &mesh_dimension)
Reading of cells and their connectivity.
void _readNodesHybridGrid(IMesh *mesh, VoronoiFile &voronoi_file, Array< Real3 > &node_coords)
Reading of nodes and their coordinates.
virtual bool allowExtension(const String &str)
Checks if the service supports files with the extension str.
Node of a DOM tree.
Definition XmlNode.h:51
MeshVariableScalarRefT< Cell, Real3 > VariableCellReal3
Coordinate type quantity at cell center.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
@ ReduceMax
Maximum of values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ArrayView< Real3 > Real3ArrayView
C equivalent of a 1D array of Real3.
Definition UtilsTypes.h:467
Int32 Integer
Type representing an integer.
eItemKind
Mesh entity type.
@ IK_Cell
Cell mesh entity.
double Real
Type representing a real number.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
std::int32_t Int32
Signed integer type of 32 bits.