Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Begin support for post-processing constituents with format VtkHdf #1975

Merged
merged 3 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions arcane/ceapart/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,10 @@ if (ARCANE_HAS_ACCELERATOR_API)
"-We,ARCANE_MATERIAL_NEW_ITEM_INIT,2" "-We,ARCANE_USE_GENERIC_COPY_BETWEEN_PURE_AND_PARTIAL,2")
arcane_add_test_sequential_host_and_accelerator(material_heat4_init3_accelerator "${ARCANE_TEST_PATH}/testMaterialHeat-4-opt15.arc" "-m 20"
"-We,ARCANE_MATERIAL_NEW_ITEM_INIT,3" "-We,ARCANE_ALLENVCELL_FOR_RUNCOMMAND,1")
if(HDF5_FOUND)
arcane_add_test(material_heat2_vtkhdfv2 testMaterialHeat-2-vtkhdfv2.arc)
endif()

endif()

###################
Expand Down
85 changes: 85 additions & 0 deletions arcane/ceapart/tests/testMaterialHeat-2-vtkhdfv2.arc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0"?>
<case codename="ArcaneTest" xml:lang="en" codeversion="1.0">
<arcane>
<title>Test MaterialHeat</title>
<description>Test des Materiaux</description>
<timeloop>MaterialHeatTestLoop</timeloop>
</arcane>

<arcane-post-processing>
<output-period>5</output-period>
<format name="VtkHdfV2PostProcessor" />
<output>
<variable>Temperature</variable>
</output>
</arcane-post-processing>

<meshes>
<mesh>
<generator name="Cartesian2D">
<nb-part-x>2</nb-part-x>
<nb-part-y>2</nb-part-y>
<origin>0.0 0.0</origin>
<x><n>40</n><length>1.2</length><progression>1.0</progression></x>
<y><n>60</n><length>1.5</length><progression>1.0</progression></y>
</generator>
</mesh>
</meshes>

<material-heat-test>
<nb-iteration>15</nb-iteration>
<modification-flags>15</modification-flags>
<check-numerical-result>false</check-numerical-result>
<material>
<name>MAT1</name>
</material>
<material>
<name>MAT2</name>
</material>
<material>
<name>MAT3</name>
</material>

<environment>
<name>ENV1</name>
<material>MAT1</material>
<material>MAT2</material>
</environment>
<environment>
<name>ENV2</name>
<material>MAT2</material>
<material>MAT3</material>
</environment>

<heat-object>
<center>0.3 0.4 0.0</center>
<velocity>0.02 0.04 0.0</velocity>
<radius>0.18</radius>
<material>ENV1_MAT1</material>
<expected-final-temperature>3632937.10322508</expected-final-temperature>
</heat-object>
<heat-object>
<center>0.8 0.4 0.0</center>
<velocity>-0.02 0.04 0.0</velocity>
<radius>0.25</radius>
<material>ENV1_MAT2</material>
<expected-final-temperature>7780818.83419631</expected-final-temperature>
</heat-object>
<heat-object>
<center>0.2 1.2 0.0</center>
<velocity>0.02 -0.05 0.0</velocity>
<radius>0.2</radius>
<material>ENV2_MAT2</material>
<expected-final-temperature>4230364.18968662</expected-final-temperature>
</heat-object>
<heat-object>
<center>0.9 0.9 0.0</center>
<velocity>-0.02 -0.04 0.0</velocity>
<radius>0.15</radius>
<material>ENV2_MAT3</material>
<expected-final-temperature>2259280.64283209</expected-final-temperature>
</heat-object>

</material-heat-test>

</case>
83 changes: 67 additions & 16 deletions arcane/src/arcane/hdf5/VtkHdfV2PostProcessor.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
//-----------------------------------------------------------------------------
// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: Apache-2.0
//-----------------------------------------------------------------------------
/*---------------------------------------------------------------------------*/
/* VtkHdfV2PostProcessor.cc (C) 2000-2024 */
/* VtkHdfV2PostProcessor.cc (C) 2000-2025 */
/* */
/* Pos-traitement au format VTK HDF. */
/*---------------------------------------------------------------------------*/
Expand All @@ -30,6 +30,9 @@
#include "arcane/core/IMesh.h"
#include "arcane/core/internal/VtkCellTypes.h"

#include "arcane/core/materials/IMeshMaterialMng.h"
#include "arcane/core/materials/IMeshEnvironment.h"

#include "arcane/hdf5/Hdf5Utils.h"
#include "arcane/hdf5/VtkHdfV2PostProcessor_axl.h"

Expand Down Expand Up @@ -66,6 +69,7 @@
namespace Arcane
{
using namespace Hdf5Utils;
using namespace Materials;

namespace
{
Expand Down Expand Up @@ -93,6 +97,15 @@ class VtkHdfV2DataWriter
*/
struct DatasetGroupAndName
{
public:

DatasetGroupAndName(HGroup& group_, const String& name_)
: group(group_)
, name(name_)
{}

public:

HGroup& group;
String name;
};
Expand Down Expand Up @@ -215,7 +228,7 @@ class VtkHdfV2DataWriter

public:

VtkHdfV2DataWriter(IMesh* mesh, const ItemGroupCollection& groups, bool use_collective_io);
VtkHdfV2DataWriter(IMesh* mesh, const ItemGroupCollection& groups, bool is_collective_io);

public:

Expand All @@ -232,8 +245,12 @@ class VtkHdfV2DataWriter

private:

//! Maillage associé
IMesh* m_mesh = nullptr;

//! Gestionnaire de matériaux associé (peut-être nul)
IMeshMaterialMng* m_material_mng = nullptr;

//! Liste des groupes à sauver
ItemGroupCollection m_groups;

Expand Down Expand Up @@ -276,6 +293,7 @@ class VtkHdfV2DataWriter

ItemGroupCollectiveInfo m_all_cells_info;
ItemGroupCollectiveInfo m_all_nodes_info;
UniqueArray<Ref<ItemGroupCollectiveInfo>> m_materials_groups;

/*!
* \brief Taille maximale (en kilo-octet) pour une écriture.
Expand Down Expand Up @@ -328,6 +346,7 @@ class VtkHdfV2DataWriter
void _initializeOffsets();
void _initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info);
WritePartInfo _computeWritePartInfo(Int64 local_size);
void _writeConstituentsGroups();
};

/*---------------------------------------------------------------------------*/
Expand All @@ -352,6 +371,9 @@ beginWrite(const VariableCollection& vars)
{
ARCANE_UNUSED(vars);

// Récupère le gestionnaire de matériaux s'il existe
m_material_mng = IMeshMaterialMng::getReference(m_mesh, false);

IParallelMng* pm = m_mesh->parallelMng();
const Int32 nb_rank = pm->commSize();
m_is_parallel = nb_rank > 1;
Expand All @@ -361,7 +383,7 @@ beginWrite(const VariableCollection& vars)
const bool is_first_call = (time_index < 2);
m_is_first_call = is_first_call;
if (is_first_call)
pwarning() << "L'implémentation au format 'VtkHdfV2' est expérimentale";
info() << "WARNING: L'implémentation au format 'VtkHdfV2' est expérimentale";

String filename = _getFileName();

Expand All @@ -372,17 +394,19 @@ beginWrite(const VariableCollection& vars)

HInit();

// Il est possible d'utiliser le mode collectif de HDF5 via MPI-IO dans les cas suivants:
// - Hdf5 a été compilé avec MPI
// - on est en mode MPI pure (ni mode mémoire partagé, ni mode hybride)
// Il est possible d'utiliser le mode collectif de HDF5 via MPI-IO dans les cas suivants :
// * Hdf5 a été compilé avec MPI,
// * on est en mode MPI pure (ni mode mémoire partagé, ni mode hybride).
m_is_collective_io = m_is_collective_io && (pm->isParallel() && HInit::hasParallelHdf5());
if (pm->isHybridImplementation() || pm->isThreadImplementation())
m_is_collective_io = false;

if (is_first_call) {
info() << "VtkHdfV2DataWriter: using collective MPI/IO ?=" << m_is_collective_io;
info() << "VtkHdfV2DataWriter: max_write_size (kB) =" << m_max_write_size;
info() << "VtkHdfV2DataWriter: has_material?=" << (m_material_mng != nullptr);
}

// Vrai si on doit participer aux écritures
// Si on utilise MPI/IO avec HDF5, il faut tout de même que tous
// les rangs fassent toutes les opérations d'écriture pour garantir
Expand Down Expand Up @@ -511,10 +535,10 @@ beginWrite(const VariableCollection& vars)
points[index][2] = pos.z;
}

// Sauve l'uniqueId de chaque noeud dans le dataset "GlobalNodeId".
// Sauve l'uniqueId de chaque nœud dans le dataset "GlobalNodeId".
_writeDataSet1DCollective<Int64>({ { m_node_data_group, "GlobalNodeId" }, m_cell_offset_info }, nodes_uid);

// Sauve les informations sur le type de noeud (réel ou fantôme).
// Sauve les informations sur le type de nœud (réel ou fantôme).
_writeDataSet1DCollective<unsigned char>({ { m_node_data_group, "vtkGhostType" }, m_cell_offset_info }, nodes_ghost_type);

// Sauve les coordonnées des noeuds.
Expand All @@ -529,7 +553,6 @@ beginWrite(const VariableCollection& vars)
_writeDataSet1DCollective<Int64>({ { m_cell_data_group, "GlobalCellId" }, m_cell_offset_info }, cells_uid);

if (m_is_writer) {

// Liste des temps.
Real current_time = m_times[time_index - 1];
_writeDataSet1D<Real>({ { m_steps_group, "Values" }, m_time_offset_info }, asConstSpan(&current_time));
Expand All @@ -541,6 +564,33 @@ beginWrite(const VariableCollection& vars)
// Nombre de temps
_addInt64Attribute(m_steps_group, "NSteps", time_index);
}

_writeConstituentsGroups();
}

/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/

void VtkHdfV2DataWriter::
_writeConstituentsGroups()
{
if (!m_material_mng)
return;

// Remplit les informations des groupes liés aux constituents
// NOTE : Pour l'instant, on ne traite que les milieux.
for (IMeshEnvironment* env : m_material_mng->environments()) {
CellGroup cells = env->cells();
Ref<ItemGroupCollectiveInfo> group_info_ref = createRef<ItemGroupCollectiveInfo>(cells);
m_materials_groups.add(group_info_ref);
ItemGroupCollectiveInfo& group_info = *group_info_ref.get();
_initializeItemGroupCollectiveInfos(group_info);
ConstArrayView<Int32> groups_ids = cells.view().localIds();
DatasetGroupAndName dataset_group_name(m_top_group, String("Constituent_") + cells.name());
if (m_is_first_call)
info() << "Writing infos for group '" << cells.name() << "'";
_writeDataSet1DCollective<Int32>({ dataset_group_name, m_cell_offset_info }, groups_ids);
}
}

/*---------------------------------------------------------------------------*/
Expand Down Expand Up @@ -1140,21 +1190,22 @@ _readAndSetOffset(DatasetInfo& offset_info, Int32 wanted_step)
void VtkHdfV2DataWriter::
_initializeOffsets()
{
// Il y a 5 valeurs d'offset utilisées:
// Il y a 5 valeurs d'offset utilisées :
//
// - offset sur le nombre de mailles (CellOffsets). Cet offset a pour nombre d'éléments
// le nombre de temps sauvés et est augmenté à chaque sortie du nombre de mailles. Cet offset
// est aussi utiliser pour les variables aux mailles
// - offset sur le nombre de noeuds (PointOffsets). Il équivalent à 'CellOffsets' mais
// est aussi utilisé pour les variables aux mailles
// - offset sur le nombre de noeuds (PointOffsets). Il est équivalent à 'CellOffsets' mais
// pour les noeuds.
// - offset pour "NumberOfCells", "NumberOfPoints" et "NumberOfConnectivityIds". Pour chacun
// de ces champs il y a NbPart valeurs par temps, avec 'NbPart' le nombre de parties (donc
// le nombre de sous-domaines si on ne fait pas de regroupement). Il y a donc au total
// le nombre de sous-domaines si on ne fait pas de regroupement). Il y a ainsi au total
// NbPart * NbTimeStep dans ce champ d'offset.
// - offset pour le champ "Connectivity" qui s'appelle "ConnectivityIdOffsets".
// Cet offset a pour nombre d'éléments le nombre de temps sauvés.
// - offset pour le champ "Offsets". "Offset" contient pour chaque maille l'offset dans
// "Connectivity" de la connectivité des noeuds de la maille. Cet offset n'est pas sauvés
// mais comme ce champ à un nombre de valeur égale au nombre de mailles plus 1 il est possible
// "Connectivity" de la connectivité des noeuds de la maille. Cet offset n'est pas sauvés,
// mais comme ce champ à un nombre de valeurs égal au nombre de mailles plus un il est possible
// de le déduire de "CellOffsets" (il vaut "CellOffsets" plus l'index du temps courant).

m_cell_offset_info = DatasetInfo(m_steps_group, "CellOffsets");
Expand Down
Loading