Skip to content

Commit 98556ae

Browse files
Xdmf io in Idefix (#13)
* [ENH] Added `HighFive` hdf5 io submodule * [ENH] Added `Xdmf` IO feature * [RFC] Removed redundant prints * [DOC] Updated documentation describing `xdmf` dumps * [RFC] Native `HDF5` dump feature * [FIX] Fixed datatype of `vect3D` to match dump datatype * [ENH] Added more info to attributes in hdf5 file * [FIX] Fixed missing hyperslab select in serial io * [FIX] Fixed output for all dimensions * [ADD] Added a 3D test problem with unequal extent * [FIX] Made `hdf5` includes optional * [FIX] Optional `hdf5` include * [FIX] More optional `hdf5` fixes * [FIX] Linter fixes * [FIX] Fixed hdf5 optional include pre-processor flags * [FIX] Fixed hdf5 optional include pre-processor flags * Used `IDEFIX_ERROR` macro for missing hdf5 linking * [RFC] Incorporated changes suggested by @glesur
1 parent aa2224e commit 98556ae

File tree

13 files changed

+1180
-12
lines changed

13 files changed

+1180
-12
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Makefile.local
2525
# test artifacts
2626
test/**/*.o
2727
test/**/*.vtk
28+
test/**/*.h5
29+
test/**/*.xmf
2830
test/**/*.dmp
2931
test/**/*.idfx
3032
test/**/*.tmp

CMakeLists.txt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ if(Idefix_MPI)
8282
target_link_libraries(idefix MPI::MPI_CXX)
8383
endif()
8484

85+
if(Idefix_HDF5)
86+
add_compile_definitions("WITH_HDF5")
87+
if(Idefix_MPI)
88+
set(HDF5_PREFER_PARALLEL TRUE)
89+
endif()
90+
find_package(HDF5 REQUIRED)
91+
target_link_libraries(idefix "${HDF5_LIBRARIES}")
92+
target_include_directories(idefix PUBLIC "${HDF5_INCLUDE_DIRS}")
93+
message(STATUS "XDMF (hdf5+xmf) dumps enabled")
94+
else()
95+
set(Idefix_HDF5 OFF)
96+
endif()
97+
8598
if(Idefix_DEBUG)
8699
add_compile_definitions("DEBUG")
87100
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g")
@@ -166,11 +179,12 @@ target_link_libraries(idefix Kokkos::kokkos)
166179

167180
message(STATUS "Idefix final configuration")
168181
if(Idefix_EVOLVE_VECTOR_POTENTIAL)
169-
message(STATUS " MHD: ${Idefix_MHD} (Vector potential)")
182+
message(STATUS " MHD: ${Idefix_MHD} (Vector potential)")
170183
else()
171-
message(STATUS " MHD: ${Idefix_MHD}")
184+
message(STATUS " MHD: ${Idefix_MHD}")
172185
endif()
173-
message(STATUS " MPI: ${Idefix_MPI}")
186+
message(STATUS " MPI: ${Idefix_MPI}")
187+
message(STATUS " HDF5: ${Idefix_HDF5}")
174188
message(STATUS " Reconstruction: ${Idefix_RECONSTRUCTION}")
175189
message(STATUS " Precision: ${Idefix_PRECISION}")
176190
message(STATUS " Version: ${GIT_SHA1}")

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ cmake $IDEFIX_DIR
5757

5858
Several options can be enabled from the command line (a complete list is available with `cmake $IDEFIX_DIR -LH`). For instance: `-DIdefix_RECONSTRUCTION=Parabolic` (enable PPM reconstruction), `-DIdefix_MPI=ON` (enable mpi), `-DKokkos_ENABLE_OPENMP=ON` (enable openmp parallelisation), etc... For more complex target architectures, it is recommended to use cmake GUI launching `ccmake $IDEFIX_DIR` in place of `cmake` and then switching on the required options.
5959

60+
Optional xdmf(hdf5+xmf) file dumping feature has been added to `Idefix`. This uses either serial or parallel implementation of `hdf5` library which needs to be made available. These xdmf file pairs can be easily visualized in `ParaView` or `VisIt` by loading the `xmf` files. The `hdf5` files can also be loaded easily in `python` (using `h5py`) for post-processing and post-run analysis. One can turn on `xdmf` data dumps by using `-DIdefix_HDF5=ON`. The `[Output]` block of `.ini` file is checked during runtime for a `xdmf` entry whih controls the frequency of xdmf file dumps during code execution.
61+
<!-- TODO: HDF5 Chunking and Compression filters -->
62+
6063
One can then compile the code:
6164

6265
```shell

src/output/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ target_sources(idefix
66
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/vtk.cpp
77
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/vtk.hpp
88
)
9+
if(Idefix_HDF5)
10+
target_sources(idefix
11+
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/xdmf.cpp
12+
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/xdmf.hpp
13+
)
14+
endif()

src/output/output.cpp

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#include "output.hpp"
99

10-
1110
Output::Output(Input &input, DataBlock &data) {
1211
idfx::pushRegion("Output::Output");
1312
// initialise the output objects for each format
@@ -25,6 +24,23 @@ Output::Output(Input &input, DataBlock &data) {
2524
}
2625
vtk.Init(input,data); // Always initialised in case of emergency vtk output
2726

27+
// Initialise xdmf outputs
28+
if(input.CheckEntry("Output","xdmf")>0) {
29+
xdmfPeriod = input.Get<real>("Output","xdmf",0);
30+
if(xdmfPeriod>=0.0) { // backward compatibility (negative value means no file)
31+
xdmfLast = data.t - xdmfPeriod; // write something in the next CheckForWrite()
32+
#ifdef WITH_HDF5
33+
xdmfEnabled = true;
34+
#else
35+
xdmfEnabled = false;
36+
IDEFIX_ERROR("Attention: HDF5 library not linked when building Idefix!");
37+
#endif
38+
}
39+
}
40+
#ifdef WITH_HDF5
41+
xdmf.Init(input,data); // Always initialised in case of emergency xdmf output
42+
#endif
43+
2844
// intialise dump outputs
2945
if(input.CheckEntry("Output","dmp")>0) {
3046
dumpPeriod = input.Get<real>("Output","dmp",0);
@@ -116,6 +132,37 @@ int Output::CheckForWrites(DataBlock &data) {
116132
}
117133
}
118134
}
135+
#ifdef WITH_HDF5
136+
// Do we need a XDMF output?
137+
if(xdmfEnabled) {
138+
if(data.t >= xdmfLast + xdmfPeriod) {
139+
elapsedTime -= timer.seconds();
140+
if(userDefVariablesEnabled) {
141+
if(haveUserDefVariablesFunc) {
142+
// Call user-def function to fill the userdefined variable arrays
143+
idfx::pushRegion("UserDef::User-defined variables function");
144+
userDefVariablesFunc(data, userDefVariables);
145+
idfx::popRegion();
146+
} else {
147+
IDEFIX_ERROR("Cannot output user-defined variables without "
148+
"enrollment of your user-defined variables function");
149+
}
150+
}
151+
xdmfLast += xdmfPeriod;
152+
xdmf.Write(data, *this);
153+
nfiles++;
154+
elapsedTime += timer.seconds();
155+
156+
// Check if our next predicted output should already have happened
157+
if((xdmfLast+xdmfPeriod <= data.t) && xdmfPeriod>0.0) {
158+
// Move forward xdmfLast
159+
while(xdmfLast <= data.t - xdmfPeriod) {
160+
xdmfLast += xdmfPeriod;
161+
}
162+
}
163+
}
164+
}
165+
#endif
119166

120167
// Do we need an analysis ?
121168
if(analysisEnabled) {
@@ -184,6 +231,29 @@ void Output::ForceWriteVtk(DataBlock &data) {
184231
idfx::popRegion();
185232
}
186233

234+
#ifdef WITH_HDF5
235+
void Output::ForceWriteXdmf(DataBlock &data) {
236+
idfx::pushRegion("Output::ForceWriteXdmf");
237+
238+
if(!forceNoWrite) {
239+
if(userDefVariablesEnabled) {
240+
if(haveUserDefVariablesFunc) {
241+
// Call user-def function to fill the userdefined variable arrays
242+
idfx::pushRegion("UserDef::User-defined variables function");
243+
userDefVariablesFunc(data, userDefVariables);
244+
idfx::popRegion();
245+
} else {
246+
IDEFIX_ERROR("Cannot output user-defined variables without "
247+
"enrollment of your user-defined variables function");
248+
}
249+
}
250+
xdmfLast += xdmfPeriod;
251+
xdmf.Write(data, *this);
252+
}
253+
idfx::popRegion();
254+
}
255+
#endif
256+
187257
void Output::EnrollAnalysis(AnalysisFunc myFunc) {
188258
idfx::pushRegion("Output::EnrollAnalysis");
189259
if(!analysisEnabled) {

src/output/output.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#include "input.hpp"
1414
#include "dataBlock.hpp"
1515
#include "vtk.hpp"
16+
#ifdef WITH_HDF5
17+
#include "xdmf.hpp"
18+
#endif
1619
#include "dump.hpp"
1720

1821

@@ -25,13 +28,19 @@ using UserDefVariablesFunc = void (*) (DataBlock &, UserDefVariablesContainer &)
2528
class Output {
2629
friend class Dump; // Allow dump to have R/W access to private variables
2730
friend class Vtk; // Allow VTK to have access to user-defined variables
31+
#ifdef WITH_HDF5
32+
friend class Xdmf; // Allow XDMF to have access to user-defined variables
33+
#endif
2834
friend class DumpImage; // Allow dumpimag to have access to dump API
2935
public:
3036
Output(Input &, DataBlock &); // Create Output Object
3137
int CheckForWrites(DataBlock &); // Check if outputs are needed at this stage
3238
void RestartFromDump(DataBlock &, int); // Restart from a dump file.
3339
void ForceWriteDump(DataBlock &); // Force write dumps (needed during an abort)
3440
void ForceWriteVtk(DataBlock &); // Force write vtks
41+
#ifdef WITH_HDF5
42+
void ForceWriteXdmf(DataBlock &); // Force write xdmfs
43+
#endif
3544
void ResetTimer(); // Reset internal timer
3645
double GetTimer();
3746
void EnrollAnalysis(AnalysisFunc);
@@ -40,7 +49,9 @@ class Output {
4049
private:
4150
Vtk vtk; // local instance of Vtk class
4251
Dump dump; // local instance of Dump class
43-
52+
#ifdef WITH_HDF5
53+
Xdmf xdmf; // local instance of Xdmf class
54+
#endif
4455
bool forceNoWrite = false; //< explicitely disable all writes
4556
bool vtkEnabled = false;
4657
real vtkPeriod = 0.0; // periodicity of vtk outputs
@@ -50,6 +61,10 @@ class Output {
5061
real dumpPeriod = 0.0;
5162
real dumpLast = 0.0;
5263

64+
bool xdmfEnabled = false;
65+
real xdmfPeriod = 0.0; // periodicity of xdmf outputs
66+
real xdmfLast = 0.0;
67+
5368
bool analysisEnabled = false;
5469
real analysisPeriod = 0.0;
5570
real analysisLast = 0.0;
@@ -65,6 +80,4 @@ class Output {
6580
Kokkos::Timer timer;
6681
double elapsedTime{0.0};
6782
};
68-
69-
7083
#endif // OUTPUT_OUTPUT_HPP_

src/output/vtk.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#endif
2727
#endif
2828

29-
// Whether of not we write the time in the VTK file
29+
// Whether or not we write the time in the VTK file
3030
#define WRITE_TIME
3131

3232
void Vtk::WriteHeaderString(const char* header, IdfxFileHandler fvtk) {
@@ -216,7 +216,7 @@ void Vtk::Init(Input &input, DataBlock &datain) {
216216

217217
#endif
218218

219-
// Creat MPI view when using MPI I/O
219+
// Create MPI view when using MPI I/O
220220
#ifdef WITH_MPI
221221
int start[3];
222222
int size[3];
@@ -346,7 +346,7 @@ void Vtk::WriteHeader(IdfxFileHandler fvtk, real time) {
346346
* Write VTK header in parallel or serial mode.
347347
*
348348
* \param [in] fvtk pointer to file
349-
* \param [in] grid pointer to an array of Grid structures
349+
* \param [in] time time of the simulation in code units
350350
*
351351
* \todo Write the grid using several processors.
352352
*********************************************************************** */

0 commit comments

Comments
 (0)