diff --git a/dune/stuff/CMakeLists.txt b/dune/stuff/CMakeLists.txt index 74a57788e163b623f3c79ea12d3579c4c99356a8..618e9b4f4265d41a962ac481e02e96378df5747f 100644 --- a/dune/stuff/CMakeLists.txt +++ b/dune/stuff/CMakeLists.txt @@ -6,6 +6,7 @@ set(lib_dune_stuff_sources common/filesystem.cc common/color.cc common/convergence-study.cc + common/localization-study.cc common/logging.cc common/logstreams.cc common/profiler.cc diff --git a/dune/stuff/common/convergence-study.cc b/dune/stuff/common/convergence-study.cc index 21a5d9f33369d25cd61da415bd0d51133b17b2b8..45701ab8da0b40a4b215d6d933472792c844b13d 100644 --- a/dune/stuff/common/convergence-study.cc +++ b/dune/stuff/common/convergence-study.cc @@ -25,12 +25,15 @@ ConvergenceStudy::ConvergenceStudy(const std::vector<std::string> only_these_nor std::vector<std::string> ConvergenceStudy::used_norms() const { - std::vector<std::string> used_norms; - for (auto norm : provided_norms()) - if (only_these_norms_.empty() - || std::find(only_these_norms_.begin(), only_these_norms_.end(), norm) != only_these_norms_.end()) - used_norms.push_back(norm); - return used_norms; + if (only_these_norms_.empty()) + return provided_norms(); + else { + std::vector<std::string> ret; + for (auto norm : provided_norms()) + if (std::find(only_these_norms_.begin(), only_these_norms_.end(), norm) != only_these_norms_.end()) + ret.push_back(norm); + return ret; + } } // ... used_norms(...) std::map<std::string, std::vector<double>> ConvergenceStudy::run(const bool relative, std::ostream& out, @@ -40,8 +43,7 @@ std::map<std::string, std::vector<double>> ConvergenceStudy::run(const bool rela DUNE_THROW(Dune::InvalidStateException, "You have to provide at least one norm!"); const auto actually_used_norms = used_norms(); if (actually_used_norms.size() == 0) - DUNE_THROW(Dune::InvalidStateException, - "There are no common norms in 'provided_norms()' and 'only_use_this_norms'!"); + DUNE_THROW(Dune::InvalidStateException, "There are no common norms in 'provided_norms()' and 'only_these_norms'!"); std::map<std::string, std::vector<double>> ret; for (const auto& norm : actually_used_norms) diff --git a/dune/stuff/common/localization-study.cc b/dune/stuff/common/localization-study.cc new file mode 100644 index 0000000000000000000000000000000000000000..49c7a5c92388bd241b5b4d37fc7177680ffff11f --- /dev/null +++ b/dune/stuff/common/localization-study.cc @@ -0,0 +1,123 @@ +// This file is part of the dune-stuff project: +// https://github.com/wwu-numerik/dune-stuff +// Copyright holders: Rene Milk, Felix Schindler +// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) + +#include "config.h" + +#include <dune/stuff/common/string.hh> + +#include "localization-study.hh" + +namespace Dune { +namespace Stuff { +namespace Common { + + +LocalizationStudy::LocalizationStudy(const std::vector<std::string> only_these_indicators) + : only_these_indicators_(only_these_indicators) +{ +} + +LocalizationStudy::~LocalizationStudy() +{ +} + +std::vector<std::string> LocalizationStudy::used_indicators() const +{ + if (only_these_indicators_.empty()) + return provided_indicators(); + else { + std::vector<std::string> ret; + for (auto indicator : provided_indicators()) + if (std::find(only_these_indicators_.begin(), only_these_indicators_.end(), indicator) + != only_these_indicators_.end()) + ret.push_back(indicator); + return ret; + } +} // ... used_indicators(...) + +void LocalizationStudy::run_localization(std::ostream& out) +{ + if (provided_indicators().size() == 0) + DUNE_THROW(Dune::InvalidStateException, "You have to provide at least one indicator!"); + const auto actually_used_indicators = used_indicators(); + if (actually_used_indicators.size() == 0) + DUNE_THROW(Dune::InvalidStateException, + "There are no common indicators in 'provided_indicators()' and 'only_these_indicators'!"); + + // build table header + out << identifier() << std::endl; + const size_t total_width = 80; + std::string header_line = + std::string(" ||") + " L^2 difference " + "|" + " L^oo difference " + "|" + " standard deviation "; + size_t first_column_size = 0; + for (auto id : actually_used_indicators) + first_column_size = std::max(first_column_size, id.size()); + first_column_size = std::max(first_column_size, total_width - header_line.size() - 1); + std::string first_column_str = ""; + for (size_t ii = 0; ii < first_column_size; ++ii) + first_column_str += " "; + header_line = std::string(" ") + first_column_str + header_line; + // print table header + if (identifier().size() > header_line.size()) + out << Stuff::Common::whitespaceify(identifier(), '=') << "\n"; + else + out << Stuff::Common::whitespaceify(header_line, '=') << "\n"; + out << header_line << "\n"; + const std::string thin_delimiter = Stuff::Common::whitespaceify(" " + first_column_str + " ", '-') + "++" + + Stuff::Common::whitespaceify(" L^2 difference ", '-') + "+" + + Stuff::Common::whitespaceify(" L^oo difference ", '-') + "+" + + Stuff::Common::whitespaceify(" standard deviation ", '-'); + const std::string thick_delimiter = Stuff::Common::whitespaceify(" " + first_column_str + " ", '=') + "++" + + Stuff::Common::whitespaceify(" L^2 difference ", '=') + "+" + + Stuff::Common::whitespaceify(" L^oo difference ", '=') + "+" + + Stuff::Common::whitespaceify(" standard deviation ", '='); + out << thick_delimiter << std::endl; + // comput reference indicators + const auto reference_indicators = compute_reference_indicators(); + if (reference_indicators.size() == 0) + DUNE_THROW(Exceptions::requirements_not_met, "Given reference indicators must not be empty!"); + // loop over all indicators + for (size_t ind = 0; ind < actually_used_indicators.size(); ++ind) { + const std::string indicator_id = actually_used_indicators[ind]; + // enlarge/cap id to first_column_size chars + std::string id_str = indicator_id.empty() ? "???" : indicator_id; + if (id_str.size() > first_column_size) + id_str = id_str.substr(0, first_column_size); + else if (id_str.size() < first_column_size) { + const double missing = (double(first_column_size) - id_str.size()) / 2.0; + for (size_t ii = 0; ii < missing; ++ii) + id_str = " " + id_str + " "; + if (id_str.size() == (first_column_size - 1)) + id_str = " " + id_str; + } + assert(id_str.size() == first_column_size); + // print first column + out << " " << id_str << " || " << std::flush; + // compute indicators + const auto indicators = compute_indicators(indicator_id); + if (indicators.size() != reference_indicators.size()) + DUNE_THROW(Exceptions::requirements_not_met, + "Given indicators of type '" << indicator_id << "' are of wrong length (is " << indicators.size() + << ", should be " + << reference_indicators.size() + << ")!"); + const auto difference = reference_indicators - indicators; + // compute L^2 difference + out << std::setw(18) << std::setprecision(2) << std::scientific << difference.l2_norm() << std::flush; + // compute L^oo difference + out << " | " << std::setw(18) << std::setprecision(2) << std::scientific << difference.sup_norm() << std::flush; + // compute standard deviation + out << " | " << std::setw(18) << std::setprecision(2) << std::scientific << difference.standard_deviation() + << std::flush; + if (ind < (actually_used_indicators.size() - 1)) + out << "\n" << thin_delimiter; + out << std::endl; + } // loop over all indicators +} // ... run(...) + + +} // namespace Common +} // namespace Stuff +} // namespace Dune diff --git a/dune/stuff/common/localization-study.hh b/dune/stuff/common/localization-study.hh new file mode 100644 index 0000000000000000000000000000000000000000..4ef15e8e587fabfe0fb8d4052d127535f18fa1c2 --- /dev/null +++ b/dune/stuff/common/localization-study.hh @@ -0,0 +1,50 @@ +// This file is part of the dune-stuff project: +// https://github.com/wwu-numerik/dune-stuff +// Copyright holders: Rene Milk, Felix Schindler +// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) + +#ifndef DUNE_STUFF_COMMON_LOCALIZATION_STUDY_HH +#define DUNE_STUFF_COMMON_LOCALIZATION_STUDY_HH + +#include <vector> +#include <map> +#include <string> +#include <iostream> + +#include <dune/stuff/common/exceptions.hh> +#include <dune/stuff/la/container/common.hh> + +namespace Dune { +namespace Stuff { +namespace Common { + + +class LocalizationStudy +{ +public: + LocalizationStudy(const std::vector<std::string> only_these_indicators = {}); + + virtual ~LocalizationStudy(); + + virtual std::string identifier() const = 0; + + virtual LA::CommonDenseVector<double> compute_reference_indicators() const = 0; + + virtual std::vector<std::string> provided_indicators() const = 0; + + virtual LA::CommonDenseVector<double> compute_indicators(const std::string type) const = 0; + + std::vector<std::string> used_indicators() const; + + /*std::map< std::string, std::vector< double > >*/ void run_localization(std::ostream& out = std::cout); + +private: + const std::vector<std::string> only_these_indicators_; +}; // class LocalizationStudy + + +} // namespace Common +} // namespace Stuff +} // namespace Dune + +#endif // DUNE_STUFF_COMMON_LOCALIZATION_STUDY_HH diff --git a/dune/stuff/test/common.cxx b/dune/stuff/test/common.cxx index a8f336e724e732fe3ed01d09022add5268d928c1..7b24586a9d959e4d45e94ea1caad3c538bb21a6e 100644 --- a/dune/stuff/test/common.cxx +++ b/dune/stuff/test/common.cxx @@ -55,8 +55,8 @@ std::pair<size_t, ssize_t> convert_to_scientific(const double number, const size } // namespace internal -void check_for_success(const Dune::Stuff::Common::ConvergenceStudy& study, - const std::map<std::string, std::vector<double>>& results_map) +void check_eoc_study_for_success(const Dune::Stuff::Common::ConvergenceStudy& study, + const std::map<std::string, std::vector<double>>& results_map) { for (const auto& norm : study.used_norms()) { const auto expected_results = study.expected_results(norm); diff --git a/dune/stuff/test/common.hh b/dune/stuff/test/common.hh index 1dbc8783f5efc2410dc5a794a8e5ea66d932373e..0e01ece621dfaa98952d65f2f0b7cbe828cf0da8 100644 --- a/dune/stuff/test/common.hh +++ b/dune/stuff/test/common.hh @@ -70,8 +70,8 @@ std::pair<size_t, ssize_t> convert_to_scientific(const double number, const size } // namespace internal -void check_for_success(const Dune::Stuff::Common::ConvergenceStudy& study, - const std::map<std::string, std::vector<double>>& errors_map); +void check_eoc_study_for_success(const Dune::Stuff::Common::ConvergenceStudy& study, + const std::map<std::string, std::vector<double>>& errors_map); } // namespace Test diff --git a/dune/stuff/test/common_fixed_map.cc b/dune/stuff/test/common_fixed_map.cc index 1d362b65376cd7cc2b3fcedba09565bff7e60f8f..abbf22098560568738d823b679c37b59dff516ed 100644 --- a/dune/stuff/test/common_fixed_map.cc +++ b/dune/stuff/test/common_fixed_map.cc @@ -26,15 +26,19 @@ TEST(FixedMapTest, All) EXPECT_THROW(too_small["1"], Dune::RangeError); for (int i : {0, 1, 2}) { EXPECT_EQ(i, too_big[toString(i)]); + EXPECT_NE(too_big.find(toString(i)), too_big.end()); } for (int DUNE_UNUSED(i) : {3, 4, 5}) { EXPECT_EQ(int(), too_big[std::string()]); + EXPECT_EQ(too_big.find(toString(i)), too_big.end()); } - auto size = fits.size(); + auto size = fits.size(); + const auto end = fits.end(); for (auto& pt : fits) { - int value = pt.second; - std::string key = pt.first; + const int value = pt.second; + const std::string key = pt.first; EXPECT_EQ(key, toString(value)); + EXPECT_NE(fits.find(key), end); size--; } EXPECT_EQ(0, size);