diff --git a/CHANGELOG.md b/CHANGELOG.md index e8cbc8176..b5a6811cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project aspires to adhere to [Semantic Versioning](https://semver.org/s - vtk-m@2.1.0 ### Added +- Added `refinement_level` option to Relay Extract. When used this will refine high order meshes to a low order representation and save the low order result as the extract data. - Added parameters to control HDF5 compression options to the Relay Extract. - Added check to make sure all domain IDs are unique - Added a `vtk` extract that saves each mesh domain to a legacy vtk file grouped, with all domain data grouped by a `.visit` file. diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp index 59e0a34ce..37ca18b8d 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_relay_filters.cpp @@ -41,6 +41,7 @@ #include #include #include +#include "ascent_transmogrifier.hpp" #include #include @@ -336,6 +337,19 @@ verify_io_params(const conduit::Node ¶ms, info["info"].append() = "includes 'num_files'"; } } + + if( params.has_child("refinement_level") ) + { + if(!params["refinement_level"].dtype().is_integer()) + { + info["errors"].append() = "optional entry 'refinement_level' must be an integer"; + res = false; + } + else + { + info["info"].append() = "includes 'refinement_level'"; + } + } #if defined(ASCENT_HDF5_ENABLED) if( params.has_child("hdf5_options") ) @@ -415,6 +429,7 @@ verify_io_params(const conduit::Node ¶ms, valid_paths.push_back("protocol"); valid_paths.push_back("fields"); valid_paths.push_back("num_files"); + valid_paths.push_back("refinement_level"); ignore_paths.push_back("fields"); #if defined(ASCENT_HDF5_ENABLED) ignore_paths.push_back("hdf5_options"); @@ -550,12 +565,46 @@ RelayIOSave::execute() ASCENT_ERROR("relay_io_save requires a DataObject input"); } + // check if user requested lor for export + int lor_level = -1; + if(params().has_child("refinement_level")) + { + lor_level = params()["refinement_level"].to_int(); + } + DataObject *data_object = input("in"); if(!data_object->is_valid()) { return; } - std::shared_ptr n_input = data_object->as_node(); + + std::shared_ptr n_input; + int tmogr_ref_level = Transmogrifier::m_refinement_level; + // check if user requested lor for export + if(lor_level >0) + { + // check if extract params are the same as global lor setting + if(lor_level != tmogr_ref_level) + { + // not the same, preserve global setting + //push + Transmogrifier::m_refinement_level = lor_level; + } + + n_input = data_object->as_low_order_bp(); + + if(lor_level != Transmogrifier::m_refinement_level) + { + // not the same, restore global setting + // pop + Transmogrifier::m_refinement_level = tmogr_ref_level; + } + + } + else + { + n_input = data_object->as_node(); + } Node *in = n_input.get(); @@ -638,7 +687,9 @@ RelayIOSave::execute() result_path = path; } #if defined(ASCENT_HDF5_ENABLED) - else if( protocol == "blueprint/mesh/hdf5" || protocol == "hdf5") + else if( protocol == "blueprint" || + protocol == "blueprint/mesh/hdf5" || + protocol == "hdf5") { mesh_blueprint_save(selected, path, @@ -648,21 +699,23 @@ RelayIOSave::execute() result_path); } #endif - else if( protocol == "blueprint/mesh/json" || protocol == "json") + else if( protocol == "blueprint" || + protocol == "blueprint/mesh/yaml" || + protocol == "yaml") { mesh_blueprint_save(selected, path, - "json", + "yaml", num_files, extra_opts, result_path); } - else if( protocol == "blueprint/mesh/yaml" || protocol == "yaml") + else if( protocol == "blueprint/mesh/json" || protocol == "json") { mesh_blueprint_save(selected, path, - "yaml", + "json", num_files, extra_opts, result_path); diff --git a/src/tests/ascent/t_ascent_relay.cpp b/src/tests/ascent/t_ascent_relay.cpp index 4113bbaec..f20302589 100644 --- a/src/tests/ascent/t_ascent_relay.cpp +++ b/src/tests/ascent/t_ascent_relay.cpp @@ -178,7 +178,7 @@ TEST(ascent_relay, test_relay_hdf5_opts) data); EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - // change values -- zeros compress nicely .... + // change values -- zeros compress nicely .... float64_array vals = data["fields/field/values"].value(); vals.fill(0); index_t nele = vals.number_of_elements(); @@ -988,6 +988,88 @@ TEST(ascent_relay, test_relay_sparse_topos) } + +//----------------------------------------------------------------------------- +TEST(ascent_relay, test_relay_lor_extract) +{ + Node n; + ascent::about(n); + + if(n["runtimes/ascent/mfem/status"].as_string() == "disabled") + { + std::cout << "mfem disabled: skipping test that requires mfem for lor" << std::endl; + return; + } + + // + // load example mesh + // + Node data,verify_info; + conduit::relay::io::blueprint::read_mesh(test_data_file("taylor_green.cycle_001860.root"), + data); + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + // create extract as published (no lor) + string output_path = prepare_output_dir(); + string output_file = conduit::utils::join_file_path(output_path,"tout_relay_ho_no_lor"); + + conduit::Node actions; + // add the extracts + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + Node &extracts = add_extracts["extracts"]; + + extracts["e1/type"] = "relay"; + + extracts["e1/params/path"] = output_file; + extracts["e1/params/protocol"] = "blueprint"; + + std::cout << actions.to_yaml() << std::endl; + + // + // Run Ascent + // + Ascent ascent; + ascent.open(); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + // check that we created an extract file + EXPECT_TRUE(conduit::utils::is_file(output_file + ".cycle_001860.root")); + + output_file = conduit::utils::join_file_path(output_path,"tout_relay_ho_lor_5"); + + // LOR and save as create extract + conduit::Node actions2; + // add the extracts + conduit::Node &add_extracts2 = actions2.append(); + add_extracts2["action"] = "add_extracts"; + Node &extracts2 = add_extracts2["extracts"]; + + extracts2["e1/type"] = "relay"; + + extracts2["e1/params/path"] = output_file; + extracts2["e1/params/refinement_level"] = 5; + extracts2["e1/params/protocol"] = "blueprint"; + + std::cout << actions2.to_yaml() << std::endl; + + // + // Run Ascent + // + Ascent ascent2; + ascent2.open(); + ascent2.publish(data); + ascent2.execute(actions2); + ascent2.close(); + // check that we created an extract file + EXPECT_TRUE(conduit::utils::is_file(output_file + ".cycle_001860.root")); + std::string msg = "An example of creating a relay extract " + "with low order refined data."; + ASCENT_ACTIONS_DUMP(actions2,output_file,msg); +} + + //----------------------------------------------------------------------------- int main(int argc, char* argv[]) {