From a6ad47ff2ea33b2895cd6420c8d4b0a3a8970df8 Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Mon, 28 Oct 2024 22:02:01 +0000 Subject: [PATCH 01/17] mpi test, better params check --- .../ascent_runtime_blueprint_filters.cpp | 64 ++++++- src/tests/ascent/t_ascent_mpi_partition.cpp | 162 ++++-------------- 2 files changed, 97 insertions(+), 129 deletions(-) diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 20393b137..4ae3db5f8 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -319,18 +319,42 @@ BlueprintPartition::verify_params(const conduit::Node ¶ms, info.reset(); bool res = true; - if(! params.has_child("target") || - ! params["target"].dtype().is_int() ) + res &= check_numeric("target",params, info, false, false); + + if(params.has_child("selections")) { - info["errors"].append() = "Missing required int parameter 'target'"; + res &= check_string("selections/type",params, info, true); + //domain_id can be int or "any" + res &= (check_string("selections/domain_id",params, info, false) || check_numeric("selections/domain_id", params, info, false, false)); + res &= check_string("selections/topology",params, info, false); } + if(params.has_child("fields")) + { + if(!params["fields"].dtype().is_list()) + { + res = false; + info["errors"].append() = "fields is not a list"; + } + } + + res &= check_numeric("mapping",params, info, false, false); + res &= check_numeric("merge_tolerance",params, info, false, false); + res &= check_numeric("build_adjsets",params, info, false, false); + res &= check_string("original_element_ids",params, info, false); + res &= check_string("original_vertex_ids",params, info, false); + std::vector valid_paths; valid_paths.push_back("target"); - valid_paths.push_back("selections"); + valid_paths.push_back("selections/type"); + valid_paths.push_back("selections/domain_id"); + valid_paths.push_back("selections/topology"); valid_paths.push_back("fields"); valid_paths.push_back("mapping"); valid_paths.push_back("merge_tolerance"); + valid_paths.push_back("build_adjsets"); + valid_paths.push_back("original_element_ids"); + valid_paths.push_back("original_vertex_ids"); valid_paths.push_back("distributed"); std::string surprises = surprise_check(valid_paths, params); @@ -361,6 +385,35 @@ BlueprintPartition::execute() conduit::Node n_options = params(); + if(params().has_child("target")) + { + n_options["target"] = params()["target"].to_int32(); + } + if(params().has_child("mapping")) + { + n_options["mapping"] = params()["mapping"].to_int32(); + } + if(params().has_child("merge_tolerance")) + { + n_options["merge_tolerance"] = params()["merge_tolerance"].to_float64(); + } + if(params().has_child("original_element_ids")) + { + n_options["original_element_ids"] = params()["original_element_ids"].to_string(); + } + if(params().has_child("original_vertex_ids")) + { + n_options["original_vertex_ids"] = params()["original_vertex_ids"].to_string(); + } + if(params().has_child("selections")) + { + conduit::Node &selections = params()["selections"]; + n_options.append() = selections; + } + std::cerr << "PRINT OPTIONS: " << std::endl; + n_options.print(); + + #ifdef ASCENT_MPI_ENABLED MPI_Comm mpi_comm = MPI_Comm_f2c(flow::Workspace::default_mpi_comm()); if(params().has_child("distributed") && @@ -372,6 +425,9 @@ BlueprintPartition::execute() } else { + std::cerr << "PRINT DATA START" << std::endl; + n_input->print(); + std::cerr << "PRINT DATA END===========" << std::endl; conduit::blueprint::mpi::mesh::partition(*n_input, n_options, *n_output, diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index d434724d7..71cdab776 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "t_config.hpp" #include "t_utils.hpp" @@ -30,17 +31,14 @@ using namespace std; using namespace conduit; using namespace ascent; +int NUM_DOMAINS = 8; + //----------------------------------------------------------------------------- -TEST(ascent_partition, test_distributed_mpi_partition_2D_multi_dom) +TEST(ascent_partition, test_partition_2D_multi_dom) { Node n; ascent::about(n); - // - // Create an example mesh. - // - Node data, verify_info; - // //Set Up MPI // @@ -50,133 +48,36 @@ TEST(ascent_partition, test_distributed_mpi_partition_2D_multi_dom) MPI_Comm_rank(comm, &par_rank); MPI_Comm_size(comm, &par_size); - // use spiral , with 7 domains - conduit::blueprint::mesh::examples::spiral(7,data); - - EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - - int root = 0; - if(par_rank == root) - ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI where the target is distributed amongst all ranks"); - - string output_path = prepare_output_dir(); - std::ostringstream oss; - - oss << "tout_distributed_partition_multi_dom_mpi"; - string output_base = conduit::utils::join_file_path(output_path, - oss.str()); - std::ostringstream ossjson; - ossjson << "tout_distributed_partition_multi_dom_mpi_json"; - string output_json = conduit::utils::join_file_path(output_base, - ossjson.str()); - // remove existing files - if(par_rank == root) - { - if(utils::is_file(output_base)) - { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) - { - utils::remove_file(output_json); - } - } - - conduit::Node actions; - int target = 1; - // add the pipeline - conduit::Node &add_pipelines = actions.append(); - add_pipelines["action"] = "add_pipelines"; - conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f1/type"] = "partition"; - pipelines["pl1/f1/params/target"] = target; - - //add the extract - conduit::Node &add_extracts = actions.append(); - add_extracts["action"] = "add_extracts"; - conduit::Node &extracts = add_extracts["extracts"]; - extracts["e1/type"] = "relay"; - extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; - - // - // Run Ascent - // - - Ascent ascent; - - Node ascent_opts; - ascent_opts["runtime"] = "ascent"; - ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); - ascent.open(ascent_opts); - ascent.publish(data); - ascent.execute(actions); - ascent.close(); - - if(par_rank == root) - { - //Two files in _output directory: - //tout_partition_multi_dom_mpi - //tout_partition_multi_dom_mpi_json - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); - - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - EXPECT_TRUE(num_doms == target); - } -} - -//----------------------------------------------------------------------------- -TEST(ascent_partition, test_nondistributed_mpi_partition_2D_multi_dom) -{ - Node n; - ascent::about(n); - // // Create an example mesh. // Node data, verify_info; - // - //Set Up MPI - // - int par_rank; - int par_size; - MPI_Comm comm = MPI_COMM_WORLD; - MPI_Comm_rank(comm, &par_rank); - MPI_Comm_size(comm, &par_size); - // use spiral , with 7 domains - conduit::blueprint::mesh::examples::spiral(7,data); + conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - int root = 0; - if(par_rank == root) - ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI but the target is not distributed and applies to each rank"); + ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); string output_path = prepare_output_dir(); std::ostringstream oss; - oss << "tout_nondistributed_partition_multi_dom_mpi"; + oss << "tout_partition_multi_dom_mpi"; string output_base = conduit::utils::join_file_path(output_path, oss.str()); std::ostringstream ossjson; - ossjson << "tout_nondistributed_partition_multi_dom_mpi_json"; + ossjson << "tout_partition_multi_dom_mpi_json"; string output_json = conduit::utils::join_file_path(output_base, ossjson.str()); - // remove existing files - if(par_rank == root) + // remove existing file + if(utils::is_file(output_base)) { - if(utils::is_file(output_base)) - { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) - { - utils::remove_file(output_json); - } + utils::remove_file(output_base); + } + if(utils::is_file(output_json)) + { + utils::remove_file(output_json); } conduit::Node actions; @@ -187,7 +88,6 @@ TEST(ascent_partition, test_nondistributed_mpi_partition_2D_multi_dom) conduit::Node &pipelines = add_pipelines["pipelines"]; pipelines["pl1/f1/type"] = "partition"; pipelines["pl1/f1/params/target"] = target; - pipelines["pl1/f1/params/distributed"] = "false"; //add the extract conduit::Node &add_extracts = actions.append(); @@ -197,6 +97,17 @@ TEST(ascent_partition, test_nondistributed_mpi_partition_2D_multi_dom) extracts["e1/pipeline"] = "pl1"; extracts["e1/params/path"] = output_base; + //add the scene + conduit::Node scenes; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "ranks"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/plots/p1/color_table/discrete"] = "true"; + scenes["s1/image_prefix"] = "tout_mpi_partition"; + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + add_scenes["scenes"] = scenes; + // // Run Ascent // @@ -211,20 +122,21 @@ TEST(ascent_partition, test_nondistributed_mpi_partition_2D_multi_dom) ascent.execute(actions); ascent.close(); - if(par_rank == root) + //Two files in _output directory: + //tout_partition_multi_dom_serial + //tout_partition_multi_dom_serial_json + if(par_rank == 0) { - //Two files in _output directory: - //tout_partition_multi_dom_mpi - //tout_partition_multi_dom_mpi_json - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); - - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - EXPECT_TRUE(num_doms == target); + EXPECT_TRUE(conduit::utils::is_file(output_base)); + Node read_csv; + conduit::relay::io::load(output_base,read_csv); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + EXPECT_TRUE(num_doms == target); } } + //----------------------------------------------------------------------------- int main(int argc, char* argv[]) { From 71525d1d2812fef2e30732f3bfc2abac58cea841 Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Mon, 28 Oct 2024 22:10:01 +0000 Subject: [PATCH 02/17] forgot fields --- .../flow_filters/ascent_runtime_blueprint_filters.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 4ae3db5f8..bbd59a563 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -410,6 +410,10 @@ BlueprintPartition::execute() conduit::Node &selections = params()["selections"]; n_options.append() = selections; } + if(params().has_child("fields")) + { + n_options["fields"] = params()["fields"]; + } std::cerr << "PRINT OPTIONS: " << std::endl; n_options.print(); From 19dff738cd9fd5209383ed1ba45406a7047afe1f Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Mon, 28 Oct 2024 22:51:58 +0000 Subject: [PATCH 03/17] redo docs --- src/docs/sphinx/Actions/Pipelines.rst | 262 ++++++++++++++------------ 1 file changed, 139 insertions(+), 123 deletions(-) diff --git a/src/docs/sphinx/Actions/Pipelines.rst b/src/docs/sphinx/Actions/Pipelines.rst index 92aaf5cdc..ceae2e86a 100644 --- a/src/docs/sphinx/Actions/Pipelines.rst +++ b/src/docs/sphinx/Actions/Pipelines.rst @@ -1088,33 +1088,25 @@ among many simulation ranks. Ascent utilizes the ``partition()`` functions provi that can be used to split or recombine Blueprint meshes in serial or parallel. Full M:N repartioning is supported. The ``partition()`` functions are in the serial and parallel Blueprint libraries, respectively. +Funtionality and further descriptions of optional parameters can be found in the Conduit::Blueprint `documentation `_. .. code:: cpp - // Serial - void conduit::blueprint::mesh::partition(const Node &mesh, - const Node &options, - Node &output); - - // Parallel - void conduit::blueprint::mpi::mesh::partition(const Node &mesh, - const Node &options, - Node &output, - MPI_Comm comm); - - -Partitioning meshes using Blueprint will use any options present to determine -how the partitioning process will behave. Typically, a caller would pass options -containing selections if pieces of domains are desired. The partitioner processes -any selections and then examines the desired target number of domains and will then -decide whether domains must be moved among ranks (only in parallel version) and -then locally combined to achieve the target number of domains. The combining -process will attempt to preserve the input topology type for the output topology. -However, in cases where lower topologies cannot be used, the algorithm will promote -the extracted domain parts towards more general topologies and use the one most -appropriate to contain the inputs. - -In parallel, the ``partition()`` function will make an effort to redistribute data across MPI + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "partition"; + //params optional + pipelines["pl1/f1/params/target"] = 1; + pipelines["pl1/f1/params/fields"] = ["pink","pony","club"]; + pipelines["pl1/f1/params/merge_tolerance"] = 0.000001; + pipelines["pl1/f1/params/mapping"] = 0;//turns off; on by default + pipelines["pl1/f1/params/build_adjsets"] = 1; + + + + + +In parallel, the Partition filter will make an effort to redistribute data across MPI ranks to attempt to balance how data are assigned. Domains produced from selections are assigned round-robin across ranks from rank 0 through rank N-1 until all domains have been assigned. This assignment is carried out after extracting @@ -1131,86 +1123,103 @@ before being combined into the target number of domains. Options +++++++ -The ``partition()`` functions accept a node containing options. The options node -can be empty and all options are optional. If no options are given, each input mesh -domain will be fully selected. It is more useful to pass selections as part of the -option node with additional options that tell the algorithm how to split or combine -the inputs. If no selections are present in the options node then the partitioner -will create selections of an appropriate type that selects all elements in each +The Partition filter accepts optional parameters. +If no optional parameters are given, each input mesh +domain will be fully selected. +If no ``selections`` are specifed as ``params`` then the partitioner +will create selections of an appropriate type that selects all elements in each input domain. -The ``target`` option is useful for setting the target number of domains in the +The ``target`` parameter is useful for setting the target number of domains in the final output mesh. If the target value is larger than the number of input domains or selections then the mesh will be split to achieve that target number of domains. This may require further subdividing selections. Alternatively, if the target is smaller than the number of selections then the selections will be combined to yield the target number of domains. The combining is done such that smaller element -count domains are combined first. Additionally, Ascent provides an optional boolean parameter, ``distributed``, which dictates if the number of chosen target domains is applied across ranks (``true``, default), or to each rank individually (``false``). +count domains are combined first. +Additionally, Ascent provides an optional boolean parameter, ``distributed``, which dictates if the number +of chosen target domains is applied across ranks (``true``, default), or to each rank individually (``false``). .. tabularcolumns:: |p{1.5cm}|p{4cm}|L| -+------------------+-----------------------------------------+------------------------------------------+ -| **Option** | **Description** | **Example** | -+------------------+-----------------------------------------+------------------------------------------+ -| selections | A list of selection objects that | .. code:: yaml | -| | identify regions of interest from the | | -| | input domains. Selections can be | selections: | -| | different on each MPI rank. | - | -| | | type: logical | -| | | start: [0,0,0] | -| | | end: [9,9,9] | -| | | domain_id: 10 | -+------------------+-----------------------------------------+------------------------------------------+ -| target | An optional integer that determines the | .. code:: yaml | -| | fields containing original domains and | | -| | number of domains in the output. If | target: 4 | -| | given, the value must be greater than 0.| | -| | Values larger than the number of | | -| | selections cause domains to be split. | | -| | Values smaller than the number of | | -| | selections cause domains to be combined.| | -| | Invalid values are ignored. | | -| | | | -| | If not given, the output will contain | | -| | the number of selections. In parallel, | | -| | the largest target value from the ranks | | -| | will be used for all ranks. | | -+------------------+-----------------------------------------+------------------------------------------+ -| fields | An list of strings that indicate the | .. code:: yaml | -| | names of the fields to extract in the | | -| | output. If this option is not provided, | fields: ["dist", "pressure"] | -| | all fields will be extracted. | | -+------------------+-----------------------------------------+------------------------------------------+ -| mapping | An integer that determines whether | .. code:: yaml | -| | fields containing original domains and | | -| | ids will be added in the output. These | mapping: 0 | -| | fields enable one to know where each | | -| | vertex and element came from originally.| | -| | Mapping is on by default. A non-zero | | -| | value turns it on and a zero value turns| | -| | it off. | | -+------------------+-----------------------------------------+------------------------------------------+ -| merge_tolerance | A double value that indicates the max | .. code:: yaml | -| | allowable distance between 2 points | | -| | before they are considered to be | merge_tolerance: 0.000001 | -| | separate. 2 points spaced smaller than | | -| | this distance will be merged when | | -| | explicit coordsets are combined. | | -+------------------+-----------------------------------------+------------------------------------------+ -| distributed | An optional boolean value for parallel | .. code:: yaml | -| | execution. If true, the chosen number | | -| | of target domains will be applied | distributed: "false" | -| | across all ranks. If false, the chosen | | -| | number of target domains will be | | -| | applied to each rank individually. | | -| | | | -| | If not given, the default is true. | | -+------------------+-----------------------------------------+------------------------------------------+ ++---------------------+-----------------------------------------+------------------------------------------+ +| **Option** | **Description** | **Example** | ++---------------------+-----------------------------------------+------------------------------------------+ +| selections | A list of selection objects that | .. code:: yaml | +| | identify regions of interest from the | | +| | input domains. Selections can be | selections: | +| | different on each MPI rank. | type: "logical" | +| | | start: [0,0,0] | +| | | end: [9,9,9] | +| | | domain_id: 10 | ++---------------------+-----------------------------------------+------------------------------------------+ +| target | An optional integer that determines the | .. code:: yaml | +| | fields containing original domains and | | +| | number of domains in the output. If | target: 4 | +| | given, the value must be greater than 0.| | +| | Values larger than the number of | | +| | selections cause domains to be split. | | +| | Values smaller than the number of | | +| | selections cause domains to be combined.| | +| | Invalid values are ignored. | | +| | | | +| | If not given, the output will contain | | +| | the number of selections. In parallel, | | +| | the largest target value from the ranks | | +| | will be used for all ranks. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| fields | An list of strings that indicate the | .. code:: yaml | +| | names of the fields to extract in the | | +| | output. If this option is not provided, | fields: ["dist", "pressure"] | +| | all fields will be extracted. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| mapping | An integer that determines whether | .. code:: yaml | +| | fields containing original domains and | | +| | ids will be added in the output. These | mapping: 0 | +| | fields enable one to know where each | | +| | vertex and element came from originally.| | +| | Mapping is on by default. A non-zero | | +| | value turns it on and a zero value turns| | +| | it off. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| merge_tolerance | A double value that indicates the max | .. code:: yaml | +| | allowable distance between 2 points | | +| | before they are considered to be | merge_tolerance: 0.000001 | +| | separate. 2 points spaced smaller than | | +| | this distance will be merged when | | +| | explicit coordsets are combined. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| distributed | An optional boolean value for parallel | .. code:: yaml | +| | execution. If true, the chosen number | | +| | of target domains will be applied | distributed: "false" | +| | across all ranks. If false, the chosen | | +| | number of target domains will be | | +| | applied to each rank individually. | | +| | | | +| | If not given, the default is true. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| build_adjsets | An integer that determines whether | .. code:: yaml | +| | the partitioner should build adjsets, | | +| | if they are present in the selected | build_adjsets: 1 | +| | topology. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| original_element_ids| A string value that provides desired | .. code::yaml | +| | field name used to contain original | | +| | element ids created from partitioning. | original_element_ids: "elem_name" | +| | The default value is | | +| | original_element_ids. | | ++---------------------+-----------------------------------------+------------------------------------------+ +| original_vertex_ids | A string value that provides desired | .. code::yaml | +| | field name used to contain original | | +| | vertex ids created from partitioning. | original_vertex_ids: "vert_name" | +| | The default value is | | +| | original_vertex_ids. | | ++---------------------+-----------------------------------------+------------------------------------------+ Selections ++++++++++ -Selections can be specified in the options for the ``partition()`` function to +Selections can be specified in the options for the Partition Filter to select regions of interest that will participate in mesh partitioning. If selections are not used then all elements from the input meshes will be selected to partitipate in the partitioning process. Selections can be further @@ -1219,7 +1228,7 @@ target specific domains and topologies as well. If a selection does not apply to the input mesh domains then no geometry is produced in the output for that selection. -The ``partition()`` function's options support 4 types of selections: +The Partition filter supports 4 types of selections: .. tabularcolumns:: |p{1.5cm}|p{2cm}|L| @@ -1251,31 +1260,29 @@ operate on the specified topology only. | type | The selection type | .. code:: yaml | | | | | | | | selections: | -| | | - | -| | | type: logical | +| | | type: "logical" | +------------------+-----------------------------------------+------------------------------------------+ | domain_id | The domain_id to which the selection | .. code:: yaml | | | will apply. This is almost always an | | | | unsigned integer value. | selections: | -| | | - | -| | | type: logical | +| | | type: "logical" | | | | domain_id: 10 | | | | | | | | .. code:: yaml | | | | | | | For field selections, domain_id is | selections: | -| | allowed to be a string "any" so a single| - | -| | selection can apply to many domains. | type: logical | -| | | domain_id: any | +| | allowed to be a string "any" so a single| type: "logical" | +| | selection can apply to many domains. | domain_id = "any" | +| | | | | | | | +------------------+-----------------------------------------+------------------------------------------+ | topology | The topology to which the selection | .. code:: yaml | | | will apply. | | | | | selections: | -| | | - | -| | | type: logical | +| | | type: "logical" | | | | domain_id: 10 | -| | | topology: mesh | +| | | topology: "mesh" | +| | | | +------------------+-----------------------------------------+------------------------------------------+ Logical Selection @@ -1286,13 +1293,15 @@ beyond the actual mesh's logical extents, they will be clipped. The partitioner automatically subdivide logical selections into smaller logical selections, if needed, preserving the logical structure of the input topology into the output. -.. code:: yaml +.. code:: cpp - selections: - - - type: logical - start: [0,0,0] - end: [9,9,9] + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "partition"; + //params optional + pipelines["pl1/f1/params/selections/type"] = "logical"; + pipelines["pl1/f1/params/selections/start"] = [0,0,0]; + pipelines["pl1/f1/params/selections/end"] = [9,9,9]; Explicit Selection ****************** @@ -1300,12 +1309,14 @@ The explicit selection allows the partitioner to extract a list of elements. This is used when the user wants to target a specific set of elements. The output will result in an explicit topology. -.. code:: yaml +.. code:: cpp - selections: - - - type: explicit - elements: [0,1,2,3,100,101,102] + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "partition"; + //params optional + pipelines["pl1/f1/params/selections/type"] = "explicit"; + pipelines["pl1/f1/params/selections/elements"] = [0,1,2,3,100,101,102]; Ranges Selection @@ -1314,12 +1325,15 @@ The ranges selection is similar to the explicit selection except that it identif ranges of elements using pairs of numbers. The list of ranges must be a multiple of 2 in length. The output will result in an explicit topology. -.. code:: yaml +.. code:: cpp + + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "partition"; + //params optional + pipelines["pl1/f1/params/selections/type"] = "ranges"; + pipelines["pl1/f1/params/selections/elements"] = [0,3,100,102]; - selections: - - - type: ranges - ranges: [0,3,100,102] Field Selection *************** @@ -1334,11 +1348,13 @@ can be set to "any" if it is desired that the field selection will be applied to all domains in the input mesh. The domain_id value can still be set to specific integer values to limit the set of domains over which the selection will be applied. -.. code:: yaml +.. code:: cpp - selections: - - - type: field - domain_id: any - field: fieldname + conduit::Node pipelines; + // pipeline 1 + pipelines["pl1/f1/type"] = "partition"; + //params optional + pipelines["pl1/f1/params/selections/type"] = "field"; + pipelines["pl1/f1/params/selections/domain_id"] = "any"; + pipelines["pl1/f1/params/selections/field"] = "padam_padam"; From 6efd5e7db5670663b9dc30a81d26af0e025a46f1 Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Wed, 30 Oct 2024 13:55:10 -0700 Subject: [PATCH 04/17] add destination_ranks --- src/docs/sphinx/Actions/Pipelines.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/docs/sphinx/Actions/Pipelines.rst b/src/docs/sphinx/Actions/Pipelines.rst index ceae2e86a..1a7a49d15 100644 --- a/src/docs/sphinx/Actions/Pipelines.rst +++ b/src/docs/sphinx/Actions/Pipelines.rst @@ -1348,6 +1348,27 @@ can be set to "any" if it is desired that the field selection will be applied to all domains in the input mesh. The domain_id value can still be set to specific integer values to limit the set of domains over which the selection will be applied. ++------------------+-----------------------------------------+------------------------------------------+ +| **Option** | **Description** | **Example** | ++------------------+-----------------------------------------+------------------------------------------+ +| field | The name of the element field that will | .. code:: yaml | +| | be used for partitioning. The field | | +| | shall contain non-negative domain | selections: | +| | numbers. | type: "field" | +| | | domain_id: "any" | +| | | | ++------------------+-----------------------------------------+------------------------------------------+ +| destination_ranks| An optional list of integers | .. code:: yaml | +| | representing the MPI rank where the | | +| | domain will be sent after partitioning. | selections: | +| | This option can help ensure domains for | type: "field" | +| | topologies partitioned via multiple | field: "albatroaz" | +| | calls to partition() end up together on | domain_id: "any" | +| | a target MPI rank. The example shows | destination_ranks: [0,1,2,3] | +| | domain 0 going to MPI rank 0 and so on. | | +| | | | ++------------------+-----------------------------------------+------------------------------------------+ + .. code:: cpp conduit::Node pipelines; From 199466e0286e69719c9f5a03e5c2010d31bf1717 Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Wed, 30 Oct 2024 16:24:02 -0700 Subject: [PATCH 05/17] wrap single domain partitions --- .../ascent_runtime_blueprint_filters.cpp | 29 +++++++------ src/tests/ascent/t_ascent_mpi_partition.cpp | 43 ++++++++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index bbd59a563..6c9c0ef0a 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -383,11 +383,13 @@ BlueprintPartition::execute() conduit::Node *n_output = new conduit::Node(); - conduit::Node n_options = params(); + conduit::Node n_options; + int target = 0; if(params().has_child("target")) { - n_options["target"] = params()["target"].to_int32(); + target = params()["target"].to_int32(); + n_options["target"] = target; } if(params().has_child("mapping")) { @@ -414,10 +416,8 @@ BlueprintPartition::execute() { n_options["fields"] = params()["fields"]; } - std::cerr << "PRINT OPTIONS: " << std::endl; - n_options.print(); - - + + conduit::Node tmp; #ifdef ASCENT_MPI_ENABLED MPI_Comm mpi_comm = MPI_Comm_f2c(flow::Workspace::default_mpi_comm()); if(params().has_child("distributed") && @@ -425,23 +425,28 @@ BlueprintPartition::execute() { conduit::blueprint::mesh::partition(*n_input, n_options, - *n_output); + tmp); } else { - std::cerr << "PRINT DATA START" << std::endl; - n_input->print(); - std::cerr << "PRINT DATA END===========" << std::endl; conduit::blueprint::mpi::mesh::partition(*n_input, n_options, - *n_output, + tmp, mpi_comm); } #else conduit::blueprint::mesh::partition(*n_input, n_options, - *n_output); + tmp); #endif + if(target == 1) + { + n_output->append() = tmp; + } + if(target != 1) + { + n_output->move(tmp); + } DataObject *d_output = new DataObject(n_output); set_output(d_output); } diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 71cdab776..0f9a0e2b7 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -90,23 +90,23 @@ TEST(ascent_partition, test_partition_2D_multi_dom) pipelines["pl1/f1/params/target"] = target; //add the extract - conduit::Node &add_extracts = actions.append(); - add_extracts["action"] = "add_extracts"; - conduit::Node &extracts = add_extracts["extracts"]; - extracts["e1/type"] = "relay"; - extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; + //conduit::Node &add_extracts = actions.append(); + //add_extracts["action"] = "add_extracts"; + //conduit::Node &extracts = add_extracts["extracts"]; + //extracts["e1/type"] = "relay"; + //extracts["e1/pipeline"] = "pl1"; + //extracts["e1/params/path"] = output_base; //add the scene - conduit::Node scenes; + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; scenes["s1/plots/p1/type"] = "pseudocolor"; - scenes["s1/plots/p1/field"] = "ranks"; + //scenes["s1/plots/p1/field"] = "dist"; + scenes["s1/plots/p1/field"] = "rank"; scenes["s1/plots/p1/pipeline"] = "pl1"; - scenes["s1/plots/p1/color_table/discrete"] = "true"; +// scenes["s1/plots/p1/color_table/discrete"] = "true"; scenes["s1/image_prefix"] = "tout_mpi_partition"; - conduit::Node &add_scenes= actions.append(); - add_scenes["action"] = "add_scenes"; - add_scenes["scenes"] = scenes; // // Run Ascent @@ -117,6 +117,7 @@ TEST(ascent_partition, test_partition_2D_multi_dom) Node ascent_opts; ascent_opts["runtime"] = "ascent"; ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["timings"] = "true"; ascent.open(ascent_opts); ascent.publish(data); ascent.execute(actions); @@ -125,15 +126,15 @@ TEST(ascent_partition, test_partition_2D_multi_dom) //Two files in _output directory: //tout_partition_multi_dom_serial //tout_partition_multi_dom_serial_json - if(par_rank == 0) - { - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); - - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - EXPECT_TRUE(num_doms == target); - } + //if(par_rank == 0) + //{ + // EXPECT_TRUE(conduit::utils::is_file(output_base)); + // Node read_csv; + // conduit::relay::io::load(output_base,read_csv); + + // int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + // EXPECT_TRUE(num_doms == target); + //} } From fc9aa850a0edbb35bffbf3588a352c78152c2b6a Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Wed, 30 Oct 2024 16:24:31 -0700 Subject: [PATCH 06/17] wrap single domain partitions --- .../runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 6c9c0ef0a..d1b31a99c 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -443,7 +443,7 @@ BlueprintPartition::execute() { n_output->append() = tmp; } - if(target != 1) + else { n_output->move(tmp); } From e9e940b981a93edb75aa5901c24cb62124096b77 Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Thu, 31 Oct 2024 15:29:22 -0700 Subject: [PATCH 07/17] docs, add selection unit test --- src/docs/sphinx/Actions/Pipelines.rst | 17 +- .../ascent_runtime_blueprint_filters.cpp | 9 +- src/tests/ascent/t_ascent_mpi_partition.cpp | 247 ++++++++++++++++-- 3 files changed, 242 insertions(+), 31 deletions(-) diff --git a/src/docs/sphinx/Actions/Pipelines.rst b/src/docs/sphinx/Actions/Pipelines.rst index 1a7a49d15..fc0b0d299 100644 --- a/src/docs/sphinx/Actions/Pipelines.rst +++ b/src/docs/sphinx/Actions/Pipelines.rst @@ -1097,7 +1097,8 @@ Funtionality and further descriptions of optional parameters can be found in the pipelines["pl1/f1/type"] = "partition"; //params optional pipelines["pl1/f1/params/target"] = 1; - pipelines["pl1/f1/params/fields"] = ["pink","pony","club"]; + const char* fields[3] = {"pink", "pony", "club"}; + pipelines["pl1/f1/params/fields"].set(fields,3); pipelines["pl1/f1/params/merge_tolerance"] = 0.000001; pipelines["pl1/f1/params/mapping"] = 0;//turns off; on by default pipelines["pl1/f1/params/build_adjsets"] = 1; @@ -1300,8 +1301,10 @@ preserving the logical structure of the input topology into the output. pipelines["pl1/f1/type"] = "partition"; //params optional pipelines["pl1/f1/params/selections/type"] = "logical"; - pipelines["pl1/f1/params/selections/start"] = [0,0,0]; - pipelines["pl1/f1/params/selections/end"] = [9,9,9]; + const float start[3] = {0,0,0}; + const float end[3] = {10,10,10}; + pipelines["pl1/f1/params/selections/start"].set(start,3); + pipelines["pl1/f1/params/selections/end"].set(end,3); Explicit Selection ****************** @@ -1316,7 +1319,8 @@ The output will result in an explicit topology. pipelines["pl1/f1/type"] = "partition"; //params optional pipelines["pl1/f1/params/selections/type"] = "explicit"; - pipelines["pl1/f1/params/selections/elements"] = [0,1,2,3,100,101,102]; + const int elements[6] = [0,1,2,3,100,101,102]; + pipelines["pl1/f1/params/selections/elements"].set(elements,6); Ranges Selection @@ -1332,7 +1336,8 @@ ranges of elements using pairs of numbers. The list of ranges must be a multiple pipelines["pl1/f1/type"] = "partition"; //params optional pipelines["pl1/f1/params/selections/type"] = "ranges"; - pipelines["pl1/f1/params/selections/elements"] = [0,3,100,102]; + const int elements[4] = [0,3,100,102]; + pipelines["pl1/f1/params/selections/elements"].set(elements,4); Field Selection @@ -1362,7 +1367,7 @@ integer values to limit the set of domains over which the selection will be appl | | representing the MPI rank where the | | | | domain will be sent after partitioning. | selections: | | | This option can help ensure domains for | type: "field" | -| | topologies partitioned via multiple | field: "albatroaz" | +| | topologies partitioned via multiple | field: "albatraoz" | | | calls to partition() end up together on | domain_id: "any" | | | a target MPI rank. The example shows | destination_ranks: [0,1,2,3] | | | domain 0 going to MPI rank 0 and so on. | | diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index d1b31a99c..9366f16b3 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -348,7 +348,12 @@ BlueprintPartition::verify_params(const conduit::Node ¶ms, valid_paths.push_back("target"); valid_paths.push_back("selections/type"); valid_paths.push_back("selections/domain_id"); + valid_paths.push_back("selections/field"); valid_paths.push_back("selections/topology"); + valid_paths.push_back("selections/start"); + valid_paths.push_back("selections/end"); + valid_paths.push_back("selections/elements"); + valid_paths.push_back("selections/ranges"); valid_paths.push_back("fields"); valid_paths.push_back("mapping"); valid_paths.push_back("merge_tolerance"); @@ -385,7 +390,7 @@ BlueprintPartition::execute() conduit::Node n_options; - int target = 0; + int target = 1; if(params().has_child("target")) { target = params()["target"].to_int32(); @@ -410,7 +415,7 @@ BlueprintPartition::execute() if(params().has_child("selections")) { conduit::Node &selections = params()["selections"]; - n_options.append() = selections; + n_options["selections"].append() = selections; } if(params().has_child("fields")) { diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 0f9a0e2b7..637ed46f1 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -34,7 +34,7 @@ using namespace ascent; int NUM_DOMAINS = 8; //----------------------------------------------------------------------------- -TEST(ascent_partition, test_partition_2D_multi_dom) +TEST(ascent_partition, test_mpi_partition_target_1) { Node n; ascent::about(n); @@ -63,11 +63,11 @@ TEST(ascent_partition, test_partition_2D_multi_dom) string output_path = prepare_output_dir(); std::ostringstream oss; - oss << "tout_partition_multi_dom_mpi"; + oss << "tout_partition_target_1_mpi"; string output_base = conduit::utils::join_file_path(output_path, oss.str()); std::ostringstream ossjson; - ossjson << "tout_partition_multi_dom_mpi_json"; + ossjson << "tout_partition_target_1_mpi_json"; string output_json = conduit::utils::join_file_path(output_base, ossjson.str()); // remove existing file @@ -90,23 +90,223 @@ TEST(ascent_partition, test_partition_2D_multi_dom) pipelines["pl1/f1/params/target"] = target; //add the extract - //conduit::Node &add_extracts = actions.append(); - //add_extracts["action"] = "add_extracts"; - //conduit::Node &extracts = add_extracts["extracts"]; - //extracts["e1/type"] = "relay"; - //extracts["e1/pipeline"] = "pl1"; - //extracts["e1/params/path"] = output_base; + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + conduit::Node &extracts = add_extracts["extracts"]; + extracts["e1/type"] = "relay"; + extracts["e1/pipeline"] = "pl1"; + extracts["e1/params/path"] = output_base; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["runtime"] = "ascent"; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + //Two files in _output directory: + //tout_partition_multi_dom_serial + //tout_partition_multi_dom_serial_json + if(par_rank == 0) + { + EXPECT_TRUE(conduit::utils::is_file(output_base)); + Node read_csv; + conduit::relay::io::load(output_base,read_csv); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + EXPECT_TRUE(num_doms == target); + } +} + +//----------------------------------------------------------------------------- +TEST(ascent_partition, test_mpi_partition_target_10) +{ + Node n; + ascent::about(n); + + // + //Set Up MPI + // + int par_rank; + int par_size; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &par_rank); + MPI_Comm_size(comm, &par_size); + + // + // Create an example mesh. + // + Node data, verify_info; + + // use spiral , with 7 domains + conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); + + string output_path = prepare_output_dir(); + std::ostringstream oss; + + oss << "tout_partition_target_10_mpi"; + string output_base = conduit::utils::join_file_path(output_path, + oss.str()); + std::ostringstream ossjson; + ossjson << "tout_partition_taret_10_mpi_json"; + string output_json = conduit::utils::join_file_path(output_base, + ossjson.str()); + // remove existing file + if(utils::is_file(output_base)) + { + utils::remove_file(output_base); + } + if(utils::is_file(output_json)) + { + utils::remove_file(output_json); + } + + conduit::Node actions; + int target = 10; + // add the pipeline + conduit::Node &add_pipelines = actions.append(); + add_pipelines["action"] = "add_pipelines"; + conduit::Node &pipelines = add_pipelines["pipelines"]; + pipelines["pl1/f1/type"] = "partition"; + pipelines["pl1/f1/params/target"] = target; + + //add the extract + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + conduit::Node &extracts = add_extracts["extracts"]; + extracts["e1/type"] = "relay"; + extracts["e1/pipeline"] = "pl1"; + extracts["e1/params/path"] = output_base; + + //add the scene + //conduit::Node &add_scenes= actions.append(); + //add_scenes["action"] = "add_scenes"; + //conduit::Node &scenes = add_scenes["scenes"]; + //scenes["s1/plots/p1/type"] = "pseudocolor"; + //scenes["s1/plots/p1/field"] = "dist"; + //scenes["s1/plots/p1/field"] = "rank"; + //scenes["s1/plots/p1/pipeline"] = "pl1"; + // scenes["s1/plots/p1/color_table/discrete"] = "true"; + //scenes["s1/image_prefix"] = "tout_mpi_partition"; + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["runtime"] = "ascent"; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + //Two files in _output directory: + //tout_partition_multi_dom_serial + //tout_partition_multi_dom_serial_json + if(par_rank == 0) + { + EXPECT_TRUE(conduit::utils::is_file(output_base)); + Node read_csv; + conduit::relay::io::load(output_base,read_csv); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + EXPECT_TRUE(num_doms == target); + } +} + + +//----------------------------------------------------------------------------- +TEST(ascent_partition, test_mpi_partition_selection) +{ + Node n; + ascent::about(n); + + // + //Set Up MPI + // + int par_rank; + int par_size; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &par_rank); + MPI_Comm_size(comm, &par_size); + + // + // Create an example mesh. + // + Node data, verify_info; + + // use spiral , with 7 domains + conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); + + string output_path = prepare_output_dir(); + std::ostringstream oss; + + oss << "tout_partition_selection_mpi"; + string output_base = conduit::utils::join_file_path(output_path, + oss.str()); + std::ostringstream ossjson; + ossjson << "tout_partition_selection_mpi_json"; + string output_json = conduit::utils::join_file_path(output_base, + ossjson.str()); + // remove existing file + if(utils::is_file(output_base)) + { + utils::remove_file(output_base); + } + if(utils::is_file(output_json)) + { + utils::remove_file(output_json); + } + + conduit::Node actions; + int target = 1; + // add the pipeline + conduit::Node &add_pipelines = actions.append(); + add_pipelines["action"] = "add_pipelines"; + conduit::Node &pipelines = add_pipelines["pipelines"]; + pipelines["pl1/f1/type"] = "partition"; + pipelines["pl1/f1/params/selections/type"] = "logical"; + //float start[2] = {0,0}; + float start[3] = {0,0,0}; + float end[3] = {10,10,0}; + //float end[2] = {0.5,0.5}; + pipelines["pl1/f1/params/selections/start"].set(start,3); + pipelines["pl1/f1/params/selections/end"].set(end,3); + + //add the extract + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + conduit::Node &extracts = add_extracts["extracts"]; + extracts["e1/type"] = "relay"; + extracts["e1/pipeline"] = "pl1"; + extracts["e1/params/path"] = output_base; //add the scene conduit::Node &add_scenes= actions.append(); add_scenes["action"] = "add_scenes"; conduit::Node &scenes = add_scenes["scenes"]; scenes["s1/plots/p1/type"] = "pseudocolor"; - //scenes["s1/plots/p1/field"] = "dist"; - scenes["s1/plots/p1/field"] = "rank"; + scenes["s1/plots/p1/field"] = "dist"; scenes["s1/plots/p1/pipeline"] = "pl1"; -// scenes["s1/plots/p1/color_table/discrete"] = "true"; - scenes["s1/image_prefix"] = "tout_mpi_partition"; + scenes["s1/image_prefix"] = output_base; // // Run Ascent @@ -117,7 +317,6 @@ TEST(ascent_partition, test_partition_2D_multi_dom) Node ascent_opts; ascent_opts["runtime"] = "ascent"; ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); - ascent_opts["timings"] = "true"; ascent.open(ascent_opts); ascent.publish(data); ascent.execute(actions); @@ -126,18 +325,20 @@ TEST(ascent_partition, test_partition_2D_multi_dom) //Two files in _output directory: //tout_partition_multi_dom_serial //tout_partition_multi_dom_serial_json - //if(par_rank == 0) - //{ - // EXPECT_TRUE(conduit::utils::is_file(output_base)); - // Node read_csv; - // conduit::relay::io::load(output_base,read_csv); - - // int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - // EXPECT_TRUE(num_doms == target); - //} + if(par_rank == 0) + { + EXPECT_TRUE(conduit::utils::is_file(output_base)); + Node read_csv; + conduit::relay::io::load(output_base,read_csv); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + EXPECT_TRUE(num_doms == target); + } } + + //----------------------------------------------------------------------------- int main(int argc, char* argv[]) { From cc7d253a9d5f5fb704f06be74df8b2e65b0ef91b Mon Sep 17 00:00:00 2001 From: Nicole Marsaglia Date: Tue, 5 Nov 2024 15:23:02 -0800 Subject: [PATCH 08/17] fields aren't the right assoc for selection? --- src/tests/ascent/t_ascent_mpi_partition.cpp | 210 ++++++++++---------- 1 file changed, 103 insertions(+), 107 deletions(-) diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 637ed46f1..4d978d3cc 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -230,113 +230,109 @@ TEST(ascent_partition, test_mpi_partition_target_10) //----------------------------------------------------------------------------- -TEST(ascent_partition, test_mpi_partition_selection) -{ - Node n; - ascent::about(n); - - // - //Set Up MPI - // - int par_rank; - int par_size; - MPI_Comm comm = MPI_COMM_WORLD; - MPI_Comm_rank(comm, &par_rank); - MPI_Comm_size(comm, &par_size); - - // - // Create an example mesh. - // - Node data, verify_info; - - // use spiral , with 7 domains - conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); - - EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - - ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); - - string output_path = prepare_output_dir(); - std::ostringstream oss; - - oss << "tout_partition_selection_mpi"; - string output_base = conduit::utils::join_file_path(output_path, - oss.str()); - std::ostringstream ossjson; - ossjson << "tout_partition_selection_mpi_json"; - string output_json = conduit::utils::join_file_path(output_base, - ossjson.str()); - // remove existing file - if(utils::is_file(output_base)) - { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) - { - utils::remove_file(output_json); - } - - conduit::Node actions; - int target = 1; - // add the pipeline - conduit::Node &add_pipelines = actions.append(); - add_pipelines["action"] = "add_pipelines"; - conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f1/type"] = "partition"; - pipelines["pl1/f1/params/selections/type"] = "logical"; - //float start[2] = {0,0}; - float start[3] = {0,0,0}; - float end[3] = {10,10,0}; - //float end[2] = {0.5,0.5}; - pipelines["pl1/f1/params/selections/start"].set(start,3); - pipelines["pl1/f1/params/selections/end"].set(end,3); - - //add the extract - conduit::Node &add_extracts = actions.append(); - add_extracts["action"] = "add_extracts"; - conduit::Node &extracts = add_extracts["extracts"]; - extracts["e1/type"] = "relay"; - extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; - - //add the scene - conduit::Node &add_scenes= actions.append(); - add_scenes["action"] = "add_scenes"; - conduit::Node &scenes = add_scenes["scenes"]; - scenes["s1/plots/p1/type"] = "pseudocolor"; - scenes["s1/plots/p1/field"] = "dist"; - scenes["s1/plots/p1/pipeline"] = "pl1"; - scenes["s1/image_prefix"] = output_base; - - // - // Run Ascent - // - - Ascent ascent; - - Node ascent_opts; - ascent_opts["runtime"] = "ascent"; - ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); - ascent.open(ascent_opts); - ascent.publish(data); - ascent.execute(actions); - ascent.close(); - - //Two files in _output directory: - //tout_partition_multi_dom_serial - //tout_partition_multi_dom_serial_json - if(par_rank == 0) - { - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); - - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - EXPECT_TRUE(num_doms == target); - } -} - - +//TEST(ascent_partition, test_mpi_partition_selection) +//{ +// Node n; +// ascent::about(n); +// +// // +// //Set Up MPI +// // +// int par_rank; +// int par_size; +// MPI_Comm comm = MPI_COMM_WORLD; +// MPI_Comm_rank(comm, &par_rank); +// MPI_Comm_size(comm, &par_size); +// +// // +// // Create an example mesh. +// // +// Node data, verify_info; +// +// // use spiral , with 7 domains +// conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); +// +// EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); +// +// ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); +// +// string output_path = prepare_output_dir(); +// std::ostringstream oss; +// +// oss << "tout_partition_selection_mpi"; +// string output_base = conduit::utils::join_file_path(output_path, +// oss.str()); +// std::ostringstream ossjson; +// ossjson << "tout_partition_selection_mpi_json"; +// string output_json = conduit::utils::join_file_path(output_base, +// ossjson.str()); +// // remove existing file +// if(utils::is_file(output_base)) +// { +// utils::remove_file(output_base); +// } +// if(utils::is_file(output_json)) +// { +// utils::remove_file(output_json); +// } +// +// conduit::Node actions; +// int target = 1; +// // add the pipeline +// conduit::Node &add_pipelines = actions.append(); +// add_pipelines["action"] = "add_pipelines"; +// conduit::Node &pipelines = add_pipelines["pipelines"]; +// pipelines["pl1/f1/type"] = "partition"; +// pipelines["pl1/f1/params/selections/type"] = "field"; +// pipelines["pl1/f1/params/selections/field"] = "dist"; +// //float start[2] = {0,0}; +// +// //add the extract +// conduit::Node &add_extracts = actions.append(); +// add_extracts["action"] = "add_extracts"; +// conduit::Node &extracts = add_extracts["extracts"]; +// extracts["e1/type"] = "relay"; +// extracts["e1/pipeline"] = "pl1"; +// extracts["e1/params/path"] = output_base; +// +// //add the scene +// conduit::Node &add_scenes= actions.append(); +// add_scenes["action"] = "add_scenes"; +// conduit::Node &scenes = add_scenes["scenes"]; +// scenes["s1/plots/p1/type"] = "pseudocolor"; +// scenes["s1/plots/p1/field"] = "dist"; +// scenes["s1/plots/p1/pipeline"] = "pl1"; +// scenes["s1/image_prefix"] = output_base; +// +// // +// // Run Ascent +// // +// +// Ascent ascent; +// +// Node ascent_opts; +// ascent_opts["runtime"] = "ascent"; +// ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); +// ascent.open(ascent_opts); +// ascent.publish(data); +// ascent.execute(actions); +// ascent.close(); +// +// //Two files in _output directory: +// //tout_partition_multi_dom_serial +// //tout_partition_multi_dom_serial_json +// if(par_rank == 0) +// { +// EXPECT_TRUE(conduit::utils::is_file(output_base)); +// Node read_csv; +// conduit::relay::io::load(output_base,read_csv); +// +// int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); +// EXPECT_TRUE(num_doms == target); +// } +//} +// +// //----------------------------------------------------------------------------- From e9dbaa1f16c5f5e563800399c7c8736626aed7df Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Thu, 30 Jan 2025 17:09:44 -0800 Subject: [PATCH 09/17] Update src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp --- .../runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 9366f16b3..d8337a98e 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -446,7 +446,7 @@ BlueprintPartition::execute() #endif if(target == 1) { - n_output->append() = tmp; + n_output->append().move(tmp); } else { From 58fc3304ce59f22c22c7551d6be9b93b7e9b6579 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Sat, 1 Feb 2025 12:06:34 -0800 Subject: [PATCH 10/17] wip --- .../ascent/t_ascent_mpi_add_domain_ids.cpp | 42 +-- src/tests/ascent/t_ascent_mpi_add_ranks.cpp | 39 +-- src/tests/ascent/t_ascent_mpi_partition.cpp | 248 +++++++++--------- src/tests/ascent/t_ascent_partition.cpp | 53 ++-- 4 files changed, 176 insertions(+), 206 deletions(-) diff --git a/src/tests/ascent/t_ascent_mpi_add_domain_ids.cpp b/src/tests/ascent/t_ascent_mpi_add_domain_ids.cpp index 8c990c81d..2e6c67f75 100644 --- a/src/tests/ascent/t_ascent_mpi_add_domain_ids.cpp +++ b/src/tests/ascent/t_ascent_mpi_add_domain_ids.cpp @@ -26,8 +26,6 @@ #include "t_utils.hpp" - - using namespace std; using namespace conduit; using namespace ascent; @@ -81,48 +79,34 @@ TEST(ascent_mpi_add_domain_ids, test_mpi_add_domain_ids) // Create the actions. // - conduit::Node pipelines; - // pipeline 1 - pipelines["pl1/f1/type"] = "add_domain_ids"; - conduit::Node ¶ms = pipelines["pl1/f1/params"]; - params["topology"] = "topo"; - params["output"] = "domain_ids"; - - conduit::Node scenes; - scenes["s1/plots/p1/type"] = "pseudocolor"; - scenes["s1/plots/p1/field"] = "domain_ids"; - scenes["s1/plots/p1/pipeline"] = "pl1"; - scenes["s1/plots/p1/color_table/discrete"] = "true"; - - scenes["s1/image_prefix"] = image_file; - conduit::Node actions; // add the pipeline conduit::Node &add_pipelines = actions.append(); add_pipelines["action"] = "add_pipelines"; - add_pipelines["pipelines"] = pipelines; + conduit::Node &pipelines = add_pipelines["pipelines"]; // add the scenes conduit::Node &add_scenes= actions.append(); add_scenes["action"] = "add_scenes"; - add_scenes["scenes"] = scenes; + conduit::Node &scenes=add_scenes["scenes"]; + + // pipeline 1 + pipelines["pl1/f1/type"] = "add_domain_ids"; + conduit::Node ¶ms = pipelines["pl1/f1/params"]; + params["topology"] = "topo"; + params["output"] = "domain_id"; -// conduit::Node extracts; -// -// extracts["e1/type"] = "relay"; -// extracts["e1/params/path"] = output_file; -// extracts["e1/params/protocol"] = "blueprint/mesh/hdf5"; -// conduit::Node &add_ext= actions.append(); -// add_ext["action"] = "add_extracts"; -// add_ext["extracts"] = extracts; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "domain_id"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/plots/p1/color_table/discrete"] = "true"; + scenes["s1/image_prefix"] = image_file; // // Run Ascent // - Ascent ascent; Node ascent_opts; - ascent_opts["runtime/type"] = "ascent"; ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); ascent_opts["exceptions"] = "forward"; ascent.open(ascent_opts); diff --git a/src/tests/ascent/t_ascent_mpi_add_ranks.cpp b/src/tests/ascent/t_ascent_mpi_add_ranks.cpp index ec13241e7..691517d14 100644 --- a/src/tests/ascent/t_ascent_mpi_add_ranks.cpp +++ b/src/tests/ascent/t_ascent_mpi_add_ranks.cpp @@ -80,49 +80,34 @@ TEST(ascent_mpi_add_mpi_ranks, test_mpi_add_mpi_ranks) // // Create the actions. // + conduit::Node actions; + // add the pipeline + conduit::Node &add_pipelines = actions.append(); + add_pipelines["action"] = "add_pipelines"; + conduit::Node &pipelines = add_pipelines["pipelines"]; + // add the scenes + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; - conduit::Node pipelines; // pipeline 1 pipelines["pl1/f1/type"] = "add_mpi_ranks"; conduit::Node ¶ms = pipelines["pl1/f1/params"]; - params["topology"] = "topo"; - params["output"] = "ranks"; + params["topology"] = "topo"; + params["output"] = "rank"; - conduit::Node scenes; scenes["s1/plots/p1/type"] = "pseudocolor"; - scenes["s1/plots/p1/field"] = "ranks"; + scenes["s1/plots/p1/field"] = "rank"; scenes["s1/plots/p1/pipeline"] = "pl1"; scenes["s1/plots/p1/color_table/discrete"] = "true"; - scenes["s1/image_prefix"] = image_file; - conduit::Node actions; - // add the pipeline - conduit::Node &add_pipelines = actions.append(); - add_pipelines["action"] = "add_pipelines"; - add_pipelines["pipelines"] = pipelines; - // add the scenes - conduit::Node &add_scenes= actions.append(); - add_scenes["action"] = "add_scenes"; - add_scenes["scenes"] = scenes; - -// conduit::Node extracts; -// -// extracts["e1/type"] = "relay"; -// extracts["e1/params/path"] = output_file; -// extracts["e1/params/protocol"] = "blueprint/mesh/hdf5"; -// conduit::Node &add_ext= actions.append(); -// add_ext["action"] = "add_extracts"; -// add_ext["extracts"] = extracts; - // // Run Ascent // Ascent ascent; - Node ascent_opts; - ascent_opts["runtime/type"] = "ascent"; ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); ascent_opts["exceptions"] = "forward"; ascent.open(ascent_opts); diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 4d978d3cc..5678e6162 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -36,6 +36,8 @@ int NUM_DOMAINS = 8; //----------------------------------------------------------------------------- TEST(ascent_partition, test_mpi_partition_target_1) { + // TODO: Only run if we have hdf5 support + Node n; ascent::about(n); @@ -61,23 +63,14 @@ TEST(ascent_partition, test_mpi_partition_target_1) ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); string output_path = prepare_output_dir(); - std::ostringstream oss; - - oss << "tout_partition_target_1_mpi"; string output_base = conduit::utils::join_file_path(output_path, - oss.str()); - std::ostringstream ossjson; - ossjson << "tout_partition_target_1_mpi_json"; - string output_json = conduit::utils::join_file_path(output_base, - ossjson.str()); + "tout_partition_target_1_mpi"); + string output_root = output_base + ".cycle_000000.root"; + // remove existing file - if(utils::is_file(output_base)) + if(utils::is_file(output_root)) { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) - { - utils::remove_file(output_json); + utils::remove_file(output_root); } conduit::Node actions; @@ -88,7 +81,9 @@ TEST(ascent_partition, test_mpi_partition_target_1) conduit::Node &pipelines = add_pipelines["pipelines"]; pipelines["pl1/f1/type"] = "partition"; pipelines["pl1/f1/params/target"] = target; - + // pipelines["pl1/f2/type"] = "add_domain_ids"; + // pipelines["pl1/f2/params/output"] = "domain_id"; + //add the extract conduit::Node &add_extracts = actions.append(); add_extracts["action"] = "add_extracts"; @@ -96,109 +91,23 @@ TEST(ascent_partition, test_mpi_partition_target_1) extracts["e1/type"] = "relay"; extracts["e1/pipeline"] = "pl1"; extracts["e1/params/path"] = output_base; + extracts["e1/params/protocol"] = "hdf5"; - // - // Run Ascent - // - - Ascent ascent; - - Node ascent_opts; - ascent_opts["runtime"] = "ascent"; - ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); - ascent.open(ascent_opts); - ascent.publish(data); - ascent.execute(actions); - ascent.close(); - - //Two files in _output directory: - //tout_partition_multi_dom_serial - //tout_partition_multi_dom_serial_json - if(par_rank == 0) - { - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); - - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); - EXPECT_TRUE(num_doms == target); - } -} - -//----------------------------------------------------------------------------- -TEST(ascent_partition, test_mpi_partition_target_10) -{ - Node n; - ascent::about(n); + extracts["einput/type"] = "relay"; + extracts["einput/params/path"] = output_base + "_input"; + extracts["einput/params/protocol"] = "hdf5"; + // Add a scene that shows domain id // - //Set Up MPI - // - int par_rank; - int par_size; - MPI_Comm comm = MPI_COMM_WORLD; - MPI_Comm_rank(comm, &par_rank); - MPI_Comm_size(comm, &par_size); - - // - // Create an example mesh. - // - Node data, verify_info; - - // use spiral , with 7 domains - conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); - - EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - - ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); - - string output_path = prepare_output_dir(); - std::ostringstream oss; - - oss << "tout_partition_target_10_mpi"; - string output_base = conduit::utils::join_file_path(output_path, - oss.str()); - std::ostringstream ossjson; - ossjson << "tout_partition_taret_10_mpi_json"; - string output_json = conduit::utils::join_file_path(output_base, - ossjson.str()); - // remove existing file - if(utils::is_file(output_base)) - { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) - { - utils::remove_file(output_json); - } - - conduit::Node actions; - int target = 10; - // add the pipeline - conduit::Node &add_pipelines = actions.append(); - add_pipelines["action"] = "add_pipelines"; - conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f1/type"] = "partition"; - pipelines["pl1/f1/params/target"] = target; - - //add the extract - conduit::Node &add_extracts = actions.append(); - add_extracts["action"] = "add_extracts"; - conduit::Node &extracts = add_extracts["extracts"]; - extracts["e1/type"] = "relay"; - extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; - //add the scene - //conduit::Node &add_scenes= actions.append(); - //add_scenes["action"] = "add_scenes"; - //conduit::Node &scenes = add_scenes["scenes"]; - //scenes["s1/plots/p1/type"] = "pseudocolor"; - //scenes["s1/plots/p1/field"] = "dist"; - //scenes["s1/plots/p1/field"] = "rank"; - //scenes["s1/plots/p1/pipeline"] = "pl1"; - // scenes["s1/plots/p1/color_table/discrete"] = "true"; - //scenes["s1/image_prefix"] = "tout_mpi_partition"; + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "domain_id"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + //scenes["s1/plots/p1/color_table/discrete"] = "true"; + scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_1_"); // // Run Ascent @@ -207,27 +116,120 @@ TEST(ascent_partition, test_mpi_partition_target_10) Ascent ascent; Node ascent_opts; - ascent_opts["runtime"] = "ascent"; ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); ascent.open(ascent_opts); ascent.publish(data); ascent.execute(actions); ascent.close(); - //Two files in _output directory: - //tout_partition_multi_dom_serial - //tout_partition_multi_dom_serial_json if(par_rank == 0) { - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); + EXPECT_TRUE(conduit::utils::is_file(output_root)); + Node read_mesh; + conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); EXPECT_TRUE(num_doms == target); } } - +// +// // ---------------------------------------------------------- +// TEST(ascent_partition, test_mpi_partition_target_10) +// { +// // TODO: Only run if we have hdf5 support +// +// Node n; +// ascent::about(n); +// +// // +// //Set Up MPI +// // +// int par_rank; +// int par_size; +// MPI_Comm comm = MPI_COMM_WORLD; +// MPI_Comm_rank(comm, &par_rank); +// MPI_Comm_size(comm, &par_size); +// +// // +// // Create an example mesh. +// // +// Node data, verify_info; +// +// // use spiral , with 7 domains +// conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); +// +// EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); +// +// ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); +// +// string output_path = prepare_output_dir(); +// string output_base = conduit::utils::join_file_path(output_path, +// "tout_partition_target_10_mpi"); +// string output_root = output_base + ".cycle_000000.root"; +// +// // remove existing file +// if(utils::is_file(output_root)) +// { +// utils::remove_file(output_root); +// } +// +// conduit::Node actions; +// int target = 10; +// // add the pipeline +// conduit::Node &add_pipelines = actions.append(); +// add_pipelines["action"] = "add_pipelines"; +// conduit::Node &pipelines = add_pipelines["pipelines"]; +// pipelines["pl1/f1/type"] = "partition"; +// pipelines["pl1/f1/params/target"] = target; +// pipelines["pl1/f2/type"] = "add_domain_ids"; +// pipelines["pl1/f2/params/output"] = "domain_id"; +// +// //add the extract +// conduit::Node &add_extracts = actions.append(); +// add_extracts["action"] = "add_extracts"; +// conduit::Node &extracts = add_extracts["extracts"]; +// extracts["e1/type"] = "relay"; +// extracts["e1/pipeline"] = "pl1"; +// extracts["e1/params/path"] = output_base; +// extracts["e1/params/protocol"] = "hdf5"; +// +// // Add a scene that shows domain id +// // +// //add the scene +// conduit::Node &add_scenes= actions.append(); +// add_scenes["action"] = "add_scenes"; +// conduit::Node &scenes = add_scenes["scenes"]; +// scenes["s1/plots/p1/type"] = "pseudocolor"; +// scenes["s1/plots/p1/field"] = "domain_id"; +// scenes["s1/plots/p1/pipeline"] = "pl1"; +// //scenes["s1/plots/p1/color_table/discrete"] = "true"; +// scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_10_"); +// +// // +// // Run Ascent +// // +// +// Ascent ascent; +// +// Node ascent_opts; +// ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); +// ascent.open(ascent_opts); +// ascent.publish(data); +// ascent.execute(actions); +// ascent.close(); +// +// if(par_rank == 0) +// { +// EXPECT_TRUE(conduit::utils::is_file(output_root)); +// Node read_mesh; +// conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); +// +// int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); +// EXPECT_TRUE(num_doms == target); +// } +// +// } +// //----------------------------------------------------------------------------- //TEST(ascent_partition, test_mpi_partition_selection) diff --git a/src/tests/ascent/t_ascent_partition.cpp b/src/tests/ascent/t_ascent_partition.cpp index 6f5a49244..435ea92f5 100644 --- a/src/tests/ascent/t_ascent_partition.cpp +++ b/src/tests/ascent/t_ascent_partition.cpp @@ -48,23 +48,14 @@ TEST(ascent_partition, test_partition_2D_multi_dom) ASCENT_INFO("Testing blueprint partition of multi-domain mesh in serial"); string output_path = prepare_output_dir(); - std::ostringstream oss; - - oss << "tout_partition_multi_dom_serial"; string output_base = conduit::utils::join_file_path(output_path, - oss.str()); - std::ostringstream ossjson; - ossjson << "tout_partition_multi_dom_serial_json"; - string output_json = conduit::utils::join_file_path(output_base, - ossjson.str()); + "tout_partition_multi_dom_serial"); + string output_root = output_base + ".cycle_000000.root"; + // remove existing file - if(utils::is_file(output_base)) - { - utils::remove_file(output_base); - } - if(utils::is_file(output_json)) + if(utils::is_file(output_root)) { - utils::remove_file(output_json); + utils::remove_file(output_root); } conduit::Node actions; @@ -73,16 +64,27 @@ TEST(ascent_partition, test_partition_2D_multi_dom) conduit::Node &add_pipelines = actions.append(); add_pipelines["action"] = "add_pipelines"; conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f1/type"] = "partition"; - pipelines["pl1/f1/params/target"] = target; - + // pipelines["pl1/f1/type"] = "add_domain_ids"; + // pipelines["pl1/f1/params/output"] = "d_id_pre"; + + pipelines["pl1/f2/type"] = "partition"; + pipelines["pl1/f2/params/target"] = target; + + // pipelines["pl1/f3/type"] = "add_domain_ids"; + // pipelines["pl1/f3/params/output"] = "d_id_post"; + //add the extract conduit::Node &add_extracts = actions.append(); add_extracts["action"] = "add_extracts"; conduit::Node &extracts = add_extracts["extracts"]; - extracts["e1/type"] = "relay"; - extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; + extracts["eout/type"] = "relay"; + extracts["eout/pipeline"] = "pl1"; + extracts["eout/params/path"] = output_base; + extracts["eout/params/protocol"] = "hdf5"; + + extracts["einput/type"] = "relay"; + extracts["einput/params/path"] = output_base + "_input"; + extracts["einput/params/protocol"] = "hdf5"; // // Run Ascent @@ -97,14 +99,11 @@ TEST(ascent_partition, test_partition_2D_multi_dom) ascent.execute(actions); ascent.close(); - //Two files in _output directory: - //tout_partition_multi_dom_serial - //tout_partition_multi_dom_serial_json - EXPECT_TRUE(conduit::utils::is_file(output_base)); - Node read_csv; - conduit::relay::io::load(output_base,read_csv); + EXPECT_TRUE(conduit::utils::is_file(output_root)); + Node read_mesh; + conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); - int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); + int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); EXPECT_TRUE(num_doms == target); } From d5ffe410bfe0a8d01561df378b9a75dcc84997e5 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 3 Feb 2025 16:15:42 -0800 Subject: [PATCH 11/17] rework tests and correclty bottle bp partition output --- .../packages/conduit/package.py | 5 + .../ascent/runtimes/ascent_data_object.cpp | 2 +- .../ascent_runtime_blueprint_filters.cpp | 47 +-- .../ascent_runtime_vtkh_filters.cpp | 6 +- src/tests/ascent/t_ascent_mpi_partition.cpp | 298 ++++++++++-------- 5 files changed, 193 insertions(+), 165 deletions(-) diff --git a/scripts/uberenv_configs/packages/conduit/package.py b/scripts/uberenv_configs/packages/conduit/package.py index 365947b97..91b53df46 100644 --- a/scripts/uberenv_configs/packages/conduit/package.py +++ b/scripts/uberenv_configs/packages/conduit/package.py @@ -43,6 +43,10 @@ class Conduit(CMakePackage): # is to bridge any spack dependencies that are still using the name master version("master", branch="develop", submodules=True) # note: 2021-05-05 latest tagged release is now preferred instead of develop + version("0.9.3", sha256="45d5a4eccd0fc978d153d29c440c53c483b8f29dfcf78ddcc9aa15c59b257177") + version("0.9.2", sha256="45d5a4eccd0fc978d153d29c440c53c483b8f29dfcf78ddcc9aa15c59b257177") + version("0.9.1", sha256="a3f1168738dcf72f8ebf83299850301aaf56e803f40618fc1230a755d0d05363") + version("0.9.0", sha256="844e012400ab820967eef6cec15e1aa9a68cb05119d0c1f292d3c01630111a58") version("0.8.8", sha256="99811e9c464b6f841f52fcd47e982ae47cbb01cba334cff43eabe13eea58c0df") version("0.8.7", sha256="f3bf44d860783f4e0d61517c5e280c88144af37414569f4cf86e2d29b3ba5293") version("0.8.6", sha256="8ca5d37033143ed7181c7286dd25a3f6126ba0358889066f13a2b32f68fc647e") @@ -128,6 +132,7 @@ class Conduit(CMakePackage): extends("python", when="+python") depends_on("py-numpy", when="+python", type=("build", "run")) depends_on("py-mpi4py", when="+python+mpi", type=("build", "run")) + depends_on("py-pip", when="+python", type="build") ####################### # I/O Packages diff --git a/src/libs/ascent/runtimes/ascent_data_object.cpp b/src/libs/ascent/runtimes/ascent_data_object.cpp index 1177469cb..c856b7437 100644 --- a/src/libs/ascent/runtimes/ascent_data_object.cpp +++ b/src/libs/ascent/runtimes/ascent_data_object.cpp @@ -389,7 +389,7 @@ std::shared_ptr DataObject::as_node() { conduit::Node *out_data = new conduit::Node(); bool zero_copy = true; - VTKHDataAdapter::VTKHCollectionToBlueprintDataSet(m_vtkh.get(), *out_data, true); + VTKHDataAdapter::VTKHCollectionToBlueprintDataSet(m_vtkh.get(), *out_data, zero_copy); detail::add_metadata(*out_data); std::shared_ptr bp(out_data); diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index d8337a98e..3c918cc41 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #endif #if defined(ASCENT_VTKM_ENABLED) @@ -394,34 +395,14 @@ BlueprintPartition::execute() if(params().has_child("target")) { target = params()["target"].to_int32(); - n_options["target"] = target; } - if(params().has_child("mapping")) - { - n_options["mapping"] = params()["mapping"].to_int32(); - } - if(params().has_child("merge_tolerance")) - { - n_options["merge_tolerance"] = params()["merge_tolerance"].to_float64(); - } - if(params().has_child("original_element_ids")) - { - n_options["original_element_ids"] = params()["original_element_ids"].to_string(); - } - if(params().has_child("original_vertex_ids")) - { - n_options["original_vertex_ids"] = params()["original_vertex_ids"].to_string(); - } - if(params().has_child("selections")) - { - conduit::Node &selections = params()["selections"]; - n_options["selections"].append() = selections; - } - if(params().has_child("fields")) + + n_options.set_external(params()); + if(n_options.has_child("distributed")) { - n_options["fields"] = params()["fields"]; + n_options.remove_child("distributed"); } - + conduit::Node tmp; #ifdef ASCENT_MPI_ENABLED MPI_Comm mpi_comm = MPI_Comm_f2c(flow::Workspace::default_mpi_comm()); @@ -444,13 +425,17 @@ BlueprintPartition::execute() n_options, tmp); #endif - if(target == 1) - { - n_output->append().move(tmp); - } - else + + if(tmp.number_of_children() > 0) { - n_output->move(tmp); + if(target == 1) + { + n_output->append().move(tmp); + } + else + { + n_output->move(tmp); + } } DataObject *d_output = new DataObject(n_output); set_output(d_output); diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp index 1d0e8b213..e91ac51db 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_vtkh_filters.cpp @@ -1414,7 +1414,7 @@ VTKHAddRanks::execute() this->name(), collection, throw_error); - std::cerr << "topo_name: " << topo_name << std::endl; + if(topo_name == "") { // this creates a data object with an invalid source @@ -1517,7 +1517,7 @@ VTKHAddDomains::execute() this->name(), collection, throw_error); - std::cerr << "topo_name: " << topo_name << std::endl; + if(topo_name == "") { // this creates a data object with an invalid source @@ -1530,8 +1530,8 @@ VTKHAddDomains::execute() vtkh::DataSet &data = collection->dataset_by_topology(topo_name); data.AddDomainIdField(output_field); + new_coll->add(data, topo_name); - // re wrap in data object DataObject *res = new DataObject(new_coll); set_output(res); diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 5678e6162..83fd1b249 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -41,6 +41,13 @@ TEST(ascent_partition, test_mpi_partition_target_1) Node n; ascent::about(n); + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + return; + } + // //Set Up MPI // @@ -62,10 +69,19 @@ TEST(ascent_partition, test_mpi_partition_target_1) ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); - string output_path = prepare_output_dir(); + string output_path; + if(par_rank == 0) + { + output_path = prepare_output_dir(); + } + else + { + output_path = output_dir(); + } + string output_base = conduit::utils::join_file_path(output_path, "tout_partition_target_1_mpi"); - string output_root = output_base + ".cycle_000000.root"; + string output_root = output_base + "_result.cycle_000000.root"; // remove existing file if(utils::is_file(output_root)) @@ -79,10 +95,8 @@ TEST(ascent_partition, test_mpi_partition_target_1) conduit::Node &add_pipelines = actions.append(); add_pipelines["action"] = "add_pipelines"; conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f1/type"] = "partition"; - pipelines["pl1/f1/params/target"] = target; - // pipelines["pl1/f2/type"] = "add_domain_ids"; - // pipelines["pl1/f2/params/output"] = "domain_id"; + pipelines["pl1/f2/type"] = "partition"; + pipelines["pl1/f2/params/target"] = target; //add the extract conduit::Node &add_extracts = actions.append(); @@ -90,7 +104,7 @@ TEST(ascent_partition, test_mpi_partition_target_1) conduit::Node &extracts = add_extracts["extracts"]; extracts["e1/type"] = "relay"; extracts["e1/pipeline"] = "pl1"; - extracts["e1/params/path"] = output_base; + extracts["e1/params/path"] = output_base + "_result"; extracts["e1/params/protocol"] = "hdf5"; extracts["einput/type"] = "relay"; @@ -104,10 +118,9 @@ TEST(ascent_partition, test_mpi_partition_target_1) add_scenes["action"] = "add_scenes"; conduit::Node &scenes = add_scenes["scenes"]; scenes["s1/plots/p1/type"] = "pseudocolor"; - scenes["s1/plots/p1/field"] = "domain_id"; + scenes["s1/plots/p1/field"] = "rank"; scenes["s1/plots/p1/pipeline"] = "pl1"; - //scenes["s1/plots/p1/color_table/discrete"] = "true"; - scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_1_"); + scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_1_result_render"); // // Run Ascent @@ -122,6 +135,8 @@ TEST(ascent_partition, test_mpi_partition_target_1) ascent.execute(actions); ascent.close(); + MPI_Barrier(comm); + if(par_rank == 0) { EXPECT_TRUE(conduit::utils::is_file(output_root)); @@ -132,111 +147,134 @@ TEST(ascent_partition, test_mpi_partition_target_1) EXPECT_TRUE(num_doms == target); } } -// -// // ---------------------------------------------------------- -// TEST(ascent_partition, test_mpi_partition_target_10) -// { -// // TODO: Only run if we have hdf5 support -// -// Node n; -// ascent::about(n); -// -// // -// //Set Up MPI -// // -// int par_rank; -// int par_size; -// MPI_Comm comm = MPI_COMM_WORLD; -// MPI_Comm_rank(comm, &par_rank); -// MPI_Comm_size(comm, &par_size); -// -// // -// // Create an example mesh. -// // -// Node data, verify_info; -// -// // use spiral , with 7 domains -// conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); -// -// EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); -// -// ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); -// -// string output_path = prepare_output_dir(); -// string output_base = conduit::utils::join_file_path(output_path, -// "tout_partition_target_10_mpi"); -// string output_root = output_base + ".cycle_000000.root"; -// -// // remove existing file -// if(utils::is_file(output_root)) -// { -// utils::remove_file(output_root); -// } -// -// conduit::Node actions; -// int target = 10; -// // add the pipeline -// conduit::Node &add_pipelines = actions.append(); -// add_pipelines["action"] = "add_pipelines"; -// conduit::Node &pipelines = add_pipelines["pipelines"]; -// pipelines["pl1/f1/type"] = "partition"; -// pipelines["pl1/f1/params/target"] = target; -// pipelines["pl1/f2/type"] = "add_domain_ids"; -// pipelines["pl1/f2/params/output"] = "domain_id"; -// -// //add the extract -// conduit::Node &add_extracts = actions.append(); -// add_extracts["action"] = "add_extracts"; -// conduit::Node &extracts = add_extracts["extracts"]; -// extracts["e1/type"] = "relay"; -// extracts["e1/pipeline"] = "pl1"; -// extracts["e1/params/path"] = output_base; -// extracts["e1/params/protocol"] = "hdf5"; -// -// // Add a scene that shows domain id -// // -// //add the scene -// conduit::Node &add_scenes= actions.append(); -// add_scenes["action"] = "add_scenes"; -// conduit::Node &scenes = add_scenes["scenes"]; -// scenes["s1/plots/p1/type"] = "pseudocolor"; -// scenes["s1/plots/p1/field"] = "domain_id"; -// scenes["s1/plots/p1/pipeline"] = "pl1"; -// //scenes["s1/plots/p1/color_table/discrete"] = "true"; -// scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_10_"); -// -// // -// // Run Ascent -// // -// -// Ascent ascent; -// -// Node ascent_opts; -// ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); -// ascent.open(ascent_opts); -// ascent.publish(data); -// ascent.execute(actions); -// ascent.close(); -// -// if(par_rank == 0) -// { -// EXPECT_TRUE(conduit::utils::is_file(output_root)); -// Node read_mesh; -// conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); -// -// int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); -// EXPECT_TRUE(num_doms == target); -// } -// -// } -// -//----------------------------------------------------------------------------- -//TEST(ascent_partition, test_mpi_partition_selection) -//{ +// ---------------------------------------------------------- +TEST(ascent_partition, test_mpi_partition_target_10) +{ + // TODO: Only run if we have hdf5 support + + Node n; + ascent::about(n); + + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + return; + } + // + //Set Up MPI + // + int par_rank; + int par_size; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &par_rank); + MPI_Comm_size(comm, &par_size); + + // + // Create an example mesh. + // + Node data, verify_info; + + // use spiral , with 7 domains + conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); + + string output_path; + if(par_rank == 0) + { + output_path = prepare_output_dir(); + } + else + { + output_path = output_dir(); + } + + string output_base = conduit::utils::join_file_path(output_path, + "tout_partition_target_10_mpi"); + string output_root = output_base + "_result.cycle_000000.root"; + + if(par_rank == 0) + { + // remove existing file + if(utils::is_file(output_root)) + { + utils::remove_file(output_root); + } + } + + conduit::Node actions; + int target = 10; + // add the pipeline + conduit::Node &add_pipelines = actions.append(); + add_pipelines["action"] = "add_pipelines"; + conduit::Node &pipelines = add_pipelines["pipelines"]; + pipelines["pl1/f2/type"] = "partition"; + pipelines["pl1/f2/params/target"] = target; + + //add the extract + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + conduit::Node &extracts = add_extracts["extracts"]; + extracts["e1/type"] = "relay"; + extracts["e1/pipeline"] = "pl1"; + extracts["e1/params/path"] = output_base + "_result"; + extracts["e1/params/protocol"] = "hdf5"; + + extracts["einput/type"] = "relay"; + extracts["einput/params/path"] = output_base + "_input"; + extracts["einput/params/protocol"] = "hdf5"; + + // Add a scene that shows domain id + // + //add the scene + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "rank"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_10_result_render"); + + + // + // Run Ascent + // + + Ascent ascent; + + Node ascent_opts; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent_opts["exceptions"] = "forward"; + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + + MPI_Barrier(comm); + + if(par_rank == 0) + { + EXPECT_TRUE(conduit::utils::is_file(output_root)); + Node read_mesh; + conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); + EXPECT_TRUE(num_doms == target); + } + +} + + +// //----------------------------------------------------------------------------- +// TEST(ascent_partition, test_mpi_partition_selection) +// { // Node n; // ascent::about(n); -// + // // // //Set Up MPI // // @@ -245,29 +283,29 @@ TEST(ascent_partition, test_mpi_partition_target_1) // MPI_Comm comm = MPI_COMM_WORLD; // MPI_Comm_rank(comm, &par_rank); // MPI_Comm_size(comm, &par_size); -// + // // // // Create an example mesh. // // // Node data, verify_info; -// + // // use spiral , with 7 domains // conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); -// + // EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); -// + // ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); -// + // string output_path = prepare_output_dir(); // std::ostringstream oss; -// + // oss << "tout_partition_selection_mpi"; // string output_base = conduit::utils::join_file_path(output_path, // oss.str()); // std::ostringstream ossjson; // ossjson << "tout_partition_selection_mpi_json"; // string output_json = conduit::utils::join_file_path(output_base, -// ossjson.str()); +// ossjson.str()); // // remove existing file // if(utils::is_file(output_base)) // { @@ -277,7 +315,7 @@ TEST(ascent_partition, test_mpi_partition_target_1) // { // utils::remove_file(output_json); // } -// + // conduit::Node actions; // int target = 1; // // add the pipeline @@ -288,7 +326,7 @@ TEST(ascent_partition, test_mpi_partition_target_1) // pipelines["pl1/f1/params/selections/type"] = "field"; // pipelines["pl1/f1/params/selections/field"] = "dist"; // //float start[2] = {0,0}; -// + // //add the extract // conduit::Node &add_extracts = actions.append(); // add_extracts["action"] = "add_extracts"; @@ -296,7 +334,7 @@ TEST(ascent_partition, test_mpi_partition_target_1) // extracts["e1/type"] = "relay"; // extracts["e1/pipeline"] = "pl1"; // extracts["e1/params/path"] = output_base; -// + // //add the scene // conduit::Node &add_scenes= actions.append(); // add_scenes["action"] = "add_scenes"; @@ -305,13 +343,13 @@ TEST(ascent_partition, test_mpi_partition_target_1) // scenes["s1/plots/p1/field"] = "dist"; // scenes["s1/plots/p1/pipeline"] = "pl1"; // scenes["s1/image_prefix"] = output_base; -// + // // // // Run Ascent // // -// + // Ascent ascent; -// + // Node ascent_opts; // ascent_opts["runtime"] = "ascent"; // ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); @@ -319,7 +357,7 @@ TEST(ascent_partition, test_mpi_partition_target_1) // ascent.publish(data); // ascent.execute(actions); // ascent.close(); -// + // //Two files in _output directory: // //tout_partition_multi_dom_serial // //tout_partition_multi_dom_serial_json @@ -328,13 +366,13 @@ TEST(ascent_partition, test_mpi_partition_target_1) // EXPECT_TRUE(conduit::utils::is_file(output_base)); // Node read_csv; // conduit::relay::io::load(output_base,read_csv); -// + // int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); // EXPECT_TRUE(num_doms == target); // } -//} -// -// +// } + + //----------------------------------------------------------------------------- From 5055cd28626a93a3e69ea3715e9033fe1bc8f439 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 3 Feb 2025 16:49:43 -0800 Subject: [PATCH 12/17] fix docs and test --- src/docs/sphinx/Actions/Pipelines.rst | 10 +- .../ascent_runtime_blueprint_filters.cpp | 10 +- src/tests/ascent/t_ascent_mpi_partition.cpp | 225 +++++++++--------- 3 files changed, 129 insertions(+), 116 deletions(-) diff --git a/src/docs/sphinx/Actions/Pipelines.rst b/src/docs/sphinx/Actions/Pipelines.rst index 4dc66cdfa..29d75c7c4 100644 --- a/src/docs/sphinx/Actions/Pipelines.rst +++ b/src/docs/sphinx/Actions/Pipelines.rst @@ -1098,14 +1098,14 @@ Funtionality and further descriptions of optional parameters can be found in the pipelines["pl1/f1/type"] = "partition"; //params optional pipelines["pl1/f1/params/target"] = 1; - const char* fields[3] = {"pink", "pony", "club"}; - pipelines["pl1/f1/params/fields"].set(fields,3); + pipelines["pl1/f1/params/fields"].append() = "pink"; + pipelines["pl1/f1/params/fields"].append() = "pony"; + pipelines["pl1/f1/params/fields"].append() = "clib"; pipelines["pl1/f1/params/merge_tolerance"] = 0.000001; - pipelines["pl1/f1/params/mapping"] = 0;//turns off; on by default + pipelines["pl1/f1/params/mapping"] = 0; //turns off; on by default pipelines["pl1/f1/params/build_adjsets"] = 1; - - + In parallel, the Partition filter will make an effort to redistribute data across MPI diff --git a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp index 3c918cc41..d6957545d 100644 --- a/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp +++ b/src/libs/ascent/runtimes/flow_filters/ascent_runtime_blueprint_filters.cpp @@ -355,16 +355,18 @@ BlueprintPartition::verify_params(const conduit::Node ¶ms, valid_paths.push_back("selections/end"); valid_paths.push_back("selections/elements"); valid_paths.push_back("selections/ranges"); - valid_paths.push_back("fields"); + valid_paths.push_back("selections/field"); valid_paths.push_back("mapping"); valid_paths.push_back("merge_tolerance"); valid_paths.push_back("build_adjsets"); valid_paths.push_back("original_element_ids"); valid_paths.push_back("original_vertex_ids"); valid_paths.push_back("distributed"); - - std::string surprises = surprise_check(valid_paths, params); - + + std::vector ingore_paths = {"fields"}; + + std::string surprises = surprise_check(valid_paths,ingore_paths, params); + if(surprises != "") { res = false; diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 83fd1b249..8fee99ebf 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -95,8 +95,8 @@ TEST(ascent_partition, test_mpi_partition_target_1) conduit::Node &add_pipelines = actions.append(); add_pipelines["action"] = "add_pipelines"; conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f2/type"] = "partition"; - pipelines["pl1/f2/params/target"] = target; + pipelines["pl1/f1/type"] = "partition"; + pipelines["pl1/f1/params/target"] = target; //add the extract conduit::Node &add_extracts = actions.append(); @@ -212,8 +212,8 @@ TEST(ascent_partition, test_mpi_partition_target_10) conduit::Node &add_pipelines = actions.append(); add_pipelines["action"] = "add_pipelines"; conduit::Node &pipelines = add_pipelines["pipelines"]; - pipelines["pl1/f2/type"] = "partition"; - pipelines["pl1/f2/params/target"] = target; + pipelines["pl1/f1/type"] = "partition"; + pipelines["pl1/f1/params/target"] = target; //add the extract conduit::Node &add_extracts = actions.append(); @@ -239,7 +239,6 @@ TEST(ascent_partition, test_mpi_partition_target_10) scenes["s1/plots/p1/pipeline"] = "pl1"; scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_mpi_partition_target_10_result_render"); - // // Run Ascent // @@ -269,110 +268,122 @@ TEST(ascent_partition, test_mpi_partition_target_10) } -// //----------------------------------------------------------------------------- -// TEST(ascent_partition, test_mpi_partition_selection) -// { -// Node n; -// ascent::about(n); - -// // -// //Set Up MPI -// // -// int par_rank; -// int par_size; -// MPI_Comm comm = MPI_COMM_WORLD; -// MPI_Comm_rank(comm, &par_rank); -// MPI_Comm_size(comm, &par_size); - -// // -// // Create an example mesh. -// // -// Node data, verify_info; - -// // use spiral , with 7 domains -// conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); - -// EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); - -// ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); - -// string output_path = prepare_output_dir(); -// std::ostringstream oss; - -// oss << "tout_partition_selection_mpi"; -// string output_base = conduit::utils::join_file_path(output_path, -// oss.str()); -// std::ostringstream ossjson; -// ossjson << "tout_partition_selection_mpi_json"; -// string output_json = conduit::utils::join_file_path(output_base, -// ossjson.str()); -// // remove existing file -// if(utils::is_file(output_base)) -// { -// utils::remove_file(output_base); -// } -// if(utils::is_file(output_json)) -// { -// utils::remove_file(output_json); -// } - -// conduit::Node actions; -// int target = 1; -// // add the pipeline -// conduit::Node &add_pipelines = actions.append(); -// add_pipelines["action"] = "add_pipelines"; -// conduit::Node &pipelines = add_pipelines["pipelines"]; -// pipelines["pl1/f1/type"] = "partition"; -// pipelines["pl1/f1/params/selections/type"] = "field"; -// pipelines["pl1/f1/params/selections/field"] = "dist"; -// //float start[2] = {0,0}; - -// //add the extract -// conduit::Node &add_extracts = actions.append(); -// add_extracts["action"] = "add_extracts"; -// conduit::Node &extracts = add_extracts["extracts"]; -// extracts["e1/type"] = "relay"; -// extracts["e1/pipeline"] = "pl1"; -// extracts["e1/params/path"] = output_base; - -// //add the scene -// conduit::Node &add_scenes= actions.append(); -// add_scenes["action"] = "add_scenes"; -// conduit::Node &scenes = add_scenes["scenes"]; -// scenes["s1/plots/p1/type"] = "pseudocolor"; -// scenes["s1/plots/p1/field"] = "dist"; -// scenes["s1/plots/p1/pipeline"] = "pl1"; -// scenes["s1/image_prefix"] = output_base; - -// // -// // Run Ascent -// // - -// Ascent ascent; - -// Node ascent_opts; -// ascent_opts["runtime"] = "ascent"; -// ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); -// ascent.open(ascent_opts); -// ascent.publish(data); -// ascent.execute(actions); -// ascent.close(); - -// //Two files in _output directory: -// //tout_partition_multi_dom_serial -// //tout_partition_multi_dom_serial_json -// if(par_rank == 0) -// { -// EXPECT_TRUE(conduit::utils::is_file(output_base)); -// Node read_csv; -// conduit::relay::io::load(output_base,read_csv); - -// int num_doms = conduit::blueprint::mesh::number_of_domains(read_csv); -// EXPECT_TRUE(num_doms == target); -// } -// } +// ---------------------------------------------------------- +TEST(ascent_partition, test_mpi_partition_fields) +{ + Node n; + ascent::about(n); + + // only run this test if ascent was built with vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + { + ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + return; + } + // + //Set Up MPI + // + int par_rank; + int par_size; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Comm_rank(comm, &par_rank); + MPI_Comm_size(comm, &par_size); + + // + // Create an example mesh. + // + Node data, verify_info; + + // use spiral , with 7 domains + conduit::blueprint::mpi::mesh::examples::spiral_round_robin(NUM_DOMAINS,data,comm); + + EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info)); + + ASCENT_INFO("Testing blueprint partition of multi-domain mesh with MPI"); + + string output_path; + if(par_rank == 0) + { + output_path = prepare_output_dir(); + } + else + { + output_path = output_dir(); + } + + string output_base = conduit::utils::join_file_path(output_path, + "tout_partition_target_1_fields"); + string output_root = output_base + "_result.cycle_000000.root"; + + if(par_rank == 0) + { + // remove existing file + if(utils::is_file(output_root)) + { + utils::remove_file(output_root); + } + } + + conduit::Node actions; + int target = 1; + // add the pipeline + conduit::Node &add_pipelines = actions.append(); + add_pipelines["action"] = "add_pipelines"; + conduit::Node &pipelines = add_pipelines["pipelines"]; + pipelines["pl1/f1/type"] = "partition"; + pipelines["pl1/f1/params/target"] = target; + pipelines["pl1/f1/params/fields"].append()="dist"; + + //add the extract + conduit::Node &add_extracts = actions.append(); + add_extracts["action"] = "add_extracts"; + conduit::Node &extracts = add_extracts["extracts"]; + extracts["e1/type"] = "relay"; + extracts["e1/pipeline"] = "pl1"; + extracts["e1/params/path"] = output_base + "_result"; + extracts["e1/params/protocol"] = "hdf5"; + + extracts["einput/type"] = "relay"; + extracts["einput/params/path"] = output_base + "_input"; + extracts["einput/params/protocol"] = "hdf5"; + + // Add a scene that shows domain id + // + //add the scene + conduit::Node &add_scenes= actions.append(); + add_scenes["action"] = "add_scenes"; + conduit::Node &scenes = add_scenes["scenes"]; + scenes["s1/plots/p1/type"] = "pseudocolor"; + scenes["s1/plots/p1/field"] = "dist"; + scenes["s1/plots/p1/pipeline"] = "pl1"; + scenes["s1/image_prefix"] = conduit::utils::join_file_path(output_path, "tout_partition_target_1_fields_result_render"); + + // + // Run Ascent + // + + Ascent ascent; + Node ascent_opts; + ascent_opts["mpi_comm"] = MPI_Comm_c2f(comm); + ascent.open(ascent_opts); + ascent.publish(data); + ascent.execute(actions); + ascent.close(); + MPI_Barrier(comm); + + if(par_rank == 0) + { + EXPECT_TRUE(conduit::utils::is_file(output_root)); + Node read_mesh; + conduit::relay::io::blueprint::load_mesh(output_root,read_mesh); + + int num_doms = conduit::blueprint::mesh::number_of_domains(read_mesh); + EXPECT_TRUE(num_doms == target); + } + +} //----------------------------------------------------------------------------- From 4e2c64c7f335c7f2d92b1e68f5bd1d96ea8efe6c Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 3 Feb 2025 16:52:48 -0800 Subject: [PATCH 13/17] club not clib --- src/docs/sphinx/Actions/Pipelines.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/sphinx/Actions/Pipelines.rst b/src/docs/sphinx/Actions/Pipelines.rst index 29d75c7c4..3ab1f535e 100644 --- a/src/docs/sphinx/Actions/Pipelines.rst +++ b/src/docs/sphinx/Actions/Pipelines.rst @@ -1100,7 +1100,7 @@ Funtionality and further descriptions of optional parameters can be found in the pipelines["pl1/f1/params/target"] = 1; pipelines["pl1/f1/params/fields"].append() = "pink"; pipelines["pl1/f1/params/fields"].append() = "pony"; - pipelines["pl1/f1/params/fields"].append() = "clib"; + pipelines["pl1/f1/params/fields"].append() = "club"; pipelines["pl1/f1/params/merge_tolerance"] = 0.000001; pipelines["pl1/f1/params/mapping"] = 0; //turns off; on by default pipelines["pl1/f1/params/build_adjsets"] = 1; From 27e55418d70920733ef6fb53c0b8349817ee4c6e Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Mon, 3 Feb 2025 18:03:15 -0800 Subject: [PATCH 14/17] try yaml for basic test --- src/tests/ascent/t_ascent_mpi_partition.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 8fee99ebf..6f885cb5e 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -36,8 +36,6 @@ int NUM_DOMAINS = 8; //----------------------------------------------------------------------------- TEST(ascent_partition, test_mpi_partition_target_1) { - // TODO: Only run if we have hdf5 support - Node n; ascent::about(n); @@ -105,11 +103,11 @@ TEST(ascent_partition, test_mpi_partition_target_1) extracts["e1/type"] = "relay"; extracts["e1/pipeline"] = "pl1"; extracts["e1/params/path"] = output_base + "_result"; - extracts["e1/params/protocol"] = "hdf5"; + extracts["e1/params/protocol"] = "blueprint/mesh/yaml"; extracts["einput/type"] = "relay"; extracts["einput/params/path"] = output_base + "_input"; - extracts["einput/params/protocol"] = "hdf5"; + extracts["einput/params/protocol"] = "blueprint/mesh/yaml"; // Add a scene that shows domain id // From e30f4f6681843b9f8638cd03ccaf797ed511c52b Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Tue, 4 Feb 2025 08:22:02 -0800 Subject: [PATCH 15/17] yaml for simplest test --- src/tests/ascent/t_ascent_partition.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tests/ascent/t_ascent_partition.cpp b/src/tests/ascent/t_ascent_partition.cpp index 435ea92f5..cd2e63233 100644 --- a/src/tests/ascent/t_ascent_partition.cpp +++ b/src/tests/ascent/t_ascent_partition.cpp @@ -32,9 +32,6 @@ using namespace ascent; //----------------------------------------------------------------------------- TEST(ascent_partition, test_partition_2D_multi_dom) { - Node n; - ascent::about(n); - // // Create an example mesh. // @@ -80,11 +77,11 @@ TEST(ascent_partition, test_partition_2D_multi_dom) extracts["eout/type"] = "relay"; extracts["eout/pipeline"] = "pl1"; extracts["eout/params/path"] = output_base; - extracts["eout/params/protocol"] = "hdf5"; + extracts["eout/params/protocol"] = "blueprint/mesh/yaml"; extracts["einput/type"] = "relay"; extracts["einput/params/path"] = output_base + "_input"; - extracts["einput/params/protocol"] = "hdf5"; + extracts["einput/params/protocol"] = "blueprint/mesh/yaml"; // // Run Ascent From 4326f259ef77c3f85f4d2c66bf2914fcbb09cdbd Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Tue, 4 Feb 2025 14:33:51 -0800 Subject: [PATCH 16/17] better guards --- src/tests/ascent/t_ascent_mpi_partition.cpp | 29 ++++++++++++--------- src/tests/ascent/t_ascent_partition.cpp | 11 ++++++++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/tests/ascent/t_ascent_mpi_partition.cpp b/src/tests/ascent/t_ascent_mpi_partition.cpp index 6f885cb5e..97a89eee6 100644 --- a/src/tests/ascent/t_ascent_mpi_partition.cpp +++ b/src/tests/ascent/t_ascent_mpi_partition.cpp @@ -39,10 +39,11 @@ TEST(ascent_partition, test_mpi_partition_target_1) Node n; ascent::about(n); - // only run this test if ascent was built with vtkm support - if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + // only run this test if ascent was built with hdf5 + vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled" || + n["runtimes/ascent/hdf5/status"].as_string() == "disabled" ) { - ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + ASCENT_INFO("Ascent Rendering and/or HDF5 support are disabled, skipping test"); return; } @@ -103,11 +104,11 @@ TEST(ascent_partition, test_mpi_partition_target_1) extracts["e1/type"] = "relay"; extracts["e1/pipeline"] = "pl1"; extracts["e1/params/path"] = output_base + "_result"; - extracts["e1/params/protocol"] = "blueprint/mesh/yaml"; + extracts["e1/params/protocol"] = "hdf5"; extracts["einput/type"] = "relay"; extracts["einput/params/path"] = output_base + "_input"; - extracts["einput/params/protocol"] = "blueprint/mesh/yaml"; + extracts["einput/params/protocol"] = "hdf5"; // Add a scene that shows domain id // @@ -149,17 +150,17 @@ TEST(ascent_partition, test_mpi_partition_target_1) // ---------------------------------------------------------- TEST(ascent_partition, test_mpi_partition_target_10) { - // TODO: Only run if we have hdf5 support - Node n; ascent::about(n); - // only run this test if ascent was built with vtkm support - if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + // only run this test if ascent was built with hdf5 + vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled" || + n["runtimes/ascent/hdf5/status"].as_string() == "disabled" ) { - ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + ASCENT_INFO("Ascent Rendering and/or HDF5 support are disabled, skipping test"); return; } + // //Set Up MPI // @@ -272,12 +273,14 @@ TEST(ascent_partition, test_mpi_partition_fields) Node n; ascent::about(n); - // only run this test if ascent was built with vtkm support - if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled") + // only run this test if ascent was built with hdf5 + vtkm support + if(n["runtimes/ascent/vtkm/status"].as_string() == "disabled" || + n["runtimes/ascent/hdf5/status"].as_string() == "disabled" ) { - ASCENT_INFO("Ascent Rendering support disabled, skipping test"); + ASCENT_INFO("Ascent Rendering and/or HDF5 support are disabled, skipping test"); return; } + // //Set Up MPI // diff --git a/src/tests/ascent/t_ascent_partition.cpp b/src/tests/ascent/t_ascent_partition.cpp index cd2e63233..ccb0760d9 100644 --- a/src/tests/ascent/t_ascent_partition.cpp +++ b/src/tests/ascent/t_ascent_partition.cpp @@ -32,6 +32,17 @@ using namespace ascent; //----------------------------------------------------------------------------- TEST(ascent_partition, test_partition_2D_multi_dom) { + Node n; + ascent::about(n); + + // only run this test if ascent was built with hdf5 \support + if(n["runtimes/ascent/hdf5/status"].as_string() == "disabled" ) + { + ASCENT_INFO("Ascent HDF5 support is disabled, skipping test"); + return; + } + + // // Create an example mesh. // From 7ef283c29a04979786f8e9031926ffc36b88e1d3 Mon Sep 17 00:00:00 2001 From: Cyrus Harrison Date: Tue, 4 Feb 2025 17:33:28 -0800 Subject: [PATCH 17/17] test --- src/tests/ascent/t_ascent_partition.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tests/ascent/t_ascent_partition.cpp b/src/tests/ascent/t_ascent_partition.cpp index ccb0760d9..7733906ae 100644 --- a/src/tests/ascent/t_ascent_partition.cpp +++ b/src/tests/ascent/t_ascent_partition.cpp @@ -55,9 +55,11 @@ TEST(ascent_partition, test_partition_2D_multi_dom) ASCENT_INFO("Testing blueprint partition of multi-domain mesh in serial"); - string output_path = prepare_output_dir(); - string output_base = conduit::utils::join_file_path(output_path, - "tout_partition_multi_dom_serial"); + // work around for windows roundtrip conduit read bug + // string output_path = prepare_output_dir(); + // string output_base = conduit::utils::join_file_path(output_path, + // "tout_partition_multi_dom_serial"); + string output_base = "tout_partition_multi_dom_serial"; string output_root = output_base + ".cycle_000000.root"; // remove existing file