Skip to content

Add OpenPMD support - #1050

Merged
pgrete merged 217 commits into
developfrom
pgrete/pmd-output
Jun 12, 2026
Merged

Add OpenPMD support#1050
pgrete merged 217 commits into
developfrom
pgrete/pmd-output

Conversation

@pgrete

@pgrete pgrete commented Apr 12, 2024

Copy link
Copy Markdown
Collaborator

PR Summary

Leftover todos (potentially for future PRs):

  • cleaner integration in build system
  • add logic for selection of var (rather than all)
  • double check additional logic for restart outputs (like UserWorkBeforeRestart)
  • Add doc
  • Add callback to provide/forward standard compatible downstream code info
  • Add pattern file for Visit/Paraview
  • Add support for slices

For upcoming PRs:

  • Adjust python script to read opmd output (or is this not needed because of the existing openpmd-viewer)?
  • Add support for units
  • Add support for Metadata::None
  • Add support for Metadata::Fine
  • Add support for Metadata::CoordinatesVec

PR Checklist

  • Code passes cpplint
  • New features are documented.
  • Adds a test for any bugs fixed. Adds tests for new features.
  • Code is formatted
  • Changes are summarized in CHANGELOG.md
  • Change is breaking (API, behavior, ...)
    • Change is additionally added to CHANGELOG.md in the breaking section
    • PR is marked as breaking
    • Short summary API changes at the top of the PR (plus optionally with an automated update/fix script)
  • CI has been triggered on Darwin for performance regression tests.
  • Docs build
  • (@lanl.gov employees) Update copyright on changed files

Comment thread src/outputs/openpmd.cpp Outdated
Comment thread src/outputs/restart_opmd.cpp Outdated
@BenWibking

Copy link
Copy Markdown
Collaborator

The only issue I discovered during manual testing is that the time metadata field seems to be missing from the outputs. Is that written?

Time is not stored in a separate attribute but in the "standard" field (iteration.time)

ts = OpenPMDTimeSeries('/path/to/out/dir')

ts.iterations

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

ts.t


ts.t

array([0.        , 0.10168297, 0.20282794, 0.3000894 , 0.40210582,
       0.50107859, 0.60178476, 0.70180927, 0.80225403, 0.90006754,
       1.00190689, 1.10025895, 1.20133299, 1.30205319, 1.4007721 ,
       1.50098825, 1.60000468, 1.70110938, 1.80133319, 1.90043797,
       2.00050956, 2.10170538, 2.20182487, 2.30114008, 2.40104512,
       2.50118173, 2.60176224, 2.70163334, 2.8007994 , 2.90145011])

Ah, ok. I wasn't reading this correctly in my VisIt plugin. Fixed now, thanks.

@BenWibking BenWibking left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works in my production runs. Throughly audited with Codex. Did not attempt to manually read each line.

@pgrete

pgrete commented May 18, 2026

Copy link
Copy Markdown
Collaborator Author

ping @Yurlungur for review.

@Yurlungur

Copy link
Copy Markdown
Collaborator

ping @Yurlungur for review.

Sorry I know I'm the blocker here... I'm out sick currently. Will review ASAP

@Yurlungur Yurlungur left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long time coming, and pretty clean in the end. Glad to see you got to reuse some of the utilities from HDF5. Sorry for the long delay in review. I have some comments but I don't consider any of them blocking.

Comment thread CMakeLists.txt
Comment thread CMakeLists.txt Outdated
Comment thread doc/sphinx/src/outputs.rst
Comment thread src/outputs/output_attr.hpp Outdated
Comment thread tst/regression/test_suites/restart_opmd/parthinput.restart Outdated
Comment thread src/outputs/parthenon_opmd.cpp
Comment thread src/outputs/parthenon_opmd.cpp Outdated
Comment on lines +111 to +112
// Current unclear how to properly handle other vectors and tensors, so everything
// that not's a proper vector is a a scalar for now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pgrete what's the status of this? How does this work right now for, e.g., a tensor field?

Comment thread src/outputs/parthenon_opmd.cpp Outdated
Comment thread src/outputs/parthenon_opmd.cpp
Comment thread src/outputs/parthenon_opmd.cpp

@lroberts36 lroberts36 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! I am glad to see this done. Just a few small non-blocking comments.

Comment thread doc/sphinx/src/outputs.rst Outdated
Comment thread doc/sphinx/src/outputs.rst Outdated
Comment thread doc/sphinx/src/outputs.rst Outdated
Comment thread doc/sphinx/src/outputs.rst Outdated
Comment thread doc/sphinx/src/outputs.rst Outdated
Comment on lines +415 to +416
// TODO(?) in principle, we could abstract this to a more general WriteAttributes place
// and reuse for hdf5 and OpenPMD output with corresponing calls

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be great (WriteOutputFile is pretty big for both OpenPMD and HDF5), but certainly not critical for this PR.

//----------------------------------------------------------------------------------------
//! \fn void OpenPMDOutput:::WriteOutputFile(Mesh *pm)
// \brief Write output in OpenPMD format
template <bool WRITE_SINGLE_PRECISION>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just template on the type itself (i.e. template <class OutT>)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow.

Comment thread src/outputs/parthenon_opmd.hpp Outdated
Comment on lines +71 to +86
RestartReaderOPMD::SparseInfo RestartReaderOPMD::GetSparseInfo() const {
SparseInfo info;
// Only read if data exists. Otherwise return default constructed.
if (it->containsAttribute("SparseInfo")) {
auto sinfo_vec = it->getAttribute("SparseInfo").get<std::vector<int8_t>>();
info.labels = it->getAttribute("SparseFields").get<std::vector<std::string>>();
info.num_sparse = static_cast<int>(info.labels.size());
info.num_blocks = sinfo_vec.size() / info.num_sparse;
info.dealloc_count = it->getAttribute("SparseDeallocCount").get<std::vector<int>>();

// copy "vector" data to bool pointer for compatiblity between output backends
info.allocated.reset(new bool[sinfo_vec.size()]);
for (int i = 0; i < sinfo_vec.size(); i++) {
info.allocated[i] = sinfo_vec.at(i);
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what the solution is, but it concerns me a little that we basically have to mirror all of the parameter reading for HDF5 and OpenPMD exactly to ensure exact restart behavior.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the solution would be (along the lines of "simplify"/write common WriteOutputFile) to have an abstraction to write arbitrary attributes so that a restart output would just call WriteAttribute that under the hoods then calls the backend specific implementation.

Comment on lines +177 to +191
if (PARTHENON_ENABLE_OPENPMD)

# h5py is also needed for the current test
list(APPEND REQUIRED_PYTHON_MODULES openpmd_api h5py)

# Restart
list(APPEND TEST_DIRS restart_opmd)
list(APPEND TEST_PROCS ${NUM_MPI_PROC_TESTING})
list(APPEND TEST_ARGS "--driver ${PROJECT_BINARY_DIR}/example/advection/advection-example \
--driver_input ${CMAKE_CURRENT_SOURCE_DIR}/test_suites/restart_opmd/parthinput.restart \
--num_steps 3")
list(APPEND EXTRA_TEST_LABELS "")

endif()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this just be part of the restart test? I think just adding OpenPMD restart output and restarting from both OpenPMD and HDF5 would test the same things and maybe run a little quicker. (I assume this new test takes as long as the current restart test).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle yes, but until OpenPMD is on by default (and more broadly used) I think it makes sense to keep this separate because the logic is simpler in two separate tests than having a configure dependent number of steps and test logic for one (large) test.

@pgrete
pgrete enabled auto-merge (squash) June 10, 2026 19:57
@pgrete
pgrete disabled auto-merge June 10, 2026 19:57
@pgrete

pgrete commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Are people happy with the latest changes? I think we'd be good to go then.

@Yurlungur

Copy link
Copy Markdown
Collaborator

Ship it.

@pgrete
pgrete enabled auto-merge (squash) June 12, 2026 06:29
@pgrete
pgrete disabled auto-merge June 12, 2026 14:30
@pgrete
pgrete enabled auto-merge (squash) June 12, 2026 14:30
@pgrete
pgrete merged commit a686f87 into develop Jun 12, 2026
38 checks passed
@pgrete
pgrete deleted the pgrete/pmd-output branch June 12, 2026 18:48
@pgrete pgrete linked an issue Jul 9, 2026 that may be closed by this pull request
@pgrete pgrete mentioned this pull request Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ADIOS I/O

5 participants