Commit 493a7246 authored by Praetorius, Simon's avatar Praetorius, Simon

Added fmt as output formatting library

parent c57c5580
Pipeline #1233 failed with stage
in 12 minutes and 55 seconds
......@@ -19,12 +19,7 @@ add_subdirectory("test")
add_subdirectory("examples" EXCLUDE_FROM_ALL)
add_subdirectory("doc")
add_subdirectory("cmake/modules")
add_subdirectory("externals" EXCLUDE_FROM_ALL)
target_include_directories(amdis PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src>)
target_compile_definitions(amdis PUBLIC AMDIS_BACKEND_MTL=1)
target_compile_options(amdis PUBLIC -Wall -pedantic -Wno-unused-parameter) #-ftemplate-backtrace-limit=0
add_subdirectory("externals")
# finalize the dune project, e.g. generating config.h etc.
finalize_dune_project(GENERATE_CONFIG_H_CMAKE)
The MIT License (MIT)
Copyright (c) 2016 Simon Praetorius
Copyright (c) 2016-2018 Simon Praetorius
2018 Felix Müller
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -2,10 +2,8 @@
# Dune module information file #
################################
#Name of the module
Module: amdis
Version: 0.1
Maintainer: simon.praetorius@tu-dresden.de
#depending on
Depends: dune-common (>= 2.6) dune-geometry (>= 2.6) dune-localfunctions (>= 2.6) dune-typetree (>= 2.6) dune-grid (>= 2.6) dune-functions (>= 2.6)
#Suggests: dune-uggrid dune-alugrid dune-foamgrid
Suggests: dune-uggrid dune-alugrid dune-foamgrid
......@@ -6,7 +6,7 @@ foreach(project ${projects2d})
add_executable(${project}.2d ${project}.cc)
add_dune_alberta_flags(GRIDDIM 2 WORLDDIM 2 ${project}.2d)
target_link_dune_default_libraries(${project}.2d)
target_link_libraries(${project}.2d amdis fmt)
target_link_libraries(${project}.2d amdis)
target_compile_definitions(${project}.2d PRIVATE AMDIS_DIM=2 AMDIS_DOW=2)
add_dependencies(examples ${project}.2d)
endforeach()
......@@ -17,7 +17,7 @@ foreach(project ${projects3d})
add_executable(${project}.3d ${project}.cc)
add_dune_alberta_flags(GRIDDIM 3 WORLDDIM 3 ${project}.3d)
target_link_dune_default_libraries(${project}.3d)
target_link_libraries(${project}.3d amdis fmt)
target_link_libraries(${project}.3d amdis)
target_compile_definitions(${project}.3d PRIVATE AMDIS_DIM=3 AMDIS_DOW=3)
add_dependencies(examples ${project}.3d)
endforeach()
\ No newline at end of file
......@@ -3,8 +3,6 @@
#endif
#include <iostream>
#include <fmt/core.h>
#include <amdis/AMDiS.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/Operators.hpp>
......@@ -79,9 +77,9 @@ int main(int argc, char** argv)
}
std::cout << "\n";
fmt::print("{:5} | {:12} | {:12} | {:12} | {:12} | {:12}\n",
"level", "h", "|u - u*|_L2","|u - u*|_H1","eoc_L2","eoc_H1");
fmt::print("{0:->7}{0:->15}{0:->15}{0:->15}{0:->15}{1:->14}","+","\n");
msg("{:5} | {:12} | {:12} | {:12} | {:12} | {:12}\n",
"level", "h", "|u - u*|_L2","|u - u*|_H1","eoc_L2","eoc_H1");
msg("{0:->7}{0:->15}{0:->15}{0:->15}{0:->15}{1:->14}","+","\n");
std::vector<double> eocL2(numLevels, 0.0), eocH1(numLevels, 0.0);
for (int i = 1; i < numLevels; ++i) {
......@@ -90,8 +88,8 @@ int main(int argc, char** argv)
}
for (int i = 0; i < numLevels; ++i)
fmt::print("{:<5} | {:<12} | {:<12} | {:<12} | {:<12} | {:<12}\n",
i+1, widths[i], errL2[i], errH1[i], eocL2[i], eocH1[i]);
msg("{:<5} | {:<12} | {:<12} | {:<12} | {:<12} | {:<12}\n",
i+1, widths[i], errL2[i], errH1[i], eocL2[i], eocH1[i]);
AMDiS::finalize();
return 0;
......
add_subdirectory(fmt)
\ No newline at end of file
target_include_directories(amdis PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/externals/fmt/include>)
dune_library_add_sources(amdis SOURCES
fmt/src/format.cc
fmt/src/posix.cc)
install(FILES
fmt/include/fmt/core.h
fmt/include/fmt/format-inl.h
fmt/include/fmt/format.h
fmt/include/fmt/ostream.h
fmt/include/fmt/posix.h
fmt/include/fmt/printf.h
fmt/include/fmt/ranges.h
fmt/include/fmt/time.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fmt)
\ No newline at end of file
add_subdirectory(amdis)
\ No newline at end of file
add_subdirectory(amdis)
target_include_directories(amdis PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src>)
target_compile_options(amdis PUBLIC -Wall -pedantic -Wno-unused-parameter) #-ftemplate-backtrace-limit=0
......@@ -41,7 +41,7 @@ namespace AMDiS
problemTime->setTime(adaptInfo);
msg("time = ", adaptInfo.getTime(), ", timestep = ", adaptInfo.getTimestep());
msg("time = {}, timestep = {}", adaptInfo.getTime(), adaptInfo.getTimestep());
adaptInfo.setSpaceIteration(0);
......@@ -62,7 +62,7 @@ namespace AMDiS
adaptInfo.setTime(adaptInfo.getTime() + adaptInfo.getTimestep());
problemTime->setTime(adaptInfo);
msg("time = ", adaptInfo.getTime(), ", timestep = ", adaptInfo.getTimestep());
msg("time = {}, timestep = {}", adaptInfo.getTime(), adaptInfo.getTimestep());
problemIteration->oneIteration(adaptInfo, NO_ADAPTION);
......@@ -153,7 +153,7 @@ namespace AMDiS
adaptInfo.setTime(adaptInfo.getTime() + adaptInfo.getTimestep());
problemTime->setTime(adaptInfo);
msg("time = ", adaptInfo.getTime(), ", timestep = ", adaptInfo.getTimestep());
msg("time = {}, timestep = {}", adaptInfo.getTime(), adaptInfo.getTimestep());
problemIteration->oneIteration(adaptInfo, FULL_ITERATION);
......@@ -189,7 +189,7 @@ namespace AMDiS
simpleAdaptiveTimeStrategy();
break;
default:
error_exit("Unknown strategy = ", strategy);
error_exit("Unknown strategy = {}", strategy);
}
adaptInfo.incTimestepNumber();
......
......@@ -95,7 +95,7 @@ void Assembler<Traits>::assemble(
// 4. finish matrix insertion and apply dirichlet boundary conditions
std::size_t nnz = finishMatrixVector(matrix, solution, rhs, asmMatrix, asmVector);
msg("fill-in of assembled matrix: ", nnz);
msg("fill-in of assembled matrix: {}", nnz);
}
......@@ -142,7 +142,7 @@ void Assembler<Traits>::initMatrixVector(
{
#ifdef HAVE_EXTENDED_DUNE_FUNCTIONS
if (rowNode.isLeaf)
msg(globalBasis_.dimension(rowTreePath), " DOFs for Basis[", to_string(rowTreePath), "]");
msg("{} DOFs for Basis[{}]",globalBasis_.dimension(rowTreePath), to_string(rowTreePath));
#endif
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
......@@ -155,7 +155,7 @@ void Assembler<Traits>::initMatrixVector(
bc->init(matrix, solution, rhs, rowBasis, colBasis);
});
});
msg(globalBasis_.dimension(), " total DOFs");
msg("{} total DOFs", globalBasis_.dimension());
}
......
......@@ -36,7 +36,7 @@ namespace AMDiS
static void addCreator(std::string key, CreatorInterface<BaseClass>* creator)
{
init();
test_exit(!creatorMap[key], "There is already a creator for key ", key);
test_exit(!creatorMap[key], "There is already a creator for key {}", key);
creatorMap[key] = creator;
}
......@@ -50,7 +50,7 @@ namespace AMDiS
key = "default";
auto creator = creatorMap[key];
test_exit(creator, "No creator for key `", key, "` defined in init file for parameter `", initFileStr, "`");
test_exit(creator, "No creator for key `{}` defined in init file for parameter `{}`", key, initFileStr);
return creator;
}
......
......@@ -94,7 +94,7 @@ namespace AMDiS
/// Implements \ref FileWriterInterface::writeFiles
virtual void writeFiles(AdaptInfo& adaptInfo, bool force) override
{
test_exit(filesystem::exists(dir_), "Output directory '",dir_,"' does not exist!");
test_exit(filesystem::exists(dir_), "Output directory '{}' does not exist!",dir_);
if (vtkSeqWriter_)
vtkSeqWriter_->write(adaptInfo.getTime(), mode_);
......
......@@ -9,7 +9,7 @@ namespace AMDiS {
void InitfileParser::readInitfile(std::string fn, Dune::ParameterTree& pt, bool overwrite)
{
test_exit(filesystem::exists(fn),
"init-file '", fn, "' cannot be opened for reading");
"init-file '{}' cannot be opened for reading", fn);
// read file if its not parsed already
auto ins = includeList().insert(fn);
......
......@@ -52,8 +52,8 @@ void Marker<Traits>::initMarking(AdaptInfo& adaptInfo)
template <class Traits>
void Marker<Traits>::finishMarking(AdaptInfo& adaptInfo)
{
msg(elMarkRefine_, " elements marked for refinement");
msg(elMarkCoarsen_, " elements marked for coarsening");
msg("{} elements marked for refinement", elMarkRefine_);
msg("{} elements marked for coarsening", elMarkCoarsen_);
}
......@@ -110,7 +110,8 @@ void MSMarker<Traits>::initMarking(AdaptInfo& adaptInfo)
this->markRLimit_ = msGammaP * adaptInfo.getEstMax(this->component_);
this->markCLimit_ = msGammaCP * adaptInfo.getEstMax(this->component_);
msg("start max_est: ", adaptInfo.getEstMax(this->component_), ", mark_limits: ", this->markRLimit_, ", " , this->markCLimit_);
msg("start max_est: {}, mark_limits: {}, {}",
adaptInfo.getEstMax(this->component_), this->markRLimit_ , this->markCLimit_);
}
......@@ -131,7 +132,7 @@ void ESMarker<Traits>::initMarking(AdaptInfo& adaptInfo)
this->markRLimit_ = esThetaP * epsP / nLeaves;
this->markCLimit_ = esThetaCP * epsP / nLeaves;
msg("start mark_limits: ", this->markRLimit_, ", " , this->markCLimit_, "; nt = ", nLeaves);
msg("start mark_limits: {}, {}; nt = {}", this->markRLimit_, this->markCLimit_, nLeaves);
}
......@@ -156,7 +157,7 @@ Flag GERSMarker<Traits>::markGrid(AdaptInfo& adaptInfo)
if (redfac < 1.0) {
LTheta *= redfac;
msg("GERS: use extrapolated theta_star = ", std::pow(LTheta, 1.0 / this->p_));
msg("GERS: use extrapolated theta_star = {}", std::pow(LTheta, 1.0 / this->p_));
}
}
......@@ -176,7 +177,7 @@ Flag GERSMarker<Traits>::markGrid(AdaptInfo& adaptInfo)
} while((GERSGamma > 0) && (gersSum_ < LTheta * this->estSum_));
}
msg("GERS refinement with gamma = ", GERSGamma);
msg("GERS refinement with gamma = {}", GERSGamma);
}
if (this->coarsenAllowed_) {
......@@ -191,10 +192,10 @@ Flag GERSMarker<Traits>::markGrid(AdaptInfo& adaptInfo)
for (const auto& elem : Dune::elements(this->grid_->leafGridView()))
markElementForCoarsening(adaptInfo, elem);
msg("coarse loop: gamma = ", GERSGamma, ", sum = ", gersSum_, ", limit = ", LTheta);
msg("coarse loop: gamma = {}, sum = {}, limit = {}", GERSGamma, gersSum_, LTheta);
} while(gersSum_ > LTheta);
msg("GERS coarsening with gamma = ", GERSGamma);
msg("GERS coarsening with gamma = {}", GERSGamma);
}
Super::finishMarking(adaptInfo);
......
......@@ -145,8 +145,6 @@ namespace AMDiS
Dune::FieldVector<double, dim> L; L = 1.0; // extension of the domain
Parameters::get(meshName + "->dimension", L);
msg("L = ", L);
auto s = Dune::filledArray<std::size_t(dim)>(1); // number of cells on coarse mesh in each direction
Parameters::get(meshName + "->num cells", s);
......
......@@ -5,6 +5,8 @@
#include <sstream>
#include <string>
#include <fmt/core.h>
/**
* \def AMDIS_NO_THROW
* \brief The preprocessor constant sets whether to use c-asserts (if defined) or
......@@ -37,10 +39,6 @@
#endif
#endif
#define AMDIS_STATIC_ASSERT(...) \
static_assert(__VA_ARGS__, #__VA_ARGS__)
#define AMDIS_UNUSED(var) __attribute__((unused)) var
#define AMDIS_FUNCNAME(nn) AMDIS_UNUSED(const char *funcName); funcName = nn;
......@@ -58,23 +56,6 @@ namespace AMDiS
{
namespace Impl
{
template <class OStream>
OStream& concat(OStream& out) { return out; }
template <class OStream, class Arg0, class... Args>
OStream& concat(OStream& out, Arg0&& arg0, Args&&... args)
{
out << arg0; concat(out, std::forward<Args>(args)...);
return out;
}
template <class... Args>
std::string to_string(Args&&... args)
{
std::stringstream ss; concat(ss, std::forward<Args>(args)...);
return ss.str();
}
template <class OStream, class... Args>
OStream& msg(OStream& out, Args&&... args)
{
......@@ -84,12 +65,12 @@ namespace AMDiS
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1 && rank == 0) {
concat(out, "[0] ",std::forward<Args>(args)...);
out << "[0] " << fmt::format(std::forward<Args>(args)...);
} else if (num_ranks == 1) {
concat(out, std::forward<Args>(args)...);
out << fmt::format(std::forward<Args>(args)...);
}
#else
concat(out, std::forward<Args>(args)...);
out << fmt::format(std::forward<Args>(args)...);
#endif
return out;
}
......@@ -107,7 +88,7 @@ namespace AMDiS
template <class... Args>
void msg(Args&&... args)
{
Impl::msg(std::cout, std::forward<Args>(args)..., "\n");
Impl::msg(std::cout, std::forward<Args>(args)...) << std::endl;
}
......@@ -135,14 +116,14 @@ namespace AMDiS
void error_exit(Args&&... args)
{
#ifdef AMDIS_NO_THROW
Impl::msg(std::cerr, "ERROR: ", std::forward<Args>(args)..., "\n");
Impl::msg(std::cerr << "ERROR: ", std::forward<Args>(args)...) << std::endl;
#ifndef NDEBUG
assert(false);
#else
std::exit(EXIT_FAILURE);
#endif
#else
throw std::runtime_error( Impl::to_string("ERROR: ", std::forward<Args>(args)...) );
throw std::runtime_error( std::string("ERROR: ") + fmt::format(std::forward<Args>(args)...));
#endif
}
......@@ -166,7 +147,7 @@ namespace AMDiS
template <class... Args>
void warning(Args&&... args)
{
msg("WARNING: ", std::forward<Args>(args)...);
Impl::msg(std::cout << "WARNING: ", std::forward<Args>(args)...) << std::endl;
}
......
......@@ -253,14 +253,14 @@ namespace AMDiS
{
gridName_ = "";
Parameters::get(name_ + "->mesh", gridName_);
test_exit(!gridName_.empty(), "No grid name specified for '", name_, "->mesh'!");
test_exit(!gridName_.empty(), "No grid name specified for '{}->mesh'!", name_);
grid_ = MeshCreator<Grid>::create(gridName_);
msg("Create grid:");
msg("#elements = " , grid_->size(0));
msg("#faces/edges = ", grid_->size(1));
msg("#vertices = " , grid_->size(dim));
msg("#elements = {}" , grid_->size(0));
msg("#faces/edges = {}", grid_->size(1));
msg("#vertices = {}" , grid_->size(dim));
msg("");
}
......
......@@ -285,14 +285,14 @@ solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData)
solverInfo);
if (solverInfo.getInfo() > 0) {
msg("solution of discrete system needed ", t.elapsed(), " seconds");
msg("solution of discrete system needed {} seconds", t.elapsed());
if (solverInfo.getAbsResidual() >= 0.0) {
if (solverInfo.getRelResidual() >= 0.0)
msg("Residual norm: ||b-Ax|| = ", solverInfo.getAbsResidual(),
", ||b-Ax||/||b|| = ", solverInfo.getRelResidual());
msg("Residual norm: ||b-Ax|| = {}, ||b-Ax||/||b|| = {}",
solverInfo.getAbsResidual(), solverInfo.getRelResidual());
else
msg("Residual norm: ||b-Ax|| = ", solverInfo.getAbsResidual());
msg("Residual norm: ||b-Ax|| = {}", solverInfo.getAbsResidual());
}
}
......@@ -304,7 +304,7 @@ solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData)
if (solverInfo.getRelTolerance() > 0
&& solverInfo.getRelResidual() > solverInfo.getRelTolerance())
tol_str << "relTol = " << solverInfo.getRelTolerance() << " ";
error_exit("Tolerance ", tol_str.str(), " could not be reached!");
error_exit("Tolerance {} could not be reached!", tol_str.str());
}
}
......@@ -318,7 +318,7 @@ Flag ProblemStat<Traits>::markElements(AdaptInfo& adaptInfo)
for (auto& currentMarker : marker_)
markFlag |= currentMarker->markGrid(adaptInfo);
msg("markElements needed ", t.elapsed(), " seconds");
msg("markElements needed {} seconds", t.elapsed());
return markFlag;
}
......@@ -335,7 +335,7 @@ buildAfterCoarsen(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool
globalBasis_->update(gv);
assembler.assemble(*systemMatrix_, *solution_, *rhs_, asmMatrix, asmVector);
msg("buildAfterCoarsen needed ", t.elapsed(), " seconds");
msg("buildAfterCoarsen needed {} seconds", t.elapsed());
}
......@@ -346,7 +346,7 @@ writeFiles(AdaptInfo& adaptInfo, bool force)
Dune::Timer t;
for (auto writer : filewriter_)
writer->writeFiles(adaptInfo, force);
msg("writeFiles needed ", t.elapsed(), " seconds");
msg("writeFiles needed {} seconds", t.elapsed());
}
......
......@@ -28,7 +28,7 @@ namespace AMDiS
AMDIS_FUNCNAME("StandardProblemIteration::beginIteration()");
msg("");
msg("begin of iteration number: ", (adaptInfo.getSpaceIteration() + 1));
msg("begin of iteration number: {}", (adaptInfo.getSpaceIteration() + 1));
msg("=============================");
}
......@@ -55,7 +55,7 @@ namespace AMDiS
AMDIS_FUNCNAME("StandardProblemIteration::endIteration()");
msg("");
msg("end of iteration number: ", (adaptInfo.getSpaceIteration() + 1));
msg("end of iteration number: {}", (adaptInfo.getSpaceIteration() + 1));
msg("=============================");
}
......
......@@ -62,7 +62,7 @@ namespace AMDiS
}
if (solverInfo.getInfo() > 0)
msg("fill matrix needed ", t.elapsed(), " seconds");
msg("fill matrix needed {} seconds", t.elapsed());
int error = runner_->solve(A, x, b, solverInfo);
solverInfo.setError(error);
......
......@@ -61,7 +61,7 @@ namespace AMDiS
{
test_exit_dbg( initialized_, "Occupation pattern not initialized!");
test_exit_dbg( r < matrix_.N() && c < matrix_.M() ,
"Indices out of range [0,", matrix_.N(), ")x[0,", matrix_.M(), ")" );
"Indices out of range [0,{})x[0,{})", matrix_.N(), matrix_.M() );
matrix_[r][c] += value;
}
......
......@@ -66,7 +66,7 @@ namespace AMDiS
value_type const& operator[](size_type i) const
{
test_exit_dbg(i < vector_.size(),
"Index ", i, " out of range [0,", vector_.size(), ")" );
"Index {} out of range [0,{})", i, vector_.size());
return vector_[i];
}
......@@ -74,7 +74,7 @@ namespace AMDiS
value_type& operator[](size_type i)
{
test_exit_dbg(i < vector_.size(),
"Index ", i, " out of range [0,", vector_.size(), ")" );
"Index {} out of range [0,{})", i, vector_.size());
return vector_[i];
}
......
......@@ -61,7 +61,7 @@ namespace AMDiS
{
test_exit_dbg(inserter_, "Inserter not initilized!");
test_exit_dbg(r < num_rows(matrix_) && c < num_cols(matrix_),
"Indices out of range [0,", num_rows(matrix_), ")x[0,", num_cols(matrix_), ")" );
"Indices out of range [0,{})x[0,{})", num_rows(matrix_), num_cols(matrix_));
(*inserter_)[r][c] += value;
}
......
......@@ -54,7 +54,7 @@ namespace AMDiS
value_type const& operator[](size_type i) const
{
test_exit_dbg(i < mtl::vec::size(vector_),
"Index ", i, " out of range [0,", mtl::vec::size(vector_), ")" );
"Index {} out of range [0,{})", i, mtl::vec::size(vector_));
return vector_[i];
}
......@@ -62,7 +62,7 @@ namespace AMDiS
value_type& operator[](size_type i)
{
test_exit_dbg(i < mtl::vec::size(vector_),
"Index ", i, " out of range [0,", mtl::vec::size(vector_), ")" );
"Index {} out of range [0,{})", i, mtl::vec::size(vector_));
return vector_[i];
}
......
......@@ -60,7 +60,7 @@ namespace AMDiS
try {
code = (*solver_)(x, b);
} catch (mtl::mat::umfpack::error& e) {
error_exit("UMFPACK_ERROR(solve, ", e.code, ") = ", e.what());
error_exit("UMFPACK_ERROR(solve, {}) = {}", e.code, e.what());
}
auto r = Vector(b);
......@@ -106,7 +106,7 @@ namespace AMDiS
try {
Super::solver_.reset(new SolverType(fullMatrix, Super::symmetricStrategy_, Super::allocInit_));
} catch (mtl::mat::umfpack::error const& e) {
error_exit("UMFPACK_ERROR(factorize, ", e.code, ") = ", e.what());
error_exit("UMFPACK_ERROR(factorize, {}) = {}", e.code, e.what());
}
}
};
......
# maybe unncessary (?)
dune_add_test(NAME test_duneamdis
TARGET duneamdis
COMPILE_ONLY)
# find_package(GTest REQUIRED)
set(projects "test1" "test2")
foreach(project ${projects})
dune_add_test(NAME ${project}
SOURCES ${project}.cc
LINK_LIBRARIES duneamdis ${GTEST_BOTH_LIBRARIES}
COMPILE_DEFINITIONS "DIM=2;DOW=2"
CMD_ARGS "init/test.json.2d")
add_dune_alberta_flags(GRIDDIM 2 WORLDDIM 2 ${project})
target_include_directories(${project} PRIVATE ${GTEST_INCLUDE_DIRS})
set_tests_properties(${project} PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endforeach()
\ No newline at end of file
#pragma once
#include <nanoflann.hpp>
#include <cstdlib>
#include <iostream>
namespace AMDiS
{
template <class FeSpace>
struct KDTreeMeshAdaptor
{
using MeshView = typename FeSpace::GridView;
using SizeType = typename FeSpace::LocalIndexSet::size_type;
using ValueType = double;
static constexpr dimension = MeshView::dimension;
static constexpr dimensionworld = MeshView::dimensionworld;
using Codim0 = typename GridView::template Codim<0>;
using PointType = typename Codim0::Geometry::GlobalCoordinate;
using VectorOfPointsType = std::vector<PointType> ;
using DataType = typename MeshView::Grid::EntitySeed;
using VectorOfDataType = std::vector<DataType>;
using Distance = nanoflann::metric_L2_Simple;
using Self = KDTreeMeshAdaptor<FeSpace>;
using Metric = typename Distance::template traits<ValueType, Self>::distance_t;
using IndexType = nanoflann::KDTreeSingleIndexAdaptor<Metric, Self, dimensionworld, SizeType>;
public:
unique_ptr<IndexType> index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index.
FeSpace const& feSpace;
VectorOfPointsType_ m_points;
VectorOfDataType_ m_data;
std::map<std::hash<DataType>, DataType> shapeValues;
public:
/// Constructor: takes a const ref to the vector of vectors object with the data points
KDTreeMeshAdaptor(FeSpace const& feSpace_,
const int leaf_max_size = 10)
: feSpace(feSpace_)
, localView(feSpace.localView())
{
init();
index = make_unique<IndexType>(dimensionworld, *this /* adaptor */,
nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dimensionworld));
index->buildIndex();
}
/// Destructor.
~KDTreeMeshAdaptor() {}
void init()
{
for (auto const& element : elements(feSpace.gridView())) {
m_points.push_back(element.geometry().center());
m_data.push_back(element.seed());
}
}
void reinit(const int leaf_max_size = 10)
{
m_points.clear();
m_data.clear();
init();
index.reset(new IndexType(dimensionworld, *this /* adaptor */,
nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dimensionworld));
index->buildIndex();
}
/** Query for the \a num_closest closest points to a given point (entered as query_point[0:dim-1]).
* Note that this is a short-cut method for index->findNeighbors().
* The user can also call index->... methods as desired.
* \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface.
*/
inline void query(const ValueType *query_point,
const std::size_t num_closest,
SizeType *out_indices,
ValueType *out_distances_sq,
const int nChecks_IGNORED = 10) const
{
nanoflann::KNNResultSet<ValueType, SizeType> resultSet(num_closest);
resultSet.init(out_indices, out_distances_sq);
index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
}
/** @name Interface expected by KDTreeSingleIndexAdaptor
* @{ */
Self const& derived() const
{
return *this;
}
Self& derived()
{
return *this;
}
// Must return the number of data points
inline std::size_t kdtree_get_point_count() const
{
return m_points.size();
}
// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
inline ValueType kdtree_distance(const double *p1,
const SizeType idx_p2,
std::size_t size) const
{
ValueType s = 0.0;
for (std::size_t i = 0; i < size; i++) {
const ValueType d = p1[i] - m_points[idx_p2][i];
s += d*d;
}
return s;
}
// Returns the dim'th component of the idx'th point in the class:
inline ValueType kdtree_get_pt(const SizeType idx, std::size_t dim) const
{
return m_points[idx][dim];
}
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
// Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
template <class BBOX>
bool kdtree_get_bbox(BBOX &bb) const