text: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  // Copyright (c) Lawrence Livermore National Security, LLC and other Ascent
  // Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
  // other details. No copyright assignment is required to contribute to Ascent.
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  
  //-----------------------------------------------------------------------------
  ///
  /// file: t_ascent_relay.cpp
  ///
  //-----------------------------------------------------------------------------
  
  
  #include "gtest/gtest.h"
  
  #include <ascent.hpp>
  
  #include <iostream>
  #include <math.h>
  
  #include <conduit_blueprint.hpp>
  #include <conduit_relay.hpp>
  
  #include "t_config.hpp"
  #include "t_utils.hpp"
  
  
  using namespace std;
  using namespace conduit;
  using namespace ascent;
  
  
  index_t EXAMPLE_MESH_SIDE_DIM = 20;
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  }
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_hdf5_2)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "hdf5";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  
  }
  
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_json)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial (json)");
  
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_json");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/json";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
      actions.save("for_chris.yaml");
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  }
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_json_2)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial (json)");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_json_2");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "json";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
      actions.save("for_chris.yaml");
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  }
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_yaml)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial (yaml)");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_yaml");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_file);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/yaml";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  }
  
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_yaml_2)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial (yaml)");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_yaml_2");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "yaml";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      // make sure the expected root file exists
      EXPECT_TRUE(conduit::utils::is_file(output_root));
  }
  
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_field_select_nestsets)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      blueprint::mesh::examples::julia_nestsets_complex(EXAMPLE_MESH_SIDE_DIM,
                                                        EXAMPLE_MESH_SIDE_DIM,
                                                        -2.0,  2.0, // x range
                                                        -2.0,  2.0, // y range
                                                        0.285, 0.01, // c value
                                                        1, // amr levels
                                                        data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial with nestsets");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_nestsets");
      string output_root = output_file + ".cycle_000100.root";
  
      // remove old images before rendering
      remove_test_image(output_root);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
      extracts["e1/params/fields"].append() = "iters";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
  }
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_subselection_no_data)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_subset_no_data");
  
      // remove old images before rendering
      remove_test_image(output_file);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
      extracts["e1/params/fields"].append() = "bananas";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      ascent_opts["runtime"] = "ascent";
      ascent_opts["exceptions"] = "forward";
      ascent.open(ascent_opts);
      ascent.publish(data);
      bool exception = false;
      try
      {
        ascent.execute(actions);
      }
      catch(const conduit::Error &e)
      {
        exception = true;
        std::cout<<e.what()<<"\n";
      }
      ascent.close();
      ASSERT_TRUE(exception);
  }
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_subselection)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_serial_extract_subset");
  
      // remove old images before rendering
      remove_test_image(output_file);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
      extracts["e1/params/fields"].append() = "braid";
      extracts["e1/params/fields"].append() = "radial";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  
      std::string msg = "An example of using a relay extract to save a subset of the data.";
      ASCENT_ACTIONS_DUMP(actions,output_file,msg);
  
  }
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_no_cycle)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
      conduit::blueprint::mesh::examples::braid("hexs",
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                EXAMPLE_MESH_SIDE_DIM,
                                                data);
  
      conduit::Node state = data["state"];
      data["state"].reset();
      data["state/time"] = state["time"];
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_no_cycle");
  
      // remove old images before rendering
      remove_test_image(output_file);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
      extracts["e1/params/fields"].append() = "braid";
      extracts["e1/params/fields"].append() = "radial";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
  }
  
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_bp_num_files)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
      Node data, verify_info;
  
      // use spiral , with 7 domains
      conduit::blueprint::mesh::examples::spiral(7,data);
  
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract num_files option in serial");
  
      string output_path = prepare_output_dir();
      std::ostringstream oss;
  
      // lets try with -1 to 8 files.
  
      // nfiles less than 1 should trigger default case
      // (n output files = n domains)
      for(int nfiles=-1; nfiles < 9; nfiles++)
      {
          std::cout << "test nfiles = " << nfiles << std::endl;
          oss.str("");
          oss << "tout_relay_serial_extract_nfiles_" << nfiles;
  
          string output_base = conduit::utils::join_file_path(output_path,
                                                              oss.str());
  
          string output_dir  = output_base + ".cycle_000000";
          string output_root = output_base + ".cycle_000000.root";
  
          // remove existing directory
          utils::remove_directory(output_dir);
          utils::remove_directory(output_root);
  
          conduit::Node actions;
          // add the extracts
          conduit::Node &add_extracts = actions.append();
          add_extracts["action"] = "add_extracts";
          conduit::Node &extracts = add_extracts["extracts"];
  
          extracts["e1/type"]  = "relay";
          extracts["e1/params/path"] = output_base;
          extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
          extracts["e1/params/num_files"] =  nfiles;
  
          //
          // Run Ascent
          //
  
          Ascent ascent;
  
          Node ascent_opts;
          // we use the mpi handle provided by the fortran interface
          // since it is simply an integer
          ascent_opts["runtime"] = "ascent";
          ascent.open(ascent_opts);
          ascent.publish(data);
          ascent.execute(actions);
          ascent.close();
  
          // count the files
          //  file_%06llu.{protocol}:/domain_%06llu/...
          int nfiles_to_check = nfiles;
          if(nfiles <=0 || nfiles == 8) // expect 7 files (one per domain)
          {
              nfiles_to_check = 7;
          }
  
          EXPECT_TRUE(conduit::utils::is_directory(output_dir));
          EXPECT_TRUE(conduit::utils::is_file(output_root));
  
          char fmt_buff[64] = {0};
          for(int i=0;i<nfiles_to_check;i++)
          {
  
              std::string fprefix = "file_";
              if(nfiles_to_check == 7)
              {
                  // in the n domains == n files case, the file prefix is
                  // domain_
                  fprefix = "domain_";
              }
              snprintf(fmt_buff, sizeof(fmt_buff), "%06d",i);
              oss.str("");
              oss << conduit::utils::join_file_path(output_base + ".cycle_000000",
                                                    fprefix)
                  << fmt_buff << ".hdf5";
              std::string fcheck = oss.str();
              std::cout << " checking: " << fcheck << std::endl;
              EXPECT_TRUE(conduit::utils::is_file(fcheck));
          }
      }
  }
  
  
  //-----------------------------------------------------------------------------
  TEST(ascent_relay, test_relay_sparse_topos)
  {
      Node n;
      ascent::about(n);
  
      //
      // Create an example mesh.
      //
  
      Node data;
      ostringstream oss;
      
      // three domains with different topos
      for(index_t d =0; d<4; d++)
      {
          std::cout << "i = " << d << std::endl;
          Node &mesh = data.append();
          oss.str("");
          oss << "my_coords_" << d ;
          std::string c_name = oss.str();
  
          oss.str("");
          oss << "my_topo_" << d ;
          std::string t_name = oss.str();
  
          oss.str("");
          oss << "my_field_" << d ;
          std::string f_name = oss.str();
  
          // create the coordinate set
          mesh["coordsets"][c_name]["type"] = "uniform";
          mesh["coordsets"][c_name]["dims/i"] = 3;
          mesh["coordsets"][c_name]["dims/j"] = 3;
          // add origin and spacing to the coordset (optional)
          mesh["coordsets"][c_name]["origin/x"] = -10.0;
          mesh["coordsets"][c_name]["origin/y"] = -10.0;
          mesh["coordsets"][c_name]["spacing/dx"] = 10.0;
          mesh["coordsets"][c_name]["spacing/dy"] = 10.0;
  
          // add the topology
          // this case is simple b/c it's implicitly derived from the coordinate set
          mesh["topologies"][t_name]["type"] = "uniform";
          // reference the coordinate set by name
          mesh["topologies"][t_name]["coordset"] = c_name;
  
          // add a simple element-associated field 
          mesh["fields"][f_name]["association"] =  "element";
          // reference the topology this field is defined on by name
          mesh["fields"][f_name]["topology"] =  t_name;
          // set the field values, for this case we have 4 elements
          mesh["fields"][f_name]["values"].set(DataType::float64(4));
  
          float64 *ele_vals_ptr = mesh["fields"][f_name]["values"].value();
  
          for(int i=0;i<4;i++)
          {
              ele_vals_ptr[i] = float64(d);
          }
      }
      
      data.print();
  
      Node verify_info;
      EXPECT_TRUE(conduit::blueprint::mesh::verify(data,verify_info));
  
      ASCENT_INFO("Testing relay extract in serial");
  
      string output_path = prepare_output_dir();
      string output_file = conduit::utils::join_file_path(output_path,"tout_relay_sparse_topos");
  
      // remove old images before rendering
      remove_test_image(output_file);
  
      conduit::Node extracts;
      extracts["e1/type"]  = "relay";
  
      extracts["e1/params/path"] = output_file;
      extracts["e1/params/protocol"] = "blueprint/mesh/hdf5";
  
      conduit::Node actions;
      // add the extracts
      conduit::Node &add_extracts = actions.append();
      add_extracts["action"] = "add_extracts";
      add_extracts["extracts"] = extracts;
  
      conduit::Node &execute  = actions.append();
      execute["action"] = "execute";
  
  
      //
      // Run Ascent
      //
  
      Ascent ascent;
  
      Node ascent_opts;
      // we use the mpi handle provided by the fortran interface
      // since it is simply an integer
      ascent_opts["runtime"] = "ascent";
      ascent.open(ascent_opts);
      ascent.publish(data);
      ascent.execute(actions);
      ascent.close();
      
      
      Node n_root;
      conduit::relay::io::load(output_file + ".cycle_000000.root","hdf5",n_root);
      n_root.print();
  }
  
  
  
  
  //-----------------------------------------------------------------------------
  int main(int argc, char* argv[])
  {
      int result = 0;
  
      ::testing::InitGoogleTest(&argc, argv);
  
      // allow override of the data size via the command line
      if(argc == 2)
      {
          EXAMPLE_MESH_SIDE_DIM = atoi(argv[1]);
      }
  
      result = RUN_ALL_TESTS();
      return result;
  }
  
  
  