diff --git a/tests/unit-tests/CMakeLists.txt b/tests/unit-tests/CMakeLists.txt index 9e6af955..f4a71100 100644 --- a/tests/unit-tests/CMakeLists.txt +++ b/tests/unit-tests/CMakeLists.txt @@ -233,12 +233,12 @@ target_link_libraries( ) add_executable( - displacement_newmark_elastic_tests - displacement_tests/Newmark/elastic/newmark_tests.cpp + displacement_newmark_tests + displacement_tests/Newmark/newmark_tests.cpp ) target_link_libraries( - displacement_newmark_elastic_tests + displacement_newmark_tests quadrature mesh material_class @@ -252,25 +252,45 @@ target_link_libraries( -lpthread -lm ) -add_executable( - displacement_newmark_acoustic_tests - displacement_tests/Newmark/acoustic/newmark_tests.cpp -) - -target_link_libraries( - displacement_newmark_acoustic_tests - quadrature - mesh - material_class - yaml-cpp - kokkos_environment - mpi_environment - compute - parameter_reader - compare_arrays - timescheme - -lpthread -lm -) +# add_executable( +# displacement_newmark_elastic_tests +# displacement_tests/Newmark/elastic/newmark_tests.cpp +# ) + +# target_link_libraries( +# displacement_newmark_elastic_tests +# quadrature +# mesh +# material_class +# yaml-cpp +# kokkos_environment +# mpi_environment +# compute +# parameter_reader +# compare_arrays +# timescheme +# -lpthread -lm +# ) + +# add_executable( +# displacement_newmark_acoustic_tests +# displacement_tests/Newmark/acoustic/newmark_tests.cpp +# ) + +# target_link_libraries( +# displacement_newmark_acoustic_tests +# quadrature +# mesh +# material_class +# yaml-cpp +# kokkos_environment +# mpi_environment +# compute +# parameter_reader +# compare_arrays +# timescheme +# -lpthread -lm +# ) add_executable( seismogram_elastic_tests @@ -338,8 +358,10 @@ if (NOT MPI_PARALLEL) gtest_discover_tests(compute_tests) gtest_discover_tests(source_location_tests) gtest_discover_tests(rmass_inverse_elastic_tests) - gtest_discover_tests(displacement_newmark_elastic_tests) - gtest_discover_tests(displacement_newmark_acoustic_tests) + gtest_discover_tests(rmass_inverse_acoustic_tests) + gtest_discover_tests(displacement_newmark_tests) + # gtest_discover_tests(displacement_newmark_elastic_tests) + # gtest_discover_tests(displacement_newmark_acoustic_tests) gtest_discover_tests(seismogram_elastic_tests) gtest_discover_tests(seismogram_acoustic_tests) endif(NOT MPI_PARALLEL) diff --git a/tests/unit-tests/displacement_tests/Newmark/newmark_tests.cpp b/tests/unit-tests/displacement_tests/Newmark/newmark_tests.cpp new file mode 100644 index 00000000..0f828ae5 --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/newmark_tests.cpp @@ -0,0 +1,257 @@ +#include "../../Kokkos_Environment.hpp" +#include "../../MPI_environment.hpp" +#include "../../utilities/include/compare_array.h" +#include "compute/interface.hpp" +#include "constants.hpp" +#include "domain/interface.hpp" +#include "material/interface.hpp" +#include "mesh/mesh.hpp" +#include "parameter_parser/interface.hpp" +#include "quadrature/interface.hpp" +#include "solver/interface.hpp" +#include "timescheme/interface.hpp" +#include "yaml-cpp/yaml.h" + +// ------------------------------------- // +// ------- Test configuration ----------- // + +namespace test_config { +struct database { +public: + database() + : specfem_config(""), elastic_domain_field("NULL"), + acoustic_domain_field("NULL"){}; + database(const YAML::Node &Node) { + specfem_config = Node["specfem_config"].as(); + // check if node elastic_domain_field exists + if (Node["elastic_domain_field"]) + elastic_domain_field = Node["elastic_domain_field"].as(); + + // check if node acoustic_domain_field exists + if (Node["acoustic_domain_field"]) + acoustic_domain_field = Node["acoustic_domain_field"].as(); + } + std::string specfem_config; + std::string elastic_domain_field = "NULL"; + std::string acoustic_domain_field = "NULL"; +}; + +struct configuration { +public: + configuration() : number_of_processors(0){}; + configuration(const YAML::Node &Node) { + number_of_processors = Node["nproc"].as(); + } + int number_of_processors; +}; + +struct Test { +public: + Test(const YAML::Node &Node) { + name = Node["name"].as(); + description = Node["description"].as(); + YAML::Node config = Node["config"]; + configuration = test_config::configuration(config); + + YAML::Node database_node = Node["databases"]; + database = test_config::database(database_node); + return; + } + + std::string name; + std::string description; + test_config::database database; + test_config::configuration configuration; +}; +} // namespace test_config + +// ------------------------------------- // + +// ----- Parse test config ------------- // + +std::vector parse_test_config(std::string test_config_file, + specfem::MPI::MPI *mpi) { + YAML::Node yaml = YAML::LoadFile(test_config_file); + const YAML::Node &tests = yaml["Tests"]; + + assert(tests.IsSequence()); + + std::vector test_configurations; + for (auto N : tests) + test_configurations.push_back(test_config::Test(N)); + + return test_configurations; +} + +// ------------------------------------- // + +TEST(DISPLACEMENT_TESTS, newmark_scheme_tests) { + std::string config_filename = "../../../tests/unit-tests/displacement_tests/" + "Newmark/test_config.yaml"; + + specfem::MPI::MPI *mpi = MPIEnvironment::mpi_; + + auto Tests = parse_test_config(config_filename, mpi); + + for (auto &Test : Tests) { + std::cout << "-------------------------------------------------------\n" + << "[RUNNING] Test: " << Test.name << "\n" + << "-------------------------------------------------------\n\n" + << std::endl; + + const auto parameter_file = Test.database.specfem_config; + + specfem::runtime_configuration::setup setup(parameter_file, + __default_file__); + + const auto [database_file, sources_file] = setup.get_databases(); + + // Set up GLL quadrature points + auto [gllx, gllz] = setup.instantiate_quadrature(); + + // Read mesh generated MESHFEM + std::vector materials; + specfem::mesh::mesh mesh(database_file, materials, mpi); + + // Read sources + // if start time is not explicitly specified then t0 is determined using + // source frequencies and time shift + auto [sources, t0] = + specfem::sources::read_sources(sources_file, setup.get_dt(), mpi); + + // Generate compute structs to be used by the solver + specfem::compute::compute compute(mesh.coorg, mesh.material_ind.knods, gllx, + gllz); + specfem::compute::partial_derivatives partial_derivatives( + mesh.coorg, mesh.material_ind.knods, gllx, gllz); + specfem::compute::properties material_properties( + mesh.material_ind.kmato, materials, mesh.nspec, gllx->get_N(), + gllz->get_N()); + specfem::compute::coupled_interfaces::coupled_interfaces coupled_interfaces( + compute.h_ibool, compute.coordinates.coord, + material_properties.h_ispec_type, mesh.coupled_interfaces); + + // Locate the sources + for (auto &source : sources) + source->locate(compute.coordinates.coord, compute.h_ibool, + gllx->get_hxi(), gllz->get_hxi(), mesh.nproc, mesh.coorg, + mesh.material_ind.knods, mesh.npgeo, + material_properties.h_ispec_type, mpi); + + // User output + for (auto &source : sources) { + if (mpi->main_proc()) + std::cout << *source << std::endl; + } + + // Update solver intialization time + setup.update_t0(-1.0 * t0); + + // Instantiate the solver and timescheme + auto it = setup.instantiate_solver(); + + // User output + if (mpi->main_proc()) + std::cout << *it << std::endl; + + // Setup solver compute struct + const type_real xmax = compute.coordinates.xmax; + const type_real xmin = compute.coordinates.xmin; + const type_real zmax = compute.coordinates.zmax; + const type_real zmin = compute.coordinates.zmin; + + specfem::compute::sources compute_sources(sources, gllx, gllz, xmax, xmin, + zmax, zmin, mpi); + + specfem::compute::receivers compute_receivers; + + // Instantiate domain classes + + try { + + const int nglob = specfem::utilities::compute_nglob(compute.h_ibool); + specfem::enums::element::quadrature::static_quadrature_points<5> qp5; + + specfem::domain::domain< + specfem::enums::element::medium::elastic, + specfem::enums::element::quadrature::static_quadrature_points<5> > + elastic_domain_static(nglob, qp5, &compute, material_properties, + partial_derivatives, compute_sources, + compute_receivers, gllx, gllz); + + specfem::domain::domain< + specfem::enums::element::medium::acoustic, + specfem::enums::element::quadrature::static_quadrature_points<5> > + acoustic_domain_static(nglob, qp5, &compute, material_properties, + partial_derivatives, compute_sources, + compute_receivers, gllx, gllz); + + // Instantiate coupled interfaces + specfem::coupled_interface::coupled_interface acoustic_elastic_interface( + acoustic_domain_static, elastic_domain_static, coupled_interfaces, + qp5, partial_derivatives, compute.h_ibool, gllx->get_xi(), + gllz->get_xi()); + + specfem::coupled_interface::coupled_interface elastic_acoustic_interface( + elastic_domain_static, acoustic_domain_static, coupled_interfaces, + qp5, partial_derivatives, compute.h_ibool, gllx->get_xi(), + gllz->get_xi()); + + specfem::solver::solver *solver = new specfem::solver::time_marching< + specfem::enums::element::quadrature::static_quadrature_points<5> >( + acoustic_domain_static, elastic_domain_static, + acoustic_elastic_interface, elastic_acoustic_interface, it); + + solver->run(); + + elastic_domain_static.sync_field(specfem::sync::DeviceToHost); + acoustic_domain_static.sync_field(specfem::sync::DeviceToHost); + + if (Test.database.elastic_domain_field != "NULL") { + specfem::kokkos::HostView2d + field_elastic = elastic_domain_static.get_host_field(); + + type_real tolerance = 0.01; + + specfem::testing::compare_norm(field_elastic, + Test.database.elastic_domain_field, + nglob, ndim, tolerance); + } + + if (Test.database.acoustic_domain_field != "NULL") { + specfem::kokkos::HostView1d + field_acoustic = Kokkos::subview( + acoustic_domain_static.get_host_field(), Kokkos::ALL(), 0); + + type_real tolerance = 0.01; + + specfem::testing::compare_norm(field_acoustic, + Test.database.acoustic_domain_field, + nglob, tolerance); + } + + std::cout << "--------------------------------------------------\n" + << "[PASSED] Test: " << Test.name << "\n" + << "--------------------------------------------------\n\n" + << std::endl; + + } catch (std::runtime_error &e) { + std::cout << " - Error: " << e.what() << std::endl; + FAIL() << "--------------------------------------------------\n" + << "[FAILED] Test failed\n" + << " - Test name: " << Test.name << "\n" + << " - Number of MPI processors: " + << Test.configuration.number_of_processors << "\n" + << " - Error: " << e.what() << "\n" + << "--------------------------------------------------\n\n" + << std::endl; + } + } +} + +int main(int argc, char *argv[]) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new MPIEnvironment); + ::testing::AddGlobalTestEnvironment(new KokkosEnvironment); + return RUN_ALL_TESTS(); +} diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test1/database.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test1/database.bin new file mode 100644 index 00000000..74013281 Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test1/database.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test1/displacement.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test1/displacement.bin new file mode 100644 index 00000000..7681d7b8 Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test1/displacement.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test1/sources.yaml b/tests/unit-tests/displacement_tests/Newmark/serial/test1/sources.yaml new file mode 100644 index 00000000..ed49a37f --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/serial/test1/sources.yaml @@ -0,0 +1,12 @@ +number-of-sources: 1 +sources: + - force: + x : 2500.0 + z : 2500.0 + source_surf: false + angle : 0.0 + vx : 0.0 + vz : 0.0 + Dirac: + factor: 1e10 + tshift: 0.0 diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test1/specfem_config.yaml b/tests/unit-tests/displacement_tests/Newmark/serial/test1/specfem_config.yaml new file mode 100644 index 00000000..0ad3fe3d --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/serial/test1/specfem_config.yaml @@ -0,0 +1,50 @@ +parameters: + + header: + ## Header information is used for logging. It is good practice to give your simulations explicit names + title: Isotropic Elastic simulation # name for your simulation + # A detailed description for your simulation + description: | + Material systems : Elastic domain (1) + Interfaces : None + Sources : Force source (1) + Boundary conditions : Neumann BCs on all edges + + simulation-setup: + ## quadrature setup + quadrature: + alpha: 0.0 + beta: 0.0 + ngllx: 5 + ngllz: 5 + + ## Solver setup + solver: + time-marching: + type-of-simulation: forward + time-scheme: + type: Newmark + dt: 1.1e-3 + nstep: 100 + + receivers: + stations-file: "../DATA/STATIONS" + angle: 0.0 + seismogram-type: + - displacement + - velocity + nstep_between_samples: 1 + + ## Runtime setup + run-setup: + number-of-processors: 1 + number-of-runs: 1 + + ## databases + databases: + mesh-database: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test1/database.bin" + source-file: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test1/sources.yaml" + + seismogram: + seismogram-format: ascii + output-folder: "." diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test2/database.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test2/database.bin new file mode 100644 index 00000000..699c950e Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test2/database.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test2/potential_acoustic.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test2/potential_acoustic.bin new file mode 100644 index 00000000..a626c09e Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test2/potential_acoustic.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test2/sources.yaml b/tests/unit-tests/displacement_tests/Newmark/serial/test2/sources.yaml new file mode 100644 index 00000000..ed49a37f --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/serial/test2/sources.yaml @@ -0,0 +1,12 @@ +number-of-sources: 1 +sources: + - force: + x : 2500.0 + z : 2500.0 + source_surf: false + angle : 0.0 + vx : 0.0 + vz : 0.0 + Dirac: + factor: 1e10 + tshift: 0.0 diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test2/specfem_config.yaml b/tests/unit-tests/displacement_tests/Newmark/serial/test2/specfem_config.yaml new file mode 100644 index 00000000..cee965ee --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/serial/test2/specfem_config.yaml @@ -0,0 +1,51 @@ +parameters: + + header: + ## Header information is used for logging. It is good practice to give your simulations explicit names + title: Isotropic Elastic simulation # name for your simulation + # A detailed description for your simulation + description: | + Material systems : Elastic domain (1) + Interfaces : None + Sources : Force source (1) + Boundary conditions : Neumann BCs on all edges + + simulation-setup: + ## quadrature setup + quadrature: + alpha: 0.0 + beta: 0.0 + ngllx: 5 + ngllz: 5 + + ## Solver setup + solver: + time-marching: + type-of-simulation: forward + time-scheme: + type: Newmark + dt: 1.1e-3 + nstep: 100 + + receivers: + stations-file: "../DATA/STATIONS" + angle: 0.0 + seismogram-type: + - displacement + - velocity + nstep_between_samples: 1 + + ## Runtime setup + run-setup: + number-of-processors: 1 + number-of-runs: 1 + + ## databases + databases: + mesh-database: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test2/database.bin" + source-file: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test2/sources.yaml" + + # seismogram output + seismogram: + seismogram-format: ascii + output-folder: "." diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test3/displacement.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test3/displacement.bin new file mode 100644 index 00000000..a90bd2d4 Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test3/displacement.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test3/potential_acoustic.bin b/tests/unit-tests/displacement_tests/Newmark/serial/test3/potential_acoustic.bin new file mode 100644 index 00000000..2b0919ff Binary files /dev/null and b/tests/unit-tests/displacement_tests/Newmark/serial/test3/potential_acoustic.bin differ diff --git a/tests/unit-tests/displacement_tests/Newmark/serial/test3/sources.yaml b/tests/unit-tests/displacement_tests/Newmark/serial/test3/sources.yaml new file mode 100644 index 00000000..b80f80b6 --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/serial/test3/sources.yaml @@ -0,0 +1,12 @@ +number-of-sources: 1 +sources: + - force: + x : 1575.0 + z : 2900.0 + source_surf: false + angle : 0.0 + vx : 0.0 + vz : 0.0 + Dirac: + factor: 1e9 + tshift: 0.0 diff --git a/tests/unit-tests/displacement_tests/Newmark/test_config.yaml b/tests/unit-tests/displacement_tests/Newmark/test_config.yaml new file mode 100644 index 00000000..1d1e6a9b --- /dev/null +++ b/tests/unit-tests/displacement_tests/Newmark/test_config.yaml @@ -0,0 +1,28 @@ +Tests: + - name : "SerialTest1 : Homogeneous elastic domain" + description: > + Testing newmark time-marching solver on a homogeneous elastic domain with no interfaces. Test is run on a single MPI process. + config: + nproc : 1 + databases: + specfem_config: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test1/specfem_config.yaml" + elastic_domain_field: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test1/displacement.bin" + + - name : "SerialTest2 : Homogeneous acoustic domain" + description: > + Testing newmark time-marching solver on a homogeneous acoustic domain with no interfaces. Test is run on a single MPI process. + config: + nproc : 1 + databases: + specfem_config: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test2/specfem_config.yaml" + acoustic_domain_field: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test2/potential_acoustic.bin" + + - name : "SerialTest3 : Acoustic-Elastic coupled domain" + description: > + Testing newmark time-marching solver on a coupled acoustic-elastic domain with 1 elastic-acoustic interface. Test is run on a single MPI process. + config: + nproc : 1 + databases: + specfem_config: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test3/specfem_config.yaml" + acoustic_domain_field: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test3/potential_acoustic.bin" + elastic_domain_field: "../../../tests/unit-tests/displacement_tests/Newmark/serial/test3/displacement.bin"