// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. // // --------------------------------------------------------------- // Convert DC: Convert between different types of data collections // --------------------------------------------------------------- // // This tool demonstrates how to convert between MFEM's different concrete // DataCollection options. // // Currently supported data collection type options: // visit: VisItDataCollection (default) // sidre or sidre_hdf5: SidreDataCollection // json: ConduitDataCollection w/ protocol json // conduit_json: ConduitDataCollection w/ protocol conduit_json // conduit_bin: ConduitDataCollection w/ protocol conduit_bin // hdf5: ConduitDataCollection w/ protocol hdf5 // fms: FMSDataCollection w/ protocol ascii // fms_json: FMSDataCollection w/ protocol json // fms_yaml: FMSDataCollection w/ protocol yaml // fms_hdf5: FMSDataCollection w/ protocol hdf5 // // Compile with: make convert-dc // // Serial sample runs: // convert-dc -s ../../examples/Example5 -st visit -o Example5_Conduit -ot json // // Parallel sample runs: // mpirun -np 4 convert-dc -s ../../examples/Example5-Parallel -st visit // -o Example5-Parallel_Conduit -ot json #include "mfem.hpp" using namespace std; using namespace mfem; DataCollection *create_data_collection(const std::string &dc_name, const std::string &dc_type) { DataCollection *dc = NULL; if (dc_type == "visit") { #ifdef MFEM_USE_MPI dc = new VisItDataCollection(MPI_COMM_WORLD, dc_name); #else dc = new VisItDataCollection(dc_name); #endif } else if ( dc_type == "sidre" || dc_type == "sidre_hdf5") { #ifdef MFEM_USE_SIDRE dc = new SidreDataCollection(dc_name); #else MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for sidre support."); #endif } else if ( dc_type == "json" || dc_type == "conduit_json" || dc_type == "conduit_bin" || dc_type == "hdf5") { #ifdef MFEM_USE_CONDUIT #ifdef MFEM_USE_MPI ConduitDataCollection *conduit_dc = new ConduitDataCollection(MPI_COMM_WORLD, dc_name); #else ConduitDataCollection *conduit_dc = new ConduitDataCollection(dc_name); #endif conduit_dc->SetProtocol(dc_type); dc = conduit_dc; #else MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for conduit support."); #endif } else if ( dc_type.substr(0,3) == "fms") { #ifdef MFEM_USE_FMS auto fms_dc = new FMSDataCollection(dc_name); std::string::size_type pos = dc_type.find("_"); if (pos != std::string::npos) { std::string fms_protocol(dc_type.substr(pos+1, dc_type.size()-pos-1)); fms_dc->SetProtocol(fms_protocol); } dc = fms_dc; #else MFEM_ABORT("Must build with MFEM_USE_FMS=YES for FMS support."); #endif } else { MFEM_ABORT("Unsupported Data Collection type:" << dc_type); } return dc; } int main(int argc, char *argv[]) { #ifdef MFEM_USE_MPI Mpi::Init(); if (!Mpi::Root()) { mfem::out.Disable(); mfem::err.Disable(); } Hypre::Init(); #endif // Parse command-line options. const char *src_coll_name = NULL; const char *src_coll_type = "visit"; int src_cycle = 0; int src_pad_digits_cycle = 6; int src_pad_digits_rank = 6; const char *out_coll_name = NULL; const char *out_coll_type = "visit"; int out_pad_digits_cycle = -1; int out_pad_digits_rank = -1; OptionsParser args(argc, argv); args.AddOption(&src_coll_name, "-s", "--source-root-prefix", "Set the source data collection root file prefix.", true); args.AddOption(&out_coll_name, "-o", "--output-root-prefix", "Set the source data collection root file prefix.", true); args.AddOption(&src_cycle, "-c", "--cycle", "Set the source cycle index to read."); args.AddOption(&src_pad_digits_cycle, "-pdc", "--pad-digits-cycle", "Number of digits in source cycle."); args.AddOption(&out_pad_digits_cycle, "-opdc", "--out-pad-digits-cycle", "Number of digits in output cycle."); args.AddOption(&src_pad_digits_rank, "-pdr", "--pad-digits-rank", "Number of digits in source MPI rank."); args.AddOption(&out_pad_digits_rank, "-opdr", "--out-pad-digits-rank", "Number of digits in output MPI rank."); args.AddOption(&src_coll_type, "-st", "--source-type", "Set the source data collection type. Options:\n" "\t visit: VisItDataCollection (default)\n" "\t sidre or sidre_hdf5: SidreDataCollection\n" "\t json: ConduitDataCollection w/ protocol json\n" "\t conduit_json: ConduitDataCollection w/ protocol conduit_json\n" "\t conduit_bin: ConduitDataCollection w/ protocol conduit_bin\n" "\t hdf5: ConduitDataCollection w/ protocol hdf5\n" "\t fms: FMSDataCollection w/ protocol ascii\n" "\t fms_json: FMSDataCollection w/ protocol json\n" "\t fms_yaml: FMSDataCollection w/ protocol yaml\n" "\t fms_hdf5: FMSDataCollection w/ protocol hdf5"); args.AddOption(&out_coll_type, "-ot", "--output-type", "Set the output data collection type. Options:\n" "\t visit: VisItDataCollection (default)\n" "\t sidre or sidre_hdf5: SidreDataCollection\n" "\t json: ConduitDataCollection w/ protocol json\n" "\t conduit_json: ConduitDataCollection w/ protocol conduit_json\n" "\t conduit_bin: ConduitDataCollection w/ protocol conduit_bin\n" "\t hdf5: ConduitDataCollection w/ protocol hdf5\n" "\t fms: FMSDataCollection w/ protocol ascii\n" "\t fms_json: FMSDataCollection w/ protocol json\n" "\t fms_yaml: FMSDataCollection w/ protocol yaml\n" "\t fms_hdf5: FMSDataCollection w/ protocol hdf5"); args.Parse(); if (!args.Good()) { args.PrintUsage(mfem::out); return 1; } if (out_pad_digits_cycle < 0) { out_pad_digits_cycle = src_pad_digits_cycle; } if (out_pad_digits_rank < 0) { out_pad_digits_rank = src_pad_digits_rank; } args.PrintOptions(mfem::out); DataCollection *src_dc = create_data_collection(std::string(src_coll_name), std::string(src_coll_type)); DataCollection *out_dc = create_data_collection(std::string(out_coll_name), std::string(out_coll_type)); out_dc->SetPadDigitsCycle(out_pad_digits_cycle); out_dc->SetPadDigitsRank(out_pad_digits_rank); src_dc->SetPadDigitsCycle(src_pad_digits_cycle); src_dc->SetPadDigitsRank(src_pad_digits_rank); src_dc->Load(src_cycle); if (src_dc->Error() != DataCollection::No_Error) { mfem::out << "Error loading data collection: " << src_coll_name << " (type = " << src_coll_type << ")" << endl; return 1; } out_dc->SetOwnData(false); // add mesh from source dc to output dc #ifdef MFEM_USE_MPI out_dc->SetMesh(MPI_COMM_WORLD,src_dc->GetMesh()); #else out_dc->SetMesh(src_dc->GetMesh()); #endif // propagate the basics out_dc->SetCycle(src_dc->GetCycle()); out_dc->SetTime(src_dc->GetTime()); out_dc->SetTimeStep(src_dc->GetTimeStep()); // loop over all fields in the source dc, and add them to the output dc const DataCollection::FieldMapType &src_fields = src_dc->GetFieldMap(); for (DataCollection::FieldMapType::const_iterator it = src_fields.begin(); it != src_fields.end(); ++it) { out_dc->RegisterField(it->first,it->second); } out_dc->Save(); if (out_dc->Error() != DataCollection::No_Error) { mfem::out << "Error saving data collection: " << out_coll_name << " (type = " << out_coll_type << ")" << endl; return 1; } // cleanup delete src_dc; delete out_dc; return 0; }