Skip to content
Snippets Groups Projects
Commit e35d5146 authored by Lars Bilke's avatar Lars Bilke
Browse files

Moved xdmfdiff from submodule to repo.

parent 5f71df3f
No related branches found
No related tags found
No related merge requests found
...@@ -46,9 +46,6 @@ ...@@ -46,9 +46,6 @@
[submodule "ThirdParty/spdlog"] [submodule "ThirdParty/spdlog"]
path = ThirdParty/spdlog path = ThirdParty/spdlog
url = https://github.com/gabime/spdlog.git url = https://github.com/gabime/spdlog.git
[submodule "ThirdParty/xdmfdiff"]
path = ThirdParty/xdmfdiff
url = https://gitlab.opengeosys.org/ogs/xdmfdiff.git
[submodule "ThirdParty/xdmf"] [submodule "ThirdParty/xdmf"]
path = ThirdParty/xdmf path = ThirdParty/xdmf
url = https://gitlab.opengeosys.org/ogs/xdmflib.git url = https://gitlab.opengeosys.org/ogs/xdmflib.git
...@@ -268,13 +268,6 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/ThirdParty/vtkdiff/CMakeLists.txt AND BUILD_TEST ...@@ -268,13 +268,6 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/ThirdParty/vtkdiff/CMakeLists.txt AND BUILD_TEST
install(PROGRAMS $<TARGET_FILE:vtkdiff> DESTINATION bin COMPONENT ogs_extras) install(PROGRAMS $<TARGET_FILE:vtkdiff> DESTINATION bin COMPONENT ogs_extras)
endif() endif()
# xdmfdiff
if(EXISTS ${PROJECT_SOURCE_DIR}/ThirdParty/xdmfdiff/CMakeLists.txt AND BUILD_TESTING)
add_subdirectory(ThirdParty/xdmfdiff)
target_link_libraries(xdmfdiff Xdmf)
install(PROGRAMS $<TARGET_FILE:xdmfdiff> DESTINATION bin COMPONENT ogs_extras)
endif()
include(scripts/cmake/CheckHeaderCompilation.cmake) include(scripts/cmake/CheckHeaderCompilation.cmake)
add_subdirectory(Applications) add_subdirectory(Applications)
......
### xdmfdiff ###
add_subdirectory(xdmfdiff)
### testrunner ###
include(${PROJECT_SOURCE_DIR}/scripts/cmake/OGSEnabledElements.cmake) include(${PROJECT_SOURCE_DIR}/scripts/cmake/OGSEnabledElements.cmake)
# VS2012 doesn't support correctly the tuples yet See # VS2012 doesn't support correctly the tuples yet See
......
add_executable(xdmfdiff xdmfdiff.cpp)
target_link_libraries(xdmfdiff Xdmf std::filesystem)
install(PROGRAMS $<TARGET_FILE:xdmfdiff> DESTINATION bin COMPONENT ogs_extras)
/**
* \file
* \copyright
* Copyright (c) 2015-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*/
#include <tclap/CmdLine.h>
#include <Xdmf.hpp>
#include <XdmfDomain.hpp>
#include <XdmfReader.hpp>
#include <XdmfUnstructuredGrid.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range.hpp>
#include <cmath>
#include <cstdlib>
#include <filesystem>
#include <iomanip>
#include <ios>
#include <memory>
#include <sstream>
#include <tuple>
// See https://stackoverflow.com/a/8513803/2706707
template <typename... Containers>
auto zip(Containers&&... containers) -> boost::iterator_range<
boost::zip_iterator<decltype(boost::make_tuple(std::begin(containers)...))>>
{
auto zip_begin =
boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
auto zip_end =
boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
return boost::make_iterator_range(zip_begin, zip_end);
}
struct Args
{
bool const quiet;
bool const verbose;
bool const meshcheck;
double const abs_err_thr;
double const rel_err_thr;
std::string const xdmf_input_a;
std::string const xdmf_input_b;
std::string const data_array_a;
std::string const data_array_b;
};
auto parseCommandLine(int argc, char* argv[]) -> Args
{
TCLAP::CmdLine cmd(
"XdmfDiff software.\n"
"Copyright (c) 2015-2020, OpenGeoSys Community "
"(http://www.opengeosys.org) "
"Distributed under a Modified BSD License. "
"See accompanying file LICENSE.txt or "
"http://www.opengeosys.org/project/license",
' ',
"0.1");
TCLAP::UnlabeledValueArg<std::string> xdmf_input_a_arg(
"input-file-a", "Path to the Xdmf input file.", true, "", "XDMF FILE");
cmd.add(xdmf_input_a_arg);
TCLAP::UnlabeledValueArg<std::string> xdmf_input_b_arg(
"input-file-b",
"Path to the second XDMF input file.",
false,
"",
"XDMF FILE");
cmd.add(xdmf_input_b_arg);
TCLAP::ValueArg<std::string> data_array_a_arg(
"a", "first_data_array", "First data array name for comparison", true,
"", "NAME");
TCLAP::ValueArg<std::string> data_array_b_arg(
"b",
"second_data_array",
"Second data array name for comparison",
false,
"",
"NAME");
cmd.add(data_array_b_arg);
TCLAP::SwitchArg meshcheck_arg(
"m", "mesh_check", "Compare mesh geometries using absolute tolerance.");
cmd.xorAdd(data_array_a_arg, meshcheck_arg);
TCLAP::SwitchArg quiet_arg("q", "quiet", "Suppress all but error output.");
cmd.add(quiet_arg);
TCLAP::SwitchArg verbose_arg("v", "verbose",
"Also print which values differ.");
cmd.add(verbose_arg);
auto const double_eps_string =
std::to_string(std::numeric_limits<double>::epsilon());
TCLAP::ValueArg<double> abs_err_thr_arg(
"",
"abs",
"Tolerance for the absolute error in the maximum norm (" +
double_eps_string + ")",
false,
std::numeric_limits<double>::epsilon(),
"FLOAT");
cmd.add(abs_err_thr_arg);
TCLAP::ValueArg<double> rel_err_thr_arg(
"",
"rel",
"Tolerance for the componentwise relative error (" + double_eps_string +
")",
false,
std::numeric_limits<double>::epsilon(),
"FLOAT");
cmd.add(rel_err_thr_arg);
cmd.parse(argc, argv);
return Args{quiet_arg.getValue(), verbose_arg.getValue(),
meshcheck_arg.getValue(), abs_err_thr_arg.getValue(),
rel_err_thr_arg.getValue(), xdmf_input_a_arg.getValue(),
xdmf_input_b_arg.getValue(), data_array_a_arg.getValue(),
data_array_b_arg.getValue()};
}
struct Grid
{
std::vector<double> point_values;
std::vector<int> topology_values;
std::vector<double> attribute_values;
};
std::unique_ptr<Grid> readMesh(std::string const& filename,
std::string const& attribute_name)
{
if (filename.empty())
{
return nullptr;
}
if (std::filesystem::path(filename).extension().string() != ".xdmf")
{
std::cerr << "Error: Expected a file with .xdmf extension."
<< "File '" << filename << "' not read.";
return nullptr;
}
auto const xreader = XdmfReader::New();
auto const domain =
shared_dynamic_cast<XdmfDomain>(xreader->read(filename));
auto const ungrid = domain->getUnstructuredGrid(0);
auto const geometry = ungrid->getGeometry();
int const size_points = geometry->getSize();
std::vector<double> points(size_points);
geometry->getValues(0, points.data(), size_points);
auto const topology = ungrid->getTopology();
int const size_topology = topology->getSize();
std::vector<int> topology_values(size_topology);
topology->getValues(0, topology_values.data(), size_topology);
auto const attribute = ungrid->getAttribute(attribute_name);
int const attribute_size = attribute->getSize();
std::vector<double> attribute_values(attribute_size);
attribute->getValues(0, attribute_values.data(), attribute_size);
return std::make_unique<Grid>(
Grid{points, topology_values, attribute_values});
}
std::tuple<std::unique_ptr<Grid>, std::unique_ptr<Grid>> readMeshes(
std::string const& file_a_name,
std::string const& file_b_name,
std::string const& attribute_a_name,
std::string const& attribute_b_name)
{
return {readMesh(file_a_name, attribute_a_name),
readMesh(file_b_name, attribute_b_name)};
}
bool compareCellTopology(std::vector<int> const& cells_a,
std::vector<int> const& cells_b)
{
if (cells_a.size() != cells_b.size())
{
std::cerr << "Number of cells in the first mesh is " << cells_a.size()
<< " and differs from the number of cells in the second "
"mesh, which is "
<< cells_b.size() << "\n";
return false;
}
for (std::size_t i = 0; i < cells_a.size(); ++i)
{
if (cells_a[0] != cells_b[0])
{
std::cerr << "Cell on position " << i << "\n"
<< "in first mesh has celltype: " << cells_a[i] << "\n"
<< "in second mesh has celltype: " << cells_b[i] << ".\n";
return false;
}
}
return true;
}
bool compareValues(std::vector<double> const& points_a,
std::vector<double> const& points_b, double const eps)
{
if (points_a.size() != points_b.size())
{
std::cerr << "Number of points in the first mesh is " << points_a.size()
<< " and differst from the number of point in the second "
"mesh, which is "
<< points_b.size() << "\n";
return false;
}
for (std::size_t i = 0; i < points_a.size(); ++i)
{
if (double const distance = std::abs(points_a[i] - points_b[i]);
distance >= eps)
{
std::cerr << "Point on position " << i << "\n"
<< "in first mesh has value: " << points_a[i] << "\n"
<< "in second mesh has value: " << points_b[i] << ".\n"
<< "The distance is: " << distance << "\n";
return false;
}
return true;
}
return true;
}
int main(int argc, char* argv[])
{
auto const digits10 = std::numeric_limits<double>::digits10;
auto const args = parseCommandLine(argc, argv);
// Setup the standard output and error stream numerical formats.
std::cout << std::scientific << std::setprecision(digits10);
std::cerr << std::scientific << std::setprecision(digits10);
auto const [mesh_a, mesh_b] =
readMeshes(args.xdmf_input_a, args.xdmf_input_b, args.data_array_a,
args.data_array_b);
if (args.xdmf_input_a == args.xdmf_input_b)
{
std::cout << "Will not compare meshes from same input file.\n";
return EXIT_SUCCESS;
}
if (!compareValues(
mesh_a->point_values, mesh_b->point_values, args.abs_err_thr))
{
std::cerr << "Error in mesh points' comparison occured.\n";
return EXIT_FAILURE;
}
if (!compareCellTopology(mesh_a->topology_values, mesh_b->topology_values))
{
std::cerr << "Error in cells' topology comparison occured.\n";
return EXIT_FAILURE;
}
if (!compareValues(mesh_a->attribute_values,
mesh_b->attribute_values,
args.abs_err_thr))
{
std::cerr << "Error in mesh attribute ( " << args.data_array_a << ") "
<< "of first mesh and ( " << args.data_array_b << ") "
<< "of second mesh occured.\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
\ No newline at end of file
Subproject commit b2928dd75bbea23640438648b8a0170dc1ed752d
...@@ -22,7 +22,7 @@ set(REQUIRED_SUBMODULES ...@@ -22,7 +22,7 @@ set(REQUIRED_SUBMODULES
${OGS_ADDITIONAL_SUBMODULES_TO_CHECKOUT} ${OGS_ADDITIONAL_SUBMODULES_TO_CHECKOUT}
) )
if(BUILD_TESTING) if(BUILD_TESTING)
list(APPEND REQUIRED_SUBMODULES ThirdParty/vtkdiff ThirdParty/xdmfdiff) list(APPEND REQUIRED_SUBMODULES ThirdParty/vtkdiff)
endif() endif()
if(OGS_BUILD_UTILS) if(OGS_BUILD_UTILS)
# Required by the partmesh tool, which is build with utils only. # Required by the partmesh tool, which is build with utils only.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment