16
16
#include < iostream>
17
17
#include < numeric>
18
18
#include < functional>
19
+ #include < memory>
19
20
20
21
#include < vtkUnstructuredGrid.h>
21
22
#include < vtkUnstructuredGridReader.h>
45
46
#include " arcane/core/IPrimaryMesh.h"
46
47
#include " arcane/core/MeshUtils.h"
47
48
#include " arcane/core/IMeshInitialAllocator.h"
49
+ #include " arcane/core/IVariableMng.h"
48
50
#include " arcane/utils/ArcaneGlobal.h"
49
51
#include " arcane/utils/ITraceMng.h"
50
52
#include " arcane/utils/UniqueArray.h"
56
58
#include " arcane/core/ItemAllocationInfo.h"
57
59
#include " arcane/core/VariableBuildInfo.h"
58
60
61
+ #include " arcane/utils/OStringStream.h"
62
+
63
+ #include " arcane/core/IXmlDocumentHolder.h"
64
+ #include " arcane/core/XmlNode.h"
65
+ #include " arcane/core/internal/IVariableMngInternal.h"
66
+
59
67
#include " arcane/std/VtkPolyhedralMeshIO_axl.h"
60
68
61
69
/* ---------------------------------------------------------------------------*/
@@ -97,6 +105,8 @@ class VtkPolyhedralMeshIOService
97
105
98
106
explicit VtkReader (const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level = VtkPolyhedralTools::PrintInfoLevel{});
99
107
108
+ VtkReader () = default ;
109
+
100
110
static String supportedVtkExtensions () noexcept {return " vtk,vtu" ;};
101
111
102
112
Int64ConstArrayView cellUids ();
@@ -151,9 +161,14 @@ class VtkPolyhedralMeshIOService
151
161
vtkPointData* pointData ();
152
162
vtkCellData* faceData ();
153
163
164
+ bool isEmpty () const noexcept { return m_is_empty; }
165
+ bool doRead () const noexcept { return m_do_read; }
166
+
154
167
private:
155
168
156
- const String& m_filename;
169
+ bool m_is_empty = true ;
170
+ bool m_do_read = false ;
171
+ String m_filename;
157
172
VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
158
173
VtkPolyhedralTools::ReadStatus m_read_status;
159
174
vtkNew<vtkUnstructuredGridReader> m_vtk_grid_reader;
@@ -195,23 +210,27 @@ class VtkPolyhedralMeshIOService
195
210
196
211
public:
197
212
198
- VtkPolyhedralTools::ReadStatus read (IPrimaryMesh* mesh, const String& filename)
213
+ VtkPolyhedralTools::ReadStatus read (IPrimaryMesh* mesh, const String& filename, bool is_parallel_read )
199
214
{
200
215
ARCANE_CHECK_POINTER (mesh);
201
- VtkReader reader{ filename, m_print_info_level };
202
- if (reader.readHasFailed ())
203
- return reader.readStatus ();
216
+ // warning meaning of parallel_read not obvious :
217
+ // if is parallel_read => master reads + broadcast, if not all ranks read a pre-distributed mesh
218
+ bool do_read = is_parallel_read ? mesh->parallelMng ()->isMasterIO () : true ;
219
+ using VtkReaderPtr = std::unique_ptr<VtkReader>;
220
+ VtkReaderPtr reader = std::make_unique<VtkReader>();
221
+ if (do_read) reader = std::make_unique<VtkReader>( filename, m_print_info_level );
222
+ if (reader->readHasFailed ())
223
+ return reader->readStatus ();
204
224
ItemAllocationInfo item_allocation_info;
205
- _fillItemAllocationInfo (item_allocation_info, reader);
225
+ _fillItemAllocationInfo (item_allocation_info, * reader);
206
226
auto polyhedral_mesh_allocator = mesh->initialAllocator ()->polyhedralMeshAllocator ();
207
227
polyhedral_mesh_allocator->allocateItems (item_allocation_info);
208
- _readVariablesAndGroups (mesh, reader);
209
- return reader. readStatus ();
228
+ _readVariablesAndGroups (mesh, * reader);
229
+ return reader-> readStatus ();
210
230
}
211
231
212
232
private:
213
233
214
- UniqueArray<VariableRef*> m_read_variables;
215
234
VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
216
235
217
236
void _readVariablesAndGroups (IPrimaryMesh* mesh, VtkReader& reader);
@@ -220,6 +239,7 @@ class VtkPolyhedralMeshIOService
220
239
221
240
static void _fillItemAllocationInfo (ItemAllocationInfo& item_allocation_info, VtkReader& vtk_reader);
222
241
void _computeFaceVtkArcaneLidConversion (Int32Span face_vtk_to_arcane_lids, Int32Span arcane_to_vtk_lids, VtkPolyhedralMeshIOService::VtkReader& reader, IPrimaryMesh* mesh) const ;
242
+ void _createEmptyVariablesAndGroups (IMesh* mesh, XmlNode::const_reference xml_node) const ;
223
243
};
224
244
225
245
/* ---------------------------------------------------------------------------*/
@@ -255,7 +275,7 @@ class VtkPolyhedralCaseMeshReader
255
275
m_trace_mng->info () << " ---Create Polyhedral mesh: " << pm->name () << " ---" ;
256
276
m_trace_mng->info () << " --Read mesh file " << m_read_info.fileName ();
257
277
VtkPolyhedralMeshIOService polyhedral_vtk_service{ m_trace_mng, m_print_info_level };
258
- auto read_status = polyhedral_vtk_service.read (pm, m_read_info.fileName ());
278
+ auto read_status = polyhedral_vtk_service.read (pm, m_read_info.fileName (),m_read_info. isParallelRead () );
259
279
if (read_status.failure )
260
280
ARCANE_FATAL (read_status.failure_message );
261
281
m_trace_mng->info () << read_status.info_message ;
@@ -418,6 +438,10 @@ _fillItemAllocationInfo(ItemAllocationInfo& item_allocation_info, VtkReader& vtk
418
438
void VtkPolyhedralMeshIOService::
419
439
_readVariablesAndGroups (IPrimaryMesh* mesh, VtkReader& reader)
420
440
{
441
+ // Register variable and group info in an xml for non reader ranks
442
+ OStringStream created_infos_str;
443
+ created_infos_str () << " <?xml version='1.0' ?>\n " ;
444
+ created_infos_str () << " <infos>" ;
421
445
// Cell data
422
446
if (auto * cell_data = reader.cellData (); cell_data) {
423
447
// Read cell groups and variables
@@ -428,10 +452,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
428
452
auto * cell_array = cell_data->GetArray (array_index);
429
453
if (!cell_array)
430
454
continue ;
431
- if (String name = cell_array->GetName (); name.substring (0 , 6 ) == " GROUP_" )
455
+ if (String name = cell_array->GetName (); name.substring (0 , 6 ) == " GROUP_" ) {
432
456
_createGroup (cell_array, name.substring (6 ), mesh, mesh->cellFamily (), vtk_to_arcane_lids.constSpan ());
433
- else
457
+ created_infos_str () << " <cell-group name='" << name.substring (6 ) << " '/>" ;
458
+ }
459
+ else {
434
460
_createVariable (cell_array, name, mesh, mesh->cellFamily (), arcane_to_vtk_lids);
461
+ created_infos_str () << " <cell-variable name='" << name << " '/>" ;
462
+ }
435
463
if (m_print_info_level.print_debug_info ) {
436
464
debug (Trace::High) << " Reading property " << cell_array->GetName ();
437
465
for (auto tuple_index = 0 ; tuple_index < cell_array->GetNumberOfTuples (); ++tuple_index) {
@@ -450,10 +478,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
450
478
Int32SharedArray arcane_to_vtk_lids{ vtk_to_arcane_lids };
451
479
for (auto array_index = 0 ; array_index < point_data->GetNumberOfArrays (); ++array_index) {
452
480
auto * point_array = point_data->GetArray (array_index);
453
- if (String name = point_array->GetName (); name.substring (0 , 6 ) == " GROUP_" )
481
+ if (String name = point_array->GetName (); name.substring (0 , 6 ) == " GROUP_" ) {
454
482
_createGroup (point_array, name.substring (6 ), mesh, mesh->nodeFamily (), vtk_to_arcane_lids.constSpan ());
455
- else
483
+ created_infos_str () << " <node-group name='" << name.substring (6 ) << " '/>" ;
484
+ }
485
+ else {
456
486
_createVariable (point_array, name, mesh, mesh->nodeFamily (), arcane_to_vtk_lids);
487
+ created_infos_str () << " <node-variable name='" << name << " '/>" ;
488
+ }
457
489
if (m_print_info_level.print_debug_info ) {
458
490
debug (Trace::High) << " Reading property " << point_array->GetName ();
459
491
for (auto tuple_index = 0 ; tuple_index < point_array->GetNumberOfTuples (); ++tuple_index) {
@@ -472,10 +504,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
472
504
_computeFaceVtkArcaneLidConversion (vtk_to_Arcane_lids, arcane_to_vtk_lids, reader, mesh);
473
505
for (auto array_index = 0 ; array_index < face_data->GetNumberOfArrays (); ++array_index) {
474
506
auto * face_array = face_data->GetArray (array_index);
475
- if (String name = face_array->GetName (); name.substring (0 , 6 ) == " GROUP_" )
507
+ if (String name = face_array->GetName (); name.substring (0 , 6 ) == " GROUP_" ) {
476
508
_createGroup (face_array, name.substring (6 ), mesh, mesh->faceFamily (), vtk_to_Arcane_lids);
477
- else
509
+ created_infos_str () << " <face-group name='" << name << " '/>" ;
510
+ }
511
+ else {
478
512
_createVariable (face_array, name, mesh, mesh->faceFamily (), arcane_to_vtk_lids);
513
+ created_infos_str () << " <face-variable name='" << name << " '/>" ;
514
+ }
479
515
if (m_print_info_level.print_debug_info ) {
480
516
debug (Trace::High) << " Reading property " << face_array->GetName ();
481
517
for (auto tuple_index = 0 ; tuple_index < face_array->GetNumberOfTuples (); ++tuple_index) {
@@ -486,6 +522,24 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
486
522
}
487
523
}
488
524
}
525
+ created_infos_str () << " </infos>" ;
526
+ // Create empty group and variables in non reader subdomain
527
+ ByteUniqueArray bytes;
528
+ auto * pm = mesh->parallelMng ();
529
+ if (!reader.isEmpty () && pm->isMasterIO ()) {
530
+ String str = created_infos_str.str ();
531
+ ByteConstArrayView bv = str.utf8 ();
532
+ Integer len = bv.size ();
533
+ bytes.resize (len + 1 );
534
+ bytes.copy (bv);
535
+ }
536
+ pm->broadcastMemoryBuffer (bytes, pm->masterIORank ());
537
+ if (reader.isEmpty ()) {
538
+ std::unique_ptr<IXmlDocumentHolder> doc (IXmlDocumentHolder::loadFromBuffer (bytes, " InternalBuffer" , traceMng ()));
539
+ XmlNode doc_node = doc->documentNode ();
540
+ _createEmptyVariablesAndGroups (mesh,doc_node);
541
+
542
+ }
489
543
}
490
544
491
545
/* ---------------------------------------------------------------------------*/
@@ -553,12 +607,12 @@ _createVariable(vtkDataArray* item_values, const String& variable_name, IMesh* m
553
607
if (item_values->GetNumberOfTuples () != item_family->nbItem ())
554
608
ARCANE_FATAL (" Cannot create variable {0}, {1} values are given for {2} items in {3} family" ,
555
609
variable_name, item_values->GetNumberOfTuples (), item_family->nbItem (), item_family->name ());
556
- debug (Trace::High ) << " Create mesh variable " << variable_name;
610
+ debug () << " Create mesh variable " << variable_name;
557
611
auto variable_creator = [mesh, variable_name, item_family, arcane_to_vtk_lids, this ](auto * values) {
558
612
VariableBuildInfo vbi{ mesh, variable_name };
559
613
using ValueType = typename std::remove_pointer_t <decltype (values)>::ValueType;
560
614
auto * var = new ItemVariableScalarRefT<to_arcane_type_t <ValueType>>{ vbi, item_family->itemKind () };
561
- m_read_variables. add (var);
615
+ mesh-> variableMng ()-> _internalApi ()-> addAutoDestroyVariable (var);
562
616
vtkDataArrayAccessor<std::remove_pointer_t <decltype (values)>> values_accessor{ values };
563
617
ENUMERATE_ITEM (item, item_family->allItems ()) {
564
618
(*var)[item] = (to_arcane_type_t <ValueType>)values_accessor.Get (arcane_to_vtk_lids[item.localId ()], 0 );
@@ -568,7 +622,7 @@ _createVariable(vtkDataArray* item_values, const String& variable_name, IMesh* m
568
622
VariableBuildInfo vbi{ mesh, variable_name };
569
623
using ValueType = typename std::remove_pointer_t <decltype (values)>::ValueType;
570
624
auto * var = new ItemVariableArrayRefT<to_arcane_type_t <ValueType>>{ vbi, item_family->itemKind () };
571
- m_read_variables. add (var);
625
+ mesh-> variableMng ()-> _internalApi ()-> addAutoDestroyVariable (var);
572
626
vtkDataArrayAccessor<std::remove_pointer_t <decltype (values)>> values_accessor{ values };
573
627
var->resize (values->GetNumberOfComponents ());
574
628
ENUMERATE_ITEM (item, item_family->allItems ()) {
@@ -623,11 +677,43 @@ _computeFaceVtkArcaneLidConversion(Int32Span face_vtk_to_arcane_lids, Int32Span
623
677
/* ---------------------------------------------------------------------------*/
624
678
/* ---------------------------------------------------------------------------*/
625
679
680
+ void VtkPolyhedralMeshIOService::
681
+ _createEmptyVariablesAndGroups (IMesh* mesh, XmlNode::const_reference variable_and_group_info) const
682
+ {
683
+ // todo generaliser pour tous les kind
684
+ ARCANE_CHECK_PTR (mesh);
685
+ {
686
+ XmlNodeList vars = variable_and_group_info.documentElement ().children (" cell-variable" );
687
+ for (XmlNode xnode : vars) {
688
+ String name = xnode.attrValue (" name" );
689
+ debug () << " Create mesh variable: " << name;
690
+ VariableCellReal* var = new VariableCellReal (VariableBuildInfo (mesh, name));
691
+ mesh->variableMng ()->_internalApi ()->addAutoDestroyVariable (var);
692
+ }
693
+ }
694
+
695
+ // Lecture des groupes de mailles
696
+ {
697
+ XmlNodeList vars = variable_and_group_info.documentElement ().children (" cell-group" );
698
+ IItemFamily* cell_family = mesh->itemFamily (IK_Cell);
699
+ for (XmlNode xnode : vars) {
700
+ String name = xnode.attrValue (" name" );
701
+ info () << " Building group: " << name;
702
+ cell_family->createGroup (name);
703
+ }
704
+ }
705
+ }
706
+
707
+ /* ---------------------------------------------------------------------------*/
708
+ /* ---------------------------------------------------------------------------*/
709
+
626
710
VtkPolyhedralMeshIOService::VtkReader::
627
711
VtkReader (const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level)
628
712
: m_filename{ filename }
629
713
, m_print_info_level{ print_info_level }
630
714
{
715
+ m_is_empty = false ;
716
+ m_do_read = true ;
631
717
if (filename.empty ()) {
632
718
m_read_status.failure = true ;
633
719
m_read_status.failure_message = " filename for polyhedral vtk mesh is empty." ;
@@ -712,6 +798,7 @@ VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_
712
798
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
713
799
cellUids ()
714
800
{
801
+ if (!doRead ()) return m_cell_uids;
715
802
if (m_cell_uids.empty ()) {
716
803
_checkVtkGrid ();
717
804
m_cell_uids.reserve (m_vtk_grid->GetNumberOfCells ());
@@ -736,6 +823,7 @@ cellUids()
736
823
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
737
824
nodeUids ()
738
825
{
826
+ if (!doRead ()) return m_node_uids;
739
827
if (m_node_uids.empty ()) {
740
828
_checkVtkGrid ();
741
829
auto nb_nodes = m_vtk_grid->GetNumberOfPoints ();
@@ -768,6 +856,7 @@ faceUids()
768
856
// Needs nodeUids to be called first (no work done if already called)
769
857
nodeUids ();
770
858
859
+ if (!doRead ()) return m_face_uids;
771
860
if (!m_face_uids.empty ())
772
861
return m_face_uids;
773
862
_checkVtkGrid ();
@@ -904,6 +993,7 @@ faceUids()
904
993
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
905
994
edgeUids ()
906
995
{
996
+ if (!doRead ()) return m_edge_uids;
907
997
if (!m_edge_uids.empty ())
908
998
return m_edge_uids;
909
999
@@ -1394,6 +1484,7 @@ nodeEdges()
1394
1484
Real3ArrayView VtkPolyhedralMeshIOService::VtkReader::
1395
1485
nodeCoords ()
1396
1486
{
1487
+ if (!doRead ()) return m_node_coordinates;
1397
1488
if (m_node_coordinates.empty ()) {
1398
1489
_checkVtkGrid ();
1399
1490
auto point_coords = m_vtk_grid->GetPoints ()->GetData ();
0 commit comments