Skip to content

Commit 28d334e

Browse files
authored
Merge pull request #1829 from arcaneframework/dev/sdc-vtk-polyhedral-reader-only-on-io-master
Read polyhedral mesh on master io only.
2 parents 6e652c6 + e9e6769 commit 28d334e

File tree

4 files changed

+113
-21
lines changed

4 files changed

+113
-21
lines changed

arcane/src/arcane/mesh/PolyhedralMesh.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -813,8 +813,7 @@ allocateItems(const Arcane::ItemAllocationInfo& item_allocation_info)
813813
m_mesh->applyScheduledOperations();
814814
// Create variable for coordinates. This has to be done before call to family::endUpdate. Todo add to the graph
815815
for (auto& family_info : item_allocation_info.family_infos) {
816-
if (family_info.item_coordinates.empty()) {
817-
++family_index;
816+
if (family_info.item_kind != IK_Node && family_info.item_coordinates.empty()) { // variable is created for node even if no coords (parallel)
818817
continue;
819818
}
820819
auto* item_family = _findItemFamily(family_info.item_kind, family_info.name);

arcane/src/arcane/std/VtkPolyhedralMeshIOService.cc

+110-19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <iostream>
1717
#include <numeric>
1818
#include <functional>
19+
#include <memory>
1920

2021
#include <vtkUnstructuredGrid.h>
2122
#include <vtkUnstructuredGridReader.h>
@@ -45,6 +46,7 @@
4546
#include "arcane/core/IPrimaryMesh.h"
4647
#include "arcane/core/MeshUtils.h"
4748
#include "arcane/core/IMeshInitialAllocator.h"
49+
#include "arcane/core/IVariableMng.h"
4850
#include "arcane/utils/ArcaneGlobal.h"
4951
#include "arcane/utils/ITraceMng.h"
5052
#include "arcane/utils/UniqueArray.h"
@@ -56,6 +58,12 @@
5658
#include "arcane/core/ItemAllocationInfo.h"
5759
#include "arcane/core/VariableBuildInfo.h"
5860

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+
5967
#include "arcane/std/VtkPolyhedralMeshIO_axl.h"
6068

6169
/*---------------------------------------------------------------------------*/
@@ -97,6 +105,8 @@ class VtkPolyhedralMeshIOService
97105

98106
explicit VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level = VtkPolyhedralTools::PrintInfoLevel{});
99107

108+
VtkReader() = default;
109+
100110
static String supportedVtkExtensions() noexcept {return "vtk,vtu";};
101111

102112
Int64ConstArrayView cellUids();
@@ -151,9 +161,14 @@ class VtkPolyhedralMeshIOService
151161
vtkPointData* pointData();
152162
vtkCellData* faceData();
153163

164+
bool isEmpty() const noexcept { return m_is_empty; }
165+
bool doRead() const noexcept { return m_do_read; }
166+
154167
private:
155168

156-
const String& m_filename;
169+
bool m_is_empty = true;
170+
bool m_do_read = false;
171+
String m_filename;
157172
VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
158173
VtkPolyhedralTools::ReadStatus m_read_status;
159174
vtkNew<vtkUnstructuredGridReader> m_vtk_grid_reader;
@@ -195,23 +210,27 @@ class VtkPolyhedralMeshIOService
195210

196211
public:
197212

198-
VtkPolyhedralTools::ReadStatus read(IPrimaryMesh* mesh, const String& filename)
213+
VtkPolyhedralTools::ReadStatus read(IPrimaryMesh* mesh, const String& filename, bool is_parallel_read)
199214
{
200215
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();
204224
ItemAllocationInfo item_allocation_info;
205-
_fillItemAllocationInfo(item_allocation_info, reader);
225+
_fillItemAllocationInfo(item_allocation_info, *reader);
206226
auto polyhedral_mesh_allocator = mesh->initialAllocator()->polyhedralMeshAllocator();
207227
polyhedral_mesh_allocator->allocateItems(item_allocation_info);
208-
_readVariablesAndGroups(mesh, reader);
209-
return reader.readStatus();
228+
_readVariablesAndGroups(mesh, *reader);
229+
return reader->readStatus();
210230
}
211231

212232
private:
213233

214-
UniqueArray<VariableRef*> m_read_variables;
215234
VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
216235

217236
void _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader);
@@ -220,6 +239,7 @@ class VtkPolyhedralMeshIOService
220239

221240
static void _fillItemAllocationInfo(ItemAllocationInfo& item_allocation_info, VtkReader& vtk_reader);
222241
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;
223243
};
224244

225245
/*---------------------------------------------------------------------------*/
@@ -255,7 +275,7 @@ class VtkPolyhedralCaseMeshReader
255275
m_trace_mng->info() << "---Create Polyhedral mesh: " << pm->name() << "---";
256276
m_trace_mng->info() << "--Read mesh file " << m_read_info.fileName();
257277
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());
259279
if (read_status.failure)
260280
ARCANE_FATAL(read_status.failure_message);
261281
m_trace_mng->info() << read_status.info_message;
@@ -418,6 +438,10 @@ _fillItemAllocationInfo(ItemAllocationInfo& item_allocation_info, VtkReader& vtk
418438
void VtkPolyhedralMeshIOService::
419439
_readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
420440
{
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>";
421445
// Cell data
422446
if (auto* cell_data = reader.cellData(); cell_data) {
423447
// Read cell groups and variables
@@ -428,10 +452,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
428452
auto* cell_array = cell_data->GetArray(array_index);
429453
if (!cell_array)
430454
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_") {
432456
_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 {
434460
_createVariable(cell_array, name, mesh, mesh->cellFamily(), arcane_to_vtk_lids);
461+
created_infos_str() << "<cell-variable name='" << name << "'/>";
462+
}
435463
if (m_print_info_level.print_debug_info) {
436464
debug(Trace::High) << "Reading property " << cell_array->GetName();
437465
for (auto tuple_index = 0; tuple_index < cell_array->GetNumberOfTuples(); ++tuple_index) {
@@ -450,10 +478,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
450478
Int32SharedArray arcane_to_vtk_lids{ vtk_to_arcane_lids };
451479
for (auto array_index = 0; array_index < point_data->GetNumberOfArrays(); ++array_index) {
452480
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_") {
454482
_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 {
456486
_createVariable(point_array, name, mesh, mesh->nodeFamily(), arcane_to_vtk_lids);
487+
created_infos_str() << "<node-variable name='" << name << "'/>";
488+
}
457489
if (m_print_info_level.print_debug_info) {
458490
debug(Trace::High) << "Reading property " << point_array->GetName();
459491
for (auto tuple_index = 0; tuple_index < point_array->GetNumberOfTuples(); ++tuple_index) {
@@ -472,10 +504,14 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
472504
_computeFaceVtkArcaneLidConversion(vtk_to_Arcane_lids, arcane_to_vtk_lids, reader, mesh);
473505
for (auto array_index = 0; array_index < face_data->GetNumberOfArrays(); ++array_index) {
474506
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_") {
476508
_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 {
478512
_createVariable(face_array, name, mesh, mesh->faceFamily(), arcane_to_vtk_lids);
513+
created_infos_str() << "<face-variable name='" << name << "'/>";
514+
}
479515
if (m_print_info_level.print_debug_info) {
480516
debug(Trace::High) << "Reading property " << face_array->GetName();
481517
for (auto tuple_index = 0; tuple_index < face_array->GetNumberOfTuples(); ++tuple_index) {
@@ -486,6 +522,24 @@ _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
486522
}
487523
}
488524
}
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+
}
489543
}
490544

491545
/*---------------------------------------------------------------------------*/
@@ -553,12 +607,12 @@ _createVariable(vtkDataArray* item_values, const String& variable_name, IMesh* m
553607
if (item_values->GetNumberOfTuples() != item_family->nbItem())
554608
ARCANE_FATAL("Cannot create variable {0}, {1} values are given for {2} items in {3} family",
555609
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;
557611
auto variable_creator = [mesh, variable_name, item_family, arcane_to_vtk_lids, this](auto* values) {
558612
VariableBuildInfo vbi{ mesh, variable_name };
559613
using ValueType = typename std::remove_pointer_t<decltype(values)>::ValueType;
560614
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);
562616
vtkDataArrayAccessor<std::remove_pointer_t<decltype(values)>> values_accessor{ values };
563617
ENUMERATE_ITEM (item, item_family->allItems()) {
564618
(*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
568622
VariableBuildInfo vbi{ mesh, variable_name };
569623
using ValueType = typename std::remove_pointer_t<decltype(values)>::ValueType;
570624
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);
572626
vtkDataArrayAccessor<std::remove_pointer_t<decltype(values)>> values_accessor{ values };
573627
var->resize(values->GetNumberOfComponents());
574628
ENUMERATE_ITEM (item, item_family->allItems()) {
@@ -623,11 +677,43 @@ _computeFaceVtkArcaneLidConversion(Int32Span face_vtk_to_arcane_lids, Int32Span
623677
/*---------------------------------------------------------------------------*/
624678
/*---------------------------------------------------------------------------*/
625679

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+
626710
VtkPolyhedralMeshIOService::VtkReader::
627711
VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level)
628712
: m_filename{ filename }
629713
, m_print_info_level{ print_info_level }
630714
{
715+
m_is_empty = false;
716+
m_do_read = true;
631717
if (filename.empty()) {
632718
m_read_status.failure = true;
633719
m_read_status.failure_message = "filename for polyhedral vtk mesh is empty.";
@@ -712,6 +798,7 @@ VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_
712798
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
713799
cellUids()
714800
{
801+
if (!doRead()) return m_cell_uids;
715802
if (m_cell_uids.empty()) {
716803
_checkVtkGrid();
717804
m_cell_uids.reserve(m_vtk_grid->GetNumberOfCells());
@@ -736,6 +823,7 @@ cellUids()
736823
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
737824
nodeUids()
738825
{
826+
if (!doRead()) return m_node_uids;
739827
if (m_node_uids.empty()) {
740828
_checkVtkGrid();
741829
auto nb_nodes = m_vtk_grid->GetNumberOfPoints();
@@ -768,6 +856,7 @@ faceUids()
768856
// Needs nodeUids to be called first (no work done if already called)
769857
nodeUids();
770858

859+
if (!doRead()) return m_face_uids;
771860
if (!m_face_uids.empty())
772861
return m_face_uids;
773862
_checkVtkGrid();
@@ -904,6 +993,7 @@ faceUids()
904993
Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
905994
edgeUids()
906995
{
996+
if (!doRead()) return m_edge_uids;
907997
if (!m_edge_uids.empty())
908998
return m_edge_uids;
909999

@@ -1394,6 +1484,7 @@ nodeEdges()
13941484
Real3ArrayView VtkPolyhedralMeshIOService::VtkReader::
13951485
nodeCoords()
13961486
{
1487+
if (!doRead()) return m_node_coordinates;
13971488
if (m_node_coordinates.empty()) {
13981489
_checkVtkGrid();
13991490
auto point_coords = m_vtk_grid->GetPoints()->GetData();

arctools/neo/src/neo/Mesh.h

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class Mesh
7979

8080
int maxNbConnectedItems() const {
8181
auto nb_connected_elements = connectivity_value.sizes();
82+
if (nb_connected_elements.size() == 0) {return 0;}
8283
return *std::max_element(nb_connected_elements.begin(), nb_connected_elements.end());
8384
}
8485
};

arctools/neo/src/neo/Properties.h

+1
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ class MeshArrayPropertyT : public PropertyBase
550550
* This method tries to avoid copy via move construct. Work only if a rvalue is passed for \a values argument. Property must be empty.
551551
*/
552552
void init(const ItemRange& item_range, std::vector<DataType> values) {
553+
if (item_range.isEmpty() && values.empty()) return;
553554
assert(("Property must be empty and item range contiguous to call init", isInitializableFrom(item_range)));
554555
assert(("call resize before init", !item_range.isEmpty() && m_data_size != 0));
555556
m_data = std::move(values);

0 commit comments

Comments
 (0)