diff --git a/dune/gdt/local/numerical-fluxes/kinetic.hh b/dune/gdt/local/numerical-fluxes/kinetic.hh index 925c30b608b7f73b09acab4257b30df970701b79..5783fecb35ba1de40ffc0451a3a22fcd0399d0a3 100644 --- a/dune/gdt/local/numerical-fluxes/kinetic.hh +++ b/dune/gdt/local/numerical-fluxes/kinetic.hh @@ -48,17 +48,17 @@ class NumericalKineticFlux public: using typename BaseType::FluxType; - using typename BaseType::FunctionType; using typename BaseType::LocalIntersectionCoords; using typename BaseType::PhysicalDomainType; using typename BaseType::StateType; + using typename BaseType::XIndependentFluxType; NumericalKineticFlux(const FluxType& flx, const MomentBasis& basis) : BaseType(flx) , basis_(basis) {} - NumericalKineticFlux(const FunctionType& flx, const MomentBasis& basis) + NumericalKineticFlux(const XIndependentFluxType& flx, const MomentBasis& basis) : BaseType(flx) , basis_(basis) {} @@ -72,20 +72,20 @@ public: using BaseType::apply; using BaseType::flux; + using BaseType::intersection; - StateType apply(const I& intersection, - const LocalIntersectionCoords& /*x*/, + StateType apply(const LocalIntersectionCoords& /*x*/, const StateType& u, const StateType& v, const PhysicalDomainType& n, const XT::Common::Parameter& /*param*/ = {}) const override final { // find direction of unit outer normal (we assume an axis-aligned cube grid) - size_t direction = intersection.indexInInside() / 2; + size_t direction = intersection().indexInInside() / 2; if (dynamic_cast<const EntropyFluxType*>(&flux()) != nullptr) { return dynamic_cast<const EntropyFluxType*>(&flux())->evaluate_kinetic_flux( - intersection.inside(), - intersection.neighbor() ? intersection.outside() : intersection.inside(), + intersection().inside(), + intersection().neighbor() ? intersection().outside() : intersection().inside(), u, v, n, diff --git a/dune/gdt/momentmodels/basisfunctions/hatfunctions.hh b/dune/gdt/momentmodels/basisfunctions/hatfunctions.hh index af900d860191ec59e7c32ea0979d865456097b75..680f7749e15b0351191bc0c689f71e1382916ab1 100644 --- a/dune/gdt/momentmodels/basisfunctions/hatfunctions.hh +++ b/dune/gdt/momentmodels/basisfunctions/hatfunctions.hh @@ -63,6 +63,13 @@ public: return "hatfunctions"; } + static size_t default_quad_order() + { + return 15; + } + + using BaseType::default_quad_refinements; + HatFunctionMomentBasis(const QuadraturesType& quadratures) : BaseType(quadratures) , triangulation_(BaseType::create_1d_triangulation(dimRange - 1)) @@ -70,7 +77,8 @@ public: BaseType::initialize_base_values(); } - HatFunctionMomentBasis(const size_t quad_order = 15, const size_t DXTC_DEBUG_ONLY(quad_refinements) = 0) + HatFunctionMomentBasis(const size_t quad_order = default_quad_order(), + const size_t DXTC_DEBUG_ONLY(quad_refinements) = default_quad_refinements()) : BaseType(BaseType::gauss_lobatto_quadratures(dimRange - 1, quad_order)) , triangulation_(BaseType::create_1d_triangulation(dimRange - 1)) { @@ -355,6 +363,13 @@ public: using BaseType::barycentre_rule; + static size_t default_quad_order() + { + return refinements == 0 ? 15 : 9; + } + + using BaseType::default_quad_refinements; + HatFunctionMomentBasis(const QuadraturesType& quadratures) : BaseType(refinements, quadratures) { @@ -371,7 +386,8 @@ public: BaseType::initialize_base_values(); } - HatFunctionMomentBasis(const size_t quad_order = (refinements == 0 ? 15 : 9), const size_t quad_refinements = 0) + HatFunctionMomentBasis(const size_t quad_order = default_quad_order(), + const size_t quad_refinements = default_quad_refinements()) : BaseType(refinements) { const QuadratureRule<RangeFieldType, 2> reference_quadrature_rule = diff --git a/dune/gdt/momentmodels/basisfunctions/interface.hh b/dune/gdt/momentmodels/basisfunctions/interface.hh index af132d836433ddf4dcc3f2160013bfed989c6ddf..6b76300201b0ffc952de51cf4edb9c3367eb5116 100644 --- a/dune/gdt/momentmodels/basisfunctions/interface.hh +++ b/dune/gdt/momentmodels/basisfunctions/interface.hh @@ -168,6 +168,17 @@ public: using MergedQuadratureIterator = typename XT::Data::MergedQuadrature<RangeFieldType, dimDomain>::MergedQuadratureIterator; + static size_t default_quad_order() + { + DUNE_THROW(Dune::NotImplemented, "Please overwrite this function in derived classes!"); + return 0; + } + + static size_t default_quad_refinements() + { + return 0; + } + MomentBasisInterface(const QuadraturesType& quadratures = QuadraturesType()) : quadratures_(quadratures) {} diff --git a/dune/gdt/momentmodels/basisfunctions/legendre.hh b/dune/gdt/momentmodels/basisfunctions/legendre.hh index 93162bf940b6db4b58c55e75ddb57aa17185d987..8aad82d2b0c85d92ac2bc0b4353c566dafc1878c 100644 --- a/dune/gdt/momentmodels/basisfunctions/legendre.hh +++ b/dune/gdt/momentmodels/basisfunctions/legendre.hh @@ -42,7 +42,18 @@ public: BaseType::initialize_base_values(); } - LegendreMomentBasis(const size_t quad_order = 197, const size_t quad_refinements = 1) + static size_t default_quad_order() + { + return 2 * order + 40; + } + + static size_t default_quad_refinements() + { + return 1; + } + + LegendreMomentBasis(const size_t quad_order = default_quad_order(), + const size_t quad_refinements = default_quad_refinements()) : BaseType(BaseType::gauss_lobatto_quadratures(std::pow(2, quad_refinements), quad_order)) { BaseType::initialize_base_values(); diff --git a/dune/gdt/momentmodels/basisfunctions/partial_moments.hh b/dune/gdt/momentmodels/basisfunctions/partial_moments.hh index b38dc638d340b3d6c24e844ba8339796ab72b15f..a8531bf02c97ed0896a2ac3d716e7ccde55515a4 100644 --- a/dune/gdt/momentmodels/basisfunctions/partial_moments.hh +++ b/dune/gdt/momentmodels/basisfunctions/partial_moments.hh @@ -70,6 +70,13 @@ public: return "pcw"; } + static size_t default_quad_order() + { + return 15; + } + + using BaseType::default_quad_refinements; + PartialMomentBasis(const QuadraturesType& quadratures) : BaseType(quadratures) , triangulation_(BaseType::create_1d_triangulation(num_intervals)) @@ -77,7 +84,8 @@ public: BaseType::initialize_base_values(); } - PartialMomentBasis(const size_t quad_order = 15, const size_t DXTC_DEBUG_ONLY(quad_refinements) = 0) + PartialMomentBasis(const size_t quad_order = default_quad_order(), + const size_t DXTC_DEBUG_ONLY(quad_refinements) = default_quad_refinements()) : BaseType(BaseType::gauss_lobatto_quadratures(num_intervals, quad_order)) , triangulation_(BaseType::create_1d_triangulation(num_intervals)) { @@ -406,6 +414,13 @@ public: using BaseType::barycentre_rule; + static size_t default_quad_order() + { + return refinements == 0 ? 15 : 9; + } + + using BaseType::default_quad_refinements; + PartialMomentBasis(const QuadraturesType& quadratures) : BaseType(refinements, quadratures) { @@ -421,7 +436,8 @@ public: BaseType::initialize_base_values(); } - PartialMomentBasis(const size_t quad_order = (refinements == 0 ? 15 : 9), const size_t quad_refinements = 0) + PartialMomentBasis(const size_t quad_order = default_quad_order(), + const size_t quad_refinements = default_quad_refinements()) : BaseType(refinements) { const QuadratureRule<RangeFieldType, 2> reference_quadrature_rule = diff --git a/dune/gdt/momentmodels/basisfunctions/spherical_harmonics.hh b/dune/gdt/momentmodels/basisfunctions/spherical_harmonics.hh index c13c036dfe9d244ef46ff9f781384499eccf219a..ad590e5d58161c03f710dc2c16aecbe4d3129319 100644 --- a/dune/gdt/momentmodels/basisfunctions/spherical_harmonics.hh +++ b/dune/gdt/momentmodels/basisfunctions/spherical_harmonics.hh @@ -50,14 +50,21 @@ public: using typename BaseType::StringifierType; static_assert(order <= std::numeric_limits<int>::max(), ""); + static size_t default_quad_order() + { + return 2 * order + 8; + } + + using BaseType::default_quad_refinements; + SphericalHarmonicsMomentBasis(const QuadraturesType& quadratures) : BaseType(quadratures) { BaseType::initialize_base_values(); } - SphericalHarmonicsMomentBasis(const size_t quad_order = 2 * order + 8, - const size_t DXTC_DEBUG_ONLY(quad_refinements) = 0) + SphericalHarmonicsMomentBasis(const size_t quad_order = default_quad_order(), + const size_t DXTC_DEBUG_ONLY(quad_refinements) = default_quad_refinements()) : BaseType(XT::Data::OctantQuadratures<DomainFieldType>::get(quad_order)) { assert(quad_refinements == 0 && "Refinement of the quadrature intervals not implemented for this basis!"); @@ -289,14 +296,21 @@ public: using typename BaseType::RangeType; using typename BaseType::StringifierType; + static size_t default_quad_order() + { + return 2 * order + 8; + } + + using BaseType::default_quad_refinements; + RealSphericalHarmonicsMomentBasis(const QuadraturesType& quadratures) : BaseType(quadratures) { BaseType::initialize_base_values(); } - RealSphericalHarmonicsMomentBasis(const size_t quad_order = 2 * order + 8, - const size_t DXTC_DEBUG_ONLY(quad_refinements) = 0) + RealSphericalHarmonicsMomentBasis(const size_t quad_order = default_quad_order(), + const size_t DXTC_DEBUG_ONLY(quad_refinements) = default_quad_refinements()) : BaseType(XT::Data::OctantQuadratures<DomainFieldType>::get(quad_order)) { assert(quad_refinements == 0 && "Refinement of the quadrature intervals not implemented for this basis!"); diff --git a/dune/gdt/momentmodels/entropyflux.hh b/dune/gdt/momentmodels/entropyflux.hh index 52b43473c60be76b3e49761ae7188d2cdbdc42ff..2710961bb8a9dd85135a79a4d267a39f5eee3ace 100644 --- a/dune/gdt/momentmodels/entropyflux.hh +++ b/dune/gdt/momentmodels/entropyflux.hh @@ -157,11 +157,33 @@ public: const size_t k_max = 1000, const RangeFieldType epsilon = std::pow(2, -52)) : index_set_(grid_view.indexSet()) + , use_thread_cache_(true) + , use_entity_cache_(true) , entity_caches_(index_set_.size(0), LocalCacheType(cache_size)) , mutexes_(index_set_.size(0)) , implementation_(basis_functions, tau, epsilon_gamma, chi, xi, r_sequence, k_0, k_max, epsilon) {} + void enable_thread_cache() + { + use_thread_cache_ = true; + } + + void disable_thread_cache() + { + use_thread_cache_ = false; + } + + void enable_entity_cache() + { + use_entity_cache_ = true; + } + + void disable_entity_cache() + { + use_entity_cache_ = false; + } + static const constexpr bool available = true; class Localfunction : public LocalFunctionType @@ -175,11 +197,15 @@ public: Localfunction(const IndexSetType& index_set, std::vector<LocalCacheType>& entity_caches, + const bool use_thread_cache, + const bool use_entity_cache, std::vector<std::mutex>& mutexes, const ImplementationType& implementation) : index_set_(index_set) , thread_cache_(cache_size) , entity_caches_(entity_caches) + , use_thread_cache_(use_thread_cache) + , use_entity_cache_(use_entity_cache) , mutexes_(mutexes) , implementation_(implementation) {} @@ -209,7 +235,7 @@ public: // calculate (inf-norm) distance to isotropic moment with same density RangeFieldType distance = (u - u_iso_scaled).infinity_norm(); VectorType alpha_start = XT::Common::convert_to<VectorType>(alpha_iso + alpha_iso_prime * std::log(density)); - if (!XT::Common::FloatCmp::eq(distance, 0.)) { + if (!XT::Common::FloatCmp::eq(distance, 0.) && use_entity_cache_) { // calculate distance to closest moment in entity_cache const auto entity_cache_dist_and_it = entity_cache_->find_closest(u); const auto& entity_cache_dist = entity_cache_dist_and_it.first; @@ -217,7 +243,7 @@ public: distance = entity_cache_dist; alpha_start = entity_cache_dist_and_it.second->second; } - if (!XT::Common::FloatCmp::eq(distance, 0.)) { + if (!XT::Common::FloatCmp::eq(distance, 0.) && use_thread_cache_) { // calculate distance to closest moment in thread_cache const auto thread_cache_dist_and_it = thread_cache_.find_closest(u); const auto& thread_cache_dist = thread_cache_dist_and_it.first; @@ -232,8 +258,10 @@ public: return std::make_unique<AlphaReturnType>(std::make_pair(alpha_start, std::make_pair(u, 0.))); } else { auto ret = implementation_.get_alpha(u, alpha_start, regularize); - entity_cache_->insert(ret->second.first, ret->first); - thread_cache_.insert(ret->second.first, ret->first); + if (use_entity_cache_) + entity_cache_->insert(ret->second.first, ret->first); + if (use_thread_cache_) + thread_cache_.insert(ret->second.first, ret->first); return std::move(ret); } } @@ -259,6 +287,8 @@ public: const IndexSetType& index_set_; mutable LocalCacheType thread_cache_; std::vector<LocalCacheType>& entity_caches_; + const bool use_thread_cache_; + const bool use_entity_cache_; std::vector<std::mutex>& mutexes_; const ImplementationType& implementation_; LocalCacheType* entity_cache_; @@ -272,12 +302,14 @@ public: virtual std::unique_ptr<LocalFunctionType> local_function() const override final { - return std::make_unique<Localfunction>(index_set_, entity_caches_, mutexes_, implementation_); + return std::make_unique<Localfunction>( + index_set_, entity_caches_, use_thread_cache_, use_entity_cache_, mutexes_, implementation_); } virtual std::unique_ptr<Localfunction> derived_local_function() const { - return std::make_unique<Localfunction>(index_set_, entity_caches_, mutexes_, implementation_); + return std::make_unique<Localfunction>( + index_set_, entity_caches_, use_thread_cache_, use_entity_cache_, mutexes_, implementation_); } StateType evaluate_kinetic_flux(const E& inside_entity, @@ -303,6 +335,8 @@ public: private: const IndexSetType& index_set_; + bool use_thread_cache_; + bool use_entity_cache_; mutable std::vector<LocalCacheType> entity_caches_; mutable std::vector<std::mutex> mutexes_; ImplementationType implementation_; diff --git a/dune/gdt/momentmodels/entropyflux_implementations.hh b/dune/gdt/momentmodels/entropyflux_implementations.hh index 5f25b1fcd39f8e7af47a0b11e3a20f2e8d9ec306..ed141053fb423640626b0a71da87045edafe23c2 100644 --- a/dune/gdt/momentmodels/entropyflux_implementations.hh +++ b/dune/gdt/momentmodels/entropyflux_implementations.hh @@ -463,7 +463,6 @@ protected: 1); #else const size_t num_quad_points = quad_points_.size(); - std::fill(scalar_products.begin(), scalar_products.end(), 0.); for (size_t ll = 0; ll < num_quad_points; ++ll) { const auto* basis_ll = &(M.get_entry_ref(ll, 0.)); scalar_products[ll] = std::inner_product(beta_in.begin(), beta_in.end(), basis_ll, 0.); @@ -743,7 +742,7 @@ public: // regularize u v = u_prime; if (r > 0) { - beta_in = get_isotropic_alpha(u); + beta_in = get_isotropic_alpha(v); VectorType r_times_u_iso = u_iso; r_times_u_iso *= r; v *= 1 - r; @@ -942,7 +941,7 @@ public: // regularize u v = u_prime; if (r > 0) { - alpha_k = get_isotropic_alpha(u); + alpha_k = get_isotropic_alpha(v); VectorType r_times_u_iso = u_iso; r_times_u_iso *= r; v *= 1 - r; @@ -1276,7 +1275,7 @@ public: // regularize u *v = *u_prime; if (r > 0.) { - *beta_in = *get_isotropic_alpha(u); + *beta_in = *get_isotropic_alpha(*v); // calculate v = (1-r) u + r u_iso // use beta_out as storage for u_iso_in * r *v *= (1 - r); @@ -1848,6 +1847,14 @@ public: return ret; } + VectorType get_isotropic_alpha(const VectorType& u) const + { + DomainType u_domain; + for (size_t ii = 0; ii < basis_dimDomain; ++ii) + u_domain[ii] = u.get_entry(ii); + return get_isotropic_alpha(u_domain); + } + virtual RangeReturnType evaluate(const DomainType& u, const XT::Common::Parameter& /*param*/ = {}) const override final { @@ -1985,7 +1992,7 @@ public: // regularize u v = u_prime; if (r > 0) { - alpha_k = get_isotropic_alpha(u); + alpha_k = get_isotropic_alpha(v); tmp_vec = u_iso; tmp_vec *= r; v *= 1 - r; @@ -2615,7 +2622,7 @@ public: // regularize u v = u_prime; if (r > 0) { - alpha_k = get_isotropic_alpha(u); + alpha_k = get_isotropic_alpha(v); VectorType r_times_u_iso(u_iso); r_times_u_iso *= r; v *= 1 - r; @@ -3023,16 +3030,15 @@ public: using QuadraturePointsType = FieldVector<std::vector<RangeFieldType>, num_intervals>; using QuadratureWeightsType = FieldVector<std::vector<RangeFieldType>, num_intervals>; - explicit EntropyBasedFluxImplementation( - const MomentBasis& basis_functions, - const RangeFieldType tau = 1e-9, - const RangeFieldType epsilon_gamma = 0.01, - const RangeFieldType chi = 0.5, - const RangeFieldType xi = 1e-3, - const std::vector<RangeFieldType> r_sequence = {0, 1e-8, 1e-6, 1e-4, 1e-3, 1e-2, 5e-2, 0.1, 0.5, 1}, - const size_t k_0 = 500, - const size_t k_max = 1000, - const RangeFieldType epsilon = std::pow(2, -52)) + explicit EntropyBasedFluxImplementation(const MomentBasis& basis_functions, + const RangeFieldType tau, + const RangeFieldType epsilon_gamma, + const RangeFieldType chi, + const RangeFieldType xi, + const std::vector<RangeFieldType> r_sequence, + const size_t k_0, + const size_t k_max, + const RangeFieldType epsilon) : basis_functions_(basis_functions) , grid_points_(basis_functions_.triangulation()) , tau_(tau) @@ -3186,7 +3192,7 @@ public: // regularize u v = u_prime; if (r > 0) { - alpha_k = get_isotropic_alpha(u); + alpha_k = get_isotropic_alpha(v); VectorType r_times_u_iso(u_iso); r_times_u_iso *= r; v *= 1 - r; diff --git a/dune/gdt/momentmodels/entropysolver.hh b/dune/gdt/momentmodels/entropysolver.hh index bb1cbf4cb7b581d86261188a2c9525da77e3695a..c43f48c3204047ace559c0e3d7180b6df95dfd94 100644 --- a/dune/gdt/momentmodels/entropysolver.hh +++ b/dune/gdt/momentmodels/entropysolver.hh @@ -88,8 +88,6 @@ public: for (size_t ii = 0; ii < dimRange; ++ii) u[ii] = local_source_->dofs().get_entry(ii); const auto& basis_functions = analytical_flux_.basis_functions(); - thread_local auto vector_indices = source_.space().mapper().global_indices(entity); - source_.space().mapper().global_indices(entity, vector_indices); basis_functions.ensure_min_density(u, min_acceptable_density_); local_flux_->bind(entity); const auto alpha_ret = local_flux_->get_alpha(u, true); diff --git a/dune/gdt/operators/reconstruction/internal.hh b/dune/gdt/operators/reconstruction/internal.hh index d65f93d949448ce5d9603cc55b8232a89c34a826..f2453d752604ff9d5ad22567df5a82d042f64801 100644 --- a/dune/gdt/operators/reconstruction/internal.hh +++ b/dune/gdt/operators/reconstruction/internal.hh @@ -194,9 +194,9 @@ public: const XT::Common::Parameter& param) override final { local_flux_->bind(entity); - local_flux_->jacobian(x_local, u, *jacobian_, param); - for (size_t dd = 0; dd < dimDomain; ++dd) { - try { + try { + local_flux_->jacobian(x_local, u, *jacobian_, param); + for (size_t dd = 0; dd < dimDomain; ++dd) { if (false) { ; #if HAVE_MKL || HAVE_LAPACKE @@ -249,14 +249,17 @@ public: if (info || eigenvectors_rcond_ < 1e-5) DUNE_THROW(Dune::MathError, "Eigenvector condition too high!"); #endif - } catch (const Dune::MathError&) { + } // dd + } catch (const Dune::MathError&) { + for (size_t dd = 0; dd < dimDomain; ++dd) { // use scalar limiters, i.e. eigenvectors matrix is eye-matrix. XT::LA::eye_matrix((*eigenvectors_)[dd]); std::fill(eigenvalues_[dd].begin(), eigenvalues_[dd].end(), 1.); (*QR_)[dd] = (*eigenvectors_)[dd]; XT::LA::qr((*QR_)[dd], tau_[dd], permutations_[dd]); - } - } // dd + } // dd + } + // we do not need jacobian_ anymore if the flux is affine, so save memory if (flux_is_affine_) jacobian_ = nullptr; @@ -343,11 +346,11 @@ public: { local_flux_->bind(entity); const FluxDomainType nonblocked_u = u.operator FluxDomainType(); - local_flux_->jacobian(x_local, nonblocked_u, *nonblocked_jacobian_, param); - *jacobian_ = *nonblocked_jacobian_; - for (size_t dd = 0; dd < dimDomain; ++dd) { - for (size_t jj = 0; jj < num_blocks; ++jj) { - try { + try { + local_flux_->jacobian(x_local, nonblocked_u, *nonblocked_jacobian_, param); + *jacobian_ = *nonblocked_jacobian_; + for (size_t dd = 0; dd < dimDomain; ++dd) { + for (size_t jj = 0; jj < num_blocks; ++jj) { if (block_size == 2) { const auto& jac = (*jacobian_)[dd].block(jj); const auto trace = jac[0][0] + jac[1][1]; @@ -414,15 +417,20 @@ public: if (info || eigenvectors_rcond_ < 1e-5) DUNE_THROW(Dune::MathError, "Eigenvector condition too high!"); #endif - } catch (const Dune::MathError&) { + } // jj + } // dd + } catch (const Dune::MathError&) { + for (size_t dd = 0; dd < dimDomain; ++dd) { + for (size_t jj = 0; jj < num_blocks; ++jj) { // use scalar limiters, i.e. eigenvectors matrix is eye-matrix. XT::LA::eye_matrix(eigenvectors_[dd].block(jj)); std::fill(eigenvalues_[dd][jj].begin(), eigenvalues_[dd][jj].end(), 1.); QR_[dd].block(jj) = eigenvectors_[dd].block(jj); XT::LA::qr(QR_[dd].block(jj), tau_[dd].block(jj), permutations_[dd].block(jj)); - } - } // jj - } // dd + } // jj + } // dd + } + if (flux_is_affine_) { jacobian_ = nullptr; nonblocked_jacobian_ = nullptr; diff --git a/dune/gdt/operators/reconstruction/linear.hh b/dune/gdt/operators/reconstruction/linear.hh index b350a297cd2bc4f3af544a3e72181ce919fce139..375214d16ad36f5fcb2236124d5350547ae3aea6 100644 --- a/dune/gdt/operators/reconstruction/linear.hh +++ b/dune/gdt/operators/reconstruction/linear.hh @@ -14,7 +14,6 @@ #include <dune/geometry/quadraturerules.hh> #include <dune/xt/common/fvector.hh> -#include <dune/xt/common/parallel/threadstorage.hh> #include <dune/xt/common/parameter.hh> #include <dune/xt/grid/walker.hh> @@ -396,6 +395,9 @@ private: }; // class LinearReconstructionOperator<...> +// Does not reconstruct a full first-order DG function, but only stores the reconstructed values at the intersection +// centers. This avoids the interpolation in this operator and the evaluation of the reconstructed function in the +// finite volume operator which are both quite expensive for large dimRange. template <class AnalyticalFluxImp, class BoundaryValueImp, class GV, diff --git a/dune/gdt/operators/reconstruction/slopes.hh b/dune/gdt/operators/reconstruction/slopes.hh index b1533e323be68f3781fba6ac6aaab30b471aabe7..3c94056799254ae3f03e60a78431f6cd7da5b5b6 100644 --- a/dune/gdt/operators/reconstruction/slopes.hh +++ b/dune/gdt/operators/reconstruction/slopes.hh @@ -1011,40 +1011,32 @@ public: private: void setup_linear_program() const { - // It should be possible to reuse the same ClpSimplex class over and over again, only changing the relevant columns. - // However, in rare cases the class seems to get corrupted, always claiming the LP is infeasible, even if it is not. - // Creating a new LP from time to time seems to fix this problem. - thread_local int counter; - ++counter; - if (!lp_ || !(counter % 100)) { - counter = 0; - // We start with creating a model with dimRange rows and num_quad_points+1 columns */ - assert(basis_values_->size() + dimRange < std::numeric_limits<int>::max()); - size_t num_cols = basis_values_->size() + dimRange; /* variables are x_1, ..., x_{num_quad_points}, theta_1, - ..., theta_{dimRange} */ - lp_ = std::make_unique<ClpSimplex>(false); - auto& lp = *lp_; - // set number of rows - lp.resize(num_rows, 0); - - // set columns for quadrature points - assert(basis_values_->size() == num_cols - dimRange); - static auto row_indices = create_row_indices(); - for (size_t ii = 0; ii < num_cols - dimRange; ++ii) { - // First argument: number of elements in column - // Second/Third argument: indices/values of column entries - // Fourth/Fifth argument: lower/upper column bound, i.e. lower/upper bound for x_i. As all x_i should be - // positive, set to 0/inf, which is the default. - // Sixth argument: Prefactor in objective for x_i, this is 0 for all x_i, which is also the default; - lp.addColumn(static_cast<int>(num_rows), row_indices.data(), &((*basis_values_)[ii][0])); - } + // We start with creating a model with dimRange rows and num_quad_points+1 columns */ + assert(basis_values_->size() + dimRange < std::numeric_limits<int>::max()); + size_t num_cols = basis_values_->size() + dimRange; /* variables are x_1, ..., x_{num_quad_points}, theta_1, + ..., theta_{dimRange} */ + lp_ = std::make_unique<ClpSimplex>(false); + auto& lp = *lp_; + // set number of rows + lp.resize(num_rows, 0); + + // set columns for quadrature points + assert(basis_values_->size() == num_cols - dimRange); + static auto row_indices = create_row_indices(); + for (size_t ii = 0; ii < num_cols - dimRange; ++ii) { + // First argument: number of elements in column + // Second/Third argument: indices/values of column entries + // Fourth/Fifth argument: lower/upper column bound, i.e. lower/upper bound for x_i. As all x_i should be + // positive, set to 0/inf, which is the default. + // Sixth argument: Prefactor in objective for x_i, this is 0 for all x_i, which is also the default; + lp.addColumn(static_cast<int>(num_rows), row_indices.data(), &((*basis_values_)[ii][0])); + } - // add theta columns (set to random values, will be set correctly in solve_linear_program) - // The bounds for theta should be [0,1]. Also sets the prefactor in the objective to 1 for the thetas. - for (size_t ii = 0; ii < dimRange; ++ii) - lp.addColumn(static_cast<int>(num_rows), row_indices.data(), &((*basis_values_)[0][0]), 0., 1., 1.); - lp.setLogLevel(0); - } // if (!lp_) + // add theta columns (set to random values, will be set correctly in solve_linear_program) + // The bounds for theta should be [0,1]. Also sets the prefactor in the objective to 1 for the thetas. + for (size_t ii = 0; ii < dimRange; ++ii) + lp.addColumn(static_cast<int>(num_rows), row_indices.data(), &((*basis_values_)[0][0]), 0., 1., 1.); + lp.setLogLevel(0); } // void setup_linear_program() VectorType solve_linear_program(const VectorType& u_char, diff --git a/dune/gdt/test/mn-discretization.hh b/dune/gdt/test/mn-discretization.hh index f0cae0222e4a5f884e8a6895474a79744cc15056..55c670d42a254cf8080defac9edb9aeae082088d 100644 --- a/dune/gdt/test/mn-discretization.hh +++ b/dune/gdt/test/mn-discretization.hh @@ -39,14 +39,15 @@ template <class TestCaseType> struct HyperbolicMnDiscretization { // returns: (l1norm, l2norm, linfnorm, MPI rank) - static std::pair<Dune::FieldVector<double, 3>, int> - run(size_t num_save_steps = 1, - size_t num_output_steps = 0, - size_t quad_order = TestCaseType::RealizabilityLimiterChooserType::quad_order, - std::string grid_size = "", - std::string overlap_size = "2", - double t_end = TestCaseType::t_end, - std::string filename = "") + static std::pair<Dune::FieldVector<double, 3>, int> run(size_t num_save_steps = 1, + size_t num_output_steps = 0, + size_t quad_order = size_t(-1), + size_t quad_refinements = size_t(-1), + size_t grid_size = size_t(-1), + size_t overlap_size = 2, + double t_end = 0., + std::string filename = "", + bool disable_thread_cache = false) { using namespace Dune; using namespace Dune::GDT; @@ -69,9 +70,9 @@ struct HyperbolicMnDiscretization //******************* create grid and FV space *************************************** auto grid_config = ProblemType::default_grid_cfg(); - if (!grid_size.empty()) - grid_config["num_elements"] = grid_size; - grid_config["overlap_size"] = overlap_size; + if (grid_size != size_t(-1)) + grid_config["num_elements"] = XT::Common::to_string(grid_size); + grid_config["overlap_size"] = XT::Common::to_string(overlap_size); const auto grid_ptr = Dune::XT::Grid::CubeGridProviderFactory<GridType>::create(grid_config, MPIHelper::getCommunicator()).grid_ptr(); assert(grid_ptr->comm().size() == 1 || grid_ptr->overlapSize(0) > 0); @@ -80,7 +81,9 @@ struct HyperbolicMnDiscretization const AdvectionSourceSpaceType advection_source_space(grid_view, 1); //******************* create EquationType object *************************************** - std::shared_ptr<const MomentBasis> basis_functions = std::make_shared<const MomentBasis>(quad_order); + std::shared_ptr<const MomentBasis> basis_functions = std::make_shared<const MomentBasis>( + quad_order == size_t(-1) ? MomentBasis::default_quad_order() : quad_order, + quad_refinements == size_t(-1) ? MomentBasis::default_quad_refinements() : quad_refinements); const std::unique_ptr<ProblemType> problem_ptr = XT::Common::make_unique<ProblemType>(*basis_functions, grid_view, grid_config); const auto& problem = *problem_ptr; @@ -88,7 +91,12 @@ struct HyperbolicMnDiscretization const auto boundary_values = problem.boundary_values(); using AnalyticalFluxType = typename ProblemType::FluxType; using EntropyFluxType = typename ProblemType::ActualFluxType; - const auto analytical_flux = problem.flux(); + auto analytical_flux = problem.flux(); + // for Legendre polynomials and real spherical harmonics, the results are sensitive to the initial guess in the + // Newton algorithm. If the thread cache is enabled, the guess is different dependent on how many threads we are + // using, so for the tests we disable this cache to get reproducible results. + if (disable_thread_cache) + dynamic_cast<EntropyFluxType*>(analytical_flux.get())->disable_thread_cache(); const RangeFieldType CFL = problem.CFL(); // ***************** project initial values to discrete function ********************* @@ -153,18 +161,23 @@ struct HyperbolicMnDiscretization constexpr double epsilon = 1e-11; auto slope = TestCaseType::RealizabilityLimiterChooserType::template make_slope<EigenvectorWrapperType>( - *dynamic_cast<const EntropyFluxType*>(analytical_flux.get()), *basis_functions, epsilon); + *dynamic_cast<EntropyFluxType*>(analytical_flux.get()), *basis_functions, epsilon); ReconstructionOperatorType reconstruction_operator(*analytical_flux, *boundary_values, fv_space, *slope, false); ReconstructionAdvectionOperatorType reconstruction_advection_operator(advection_operator, reconstruction_operator); - filename += "_" + ProblemType::static_id(); - filename += "_grid_" + grid_size; + if (XT::Common::is_zero(t_end)) + t_end = problem.t_end(); + + if (!filename.empty()) + filename += "_"; + filename += ProblemType::static_id(); + filename += "_grid_" + grid_config["num_elements"]; filename += "_tend_" + XT::Common::to_string(t_end); filename += "_quad_" + XT::Common::to_string(quad_order); filename += TestCaseType::reconstruction ? "_ord2" : "_ord1"; filename += "_" + basis_functions->mn_name(); - EntropySolverType entropy_solver(*(dynamic_cast<const EntropyFluxType*>(analytical_flux.get())), + EntropySolverType entropy_solver(*(dynamic_cast<EntropyFluxType*>(analytical_flux.get())), fv_space, problem.psi_vac() * basis_functions->unit_ball_volume() / 10, filename); @@ -226,7 +239,17 @@ struct HyperbolicMnTest { void run() { - auto norms = HyperbolicMnDiscretization<TestCaseType>::run().first; + auto norms = HyperbolicMnDiscretization<TestCaseType>::run( + 1, + 0, + TestCaseType::RealizabilityLimiterChooserType::quad_order, + TestCaseType::RealizabilityLimiterChooserType::quad_refinements, + size_t(-1), + 2, + TestCaseType::t_end, + "test", + Dune::GDT::is_full_moment_basis<typename TestCaseType::MomentBasis>::value) + .first; const double l1norm = norms[0]; const double l2norm = norms[1]; const double linfnorm = norms[2]; diff --git a/dune/gdt/test/momentmodels/kinetictransport/testcases.hh b/dune/gdt/test/momentmodels/kinetictransport/testcases.hh index 9b84bd06a65ca22c6b6346d66e5e9ed8dddc4232..12ba0aa3e2f003c67b63bbba3be4f48d26cb856d 100644 --- a/dune/gdt/test/momentmodels/kinetictransport/testcases.hh +++ b/dune/gdt/test/momentmodels/kinetictransport/testcases.hh @@ -43,6 +43,7 @@ struct RealizabilityLimiterChooser<GV, using MomentBasis = LegendreMomentBasis<double, double, order>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; static constexpr size_t quad_order = 54; + static constexpr size_t quad_refinements = 1; template <class EigenVectorWrapperType> static std::unique_ptr<LpConvexhullRealizabilityLimitedSlope<GV, MomentBasis, EigenVectorWrapperType>> @@ -66,6 +67,7 @@ struct RealizabilityLimiterChooser<GV, using MomentBasis = HatFunctionMomentBasis<double, 1, double, dimRange, 1, 1>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; static constexpr size_t quad_order = 15; + static constexpr size_t quad_refinements = 0; #if HAVE_CLP && USE_LP_POSITIVITY_LIMITER template <class EigenVectorWrapperType> @@ -95,6 +97,7 @@ struct RealizabilityLimiterChooser<GV, using MomentBasis = PartialMomentBasis<double, 1, double, dimRange, 1, 1>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; static constexpr size_t quad_order = 15; + static constexpr size_t quad_refinements = 0; template <class EigenVectorWrapperType> static std::unique_ptr<Dg1dRealizabilityLimitedSlope<GV, double, dimRange, EigenVectorWrapperType>> @@ -114,7 +117,8 @@ struct RealizabilityLimiterChooser<GV, { using MomentBasis = RealSphericalHarmonicsMomentBasis<double, double, order, 3>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; - static constexpr size_t quad_order = 2 * order + 6; + static constexpr size_t quad_order = 2 * order + 8; + static constexpr size_t quad_refinements = 0; template <class EigenVectorWrapperType> static std::unique_ptr<LpConvexhullRealizabilityLimitedSlope<GV, MomentBasis, EigenVectorWrapperType>> @@ -135,7 +139,8 @@ struct RealizabilityLimiterChooser<GV, using MomentBasis = HatFunctionMomentBasis<double, 3, double, refinements, 1, 3>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; static constexpr size_t dimRange = MomentBasis::dimRange; - static constexpr size_t quad_order = 18; // fekete rule number 7 + static constexpr size_t quad_order = refinements == 0 ? 18 /*fekete rule number 7*/ : 9 /*fekete rule number 3*/; + static constexpr size_t quad_refinements = 0; #if HAVE_CLP && USE_LP_POSITIVITY_LIMITER template <class EigenVectorWrapperType> @@ -165,7 +170,8 @@ struct RealizabilityLimiterChooser<GV, { using MomentBasis = PartialMomentBasis<double, 3, double, refinements, 1, 3>; using EntropyFluxType = EntropyBasedFluxFunction<GV, MomentBasis>; - static constexpr size_t quad_order = 9; // fekete rule number 3 + static constexpr size_t quad_order = refinements == 0 ? 18 /*fekete rule number 7*/ : 9 /*fekete rule number 3*/; + static constexpr size_t quad_refinements = 0; template <class EigenVectorWrapperType> static std::unique_ptr<DgConvexHullRealizabilityLimitedSlope<GV, MomentBasis, EigenVectorWrapperType>> @@ -239,9 +245,9 @@ template <bool reconstruct> struct SourceBeamMnExpectedResults<LegendreMomentBasis<double, double, 7>, reconstruct> { static constexpr double l1norm = reconstruct ? 0.28535354296013105 : 0.28535354295945792; - static constexpr double l2norm = reconstruct ? 0.37115083996060916 : 0.36265752973701221; + static constexpr double l2norm = reconstruct ? 0.37115145999473981 : 0.36265752973701221; static constexpr double linfnorm = reconstruct ? 0.78506610334488358 : 0.78315544039143314; - static constexpr double tol = 1e-9; + static constexpr double tol = 1e-5; }; template <bool reconstruct> @@ -326,9 +332,9 @@ template <bool reconstruct> struct PlaneSourceMnExpectedResults<LegendreMomentBasis<double, double, 7>, reconstruct> { static constexpr double l1norm = reconstruct ? 2.0000000240000007 : 2.0000000240000029; - static constexpr double l2norm = reconstruct ? 2.7878232892168211 : 2.746101358507282; - static constexpr double linfnorm = reconstruct ? 4.9086815941726396 : 5.327698357914608; - static constexpr double tol = 1e-9; + static constexpr double l2norm = reconstruct ? 2.785411193059216 : 2.746101358507282; + static constexpr double linfnorm = reconstruct ? 4.9069101475812698 : 5.327698357914608; + static constexpr double tol = 1e-7; }; template <bool reconstruct> @@ -513,9 +519,9 @@ struct PointSourceMnExpectedResults; template <bool reconstruct> struct PointSourceMnExpectedResults<RealSphericalHarmonicsMomentBasis<double, double, 2, 3>, reconstruct> { - static constexpr double l1norm = reconstruct ? 1.0000016440585395 : 1.0000016440583621; - static constexpr double l2norm = reconstruct ? 2.6896356393271734 : 2.6837985426830504; - static constexpr double linfnorm = reconstruct ? 10.368884563879304 : 10.375079241728713; + static constexpr double l1norm = reconstruct ? 1.0000013830443908 : 1.0000013830442143; + static constexpr double l2norm = reconstruct ? 2.6901467570598112 : 2.684314243798307; + static constexpr double linfnorm = reconstruct ? 10.371048798431969 : 10.377307670780343; static constexpr double tol = 1e-9; }; @@ -538,9 +544,9 @@ struct PointSourceMnExpectedResults<HatFunctionMomentBasis<double, 3, double, 0, template <bool reconstruct> struct PointSourceMnExpectedResults<PartialMomentBasis<double, 3, double, 0, 1, 3, 1>, reconstruct> { - static constexpr double l1norm = reconstruct ? 1.0000127558028837 : 1.0000127558027134; - static constexpr double l2norm = reconstruct ? 2.6983746461758269 : 2.6882147627660715; - static constexpr double linfnorm = reconstruct ? 10.391230462003152 : 10.394186618150204; + static constexpr double l1norm = reconstruct ? 1.0000000829624787 : 1.0000000829623072; + static constexpr double l2norm = reconstruct ? 2.6983516853120966 : 2.6881937835020211; + static constexpr double linfnorm = reconstruct ? 10.391142640527102 : 10.394108065213185; static constexpr double tol = 1e-9; }; @@ -568,9 +574,9 @@ struct CheckerboardMnExpectedResults; template <bool reconstruct> struct CheckerboardMnExpectedResults<RealSphericalHarmonicsMomentBasis<double, double, 2, 3>, reconstruct> { - static constexpr double l1norm = reconstruct ? 0. : 0.35404367426148931; - static constexpr double l2norm = reconstruct ? 0. : 0.32921585327065972; - static constexpr double linfnorm = reconstruct ? 0. : 0.32895499053937993; + static constexpr double l1norm = reconstruct ? 0. : 0.35404440392013337; + static constexpr double l2norm = reconstruct ? 0. : 0.32922954029850499; + static constexpr double linfnorm = reconstruct ? 0. : 0.32896894056609421; static constexpr double tol = 1e-9; }; @@ -598,9 +604,9 @@ struct ShadowMnExpectedResults; template <bool reconstruct> struct ShadowMnExpectedResults<RealSphericalHarmonicsMomentBasis<double, double, 2, 3>, reconstruct> { - static constexpr double l1norm = reconstruct ? 0. : 0.59247415692031025; - static constexpr double l2norm = reconstruct ? 0. : 0.097642936357459895; - static constexpr double linfnorm = reconstruct ? 0. : 0.016480937983211638; + static constexpr double l1norm = reconstruct ? 0. : 0.59248402251960053; + static constexpr double l2norm = reconstruct ? 0. : 0.097644561106262767; + static constexpr double linfnorm = reconstruct ? 0. : 0.016480889201743513; static constexpr double tol = 1e-9; }; diff --git a/dune/gdt/test/pn-discretization.hh b/dune/gdt/test/pn-discretization.hh index 6f3ca032250c171af1098075258a47e88b7b2cab..29f144ec478dde96044d748d2a8886d066d4d9ed 100644 --- a/dune/gdt/test/pn-discretization.hh +++ b/dune/gdt/test/pn-discretization.hh @@ -8,6 +8,8 @@ #ifndef DUNE_GDT_TEST_HYPERBOLIC_PN_DISCRETIZATION_HH #define DUNE_GDT_TEST_HYPERBOLIC_PN_DISCRETIZATION_HH +#include <dune/common/exceptions.hh> + #include <dune/xt/common/parallel/threadmanager.hh> #include <dune/xt/common/string.hh> #include <dune/xt/common/test/gtest/gtest.h> @@ -33,95 +35,92 @@ #include <dune/gdt/test/momentmodels/kineticequation.hh> -int parse_momentmodel_arguments(int argc, - char** argv, - size_t& num_threads, - size_t& threading_partition_factor, - size_t& num_save_steps, - size_t& num_output_steps, - size_t& quad_order, - std::string& grid_size, - std::string& overlap_size, - double& t_end, - std::string& filename) +void parse_momentmodel_arguments(int argc, + char** argv, + size_t& num_threads, + size_t& threading_partition_factor, + size_t& num_save_steps, + size_t& num_output_steps, + size_t& quad_order, + size_t& quad_refinements, + size_t& grid_size, + size_t& overlap_size, + double& t_end, + std::string& filename) { using namespace Dune; using namespace Dune::GDT; MPIHelper::instance(argc, argv); + // default values + num_threads = 1; + threading_partition_factor = 1; + num_save_steps = 10; + num_output_steps = num_save_steps; + quad_order = -1; + quad_refinements = -1; + grid_size = -1, overlap_size = 2; + t_end = 0.; + filename = ""; + for (int i = 1; i < argc; ++i) { if (std::string(argv[i]) == "--num_threads") { - if (i + 1 < argc) { + if (i + 1 < argc) num_threads = XT::Common::from_string<size_t>(argv[++i]); - } else { - std::cerr << "--num_threads option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--num_threads option requires one argument."); } else if (std::string(argv[i]) == "--threading_partition_factor") { - if (i + 1 < argc) { + if (i + 1 < argc) threading_partition_factor = XT::Common::from_string<size_t>(argv[++i]); - } else { - std::cerr << "--threading_partition_factor option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--threading_partition_factor option requires one argument."); } else if (std::string(argv[i]) == "--filename") { - if (i + 1 < argc) { + if (i + 1 < argc) filename = std::string(argv[++i]); - } else { - std::cerr << "--filename option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--filename option requires one argument."); } else if (std::string(argv[i]) == "--quad_order") { - if (i + 1 < argc) { + if (i + 1 < argc) quad_order = XT::Common::from_string<size_t>(argv[++i]); - } else { - std::cerr << "--quad_order option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--quad_order option requires one argument."); + } else if (std::string(argv[i]) == "--quad_refinements") { + if (i + 1 < argc) + quad_refinements = XT::Common::from_string<size_t>(argv[++i]); + else + DUNE_THROW(Dune::IOError, "--quad_refinements option requires one argument."); } else if (std::string(argv[i]) == "--num_save_steps") { - if (i + 1 < argc) { + if (i + 1 < argc) num_save_steps = XT::Common::from_string<size_t>(argv[++i]); - } else { - std::cerr << "--num_save_steps option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--num_save_steps option requires one argument."); } else if (std::string(argv[i]) == "--num_output_steps") { - if (i + 1 < argc) { + if (i + 1 < argc) num_output_steps = XT::Common::from_string<size_t>(argv[++i]); - } else { - std::cerr << "--num_output_steps option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--num_output_steps option requires one argument."); } else if (std::string(argv[i]) == "--grid_size") { - if (i + 1 < argc) { - grid_size = argv[++i]; - } else { - std::cerr << "--grid_size option requires one argument." << std::endl; - return 1; - } + if (i + 1 < argc) + grid_size = XT::Common::from_string<size_t>(argv[++i]); + else + DUNE_THROW(Dune::IOError, "--grid_size option requires one argument."); } else if (std::string(argv[i]) == "--overlap_size") { - if (i + 1 < argc) { - overlap_size = argv[++i]; - } else { - std::cerr << "--overlap_size option requires one argument." << std::endl; - return 1; - } + if (i + 1 < argc) + overlap_size = XT::Common::from_string<size_t>(argv[++i]); + else + DUNE_THROW(Dune::IOError, "--overlap_size option requires one argument."); } else if (std::string(argv[i]) == "--t_end") { - if (i + 1 < argc) { + if (i + 1 < argc) t_end = XT::Common::from_string<double>(argv[++i]); - } else { - std::cerr << "--t_end option requires one argument." << std::endl; - return 1; - } + else + DUNE_THROW(Dune::IOError, "--t_end option requires one argument."); } else { - std::cerr << "Unknown option " << std::string(argv[i]) << std::endl; - return 1; + DUNE_THROW(Dune::IOError, "Unknown option " + std::string(argv[i])); } } DXTC_CONFIG.set("threading.partition_factor", threading_partition_factor, true); XT::Common::threadManager().set_max_threads(num_threads); - return 0; } @@ -176,9 +175,10 @@ struct HyperbolicPnDiscretization Dune::FieldVector<double, 3> run(size_t num_save_steps = 1, size_t num_output_steps = 0, size_t quad_order = size_t(-1), - std::string grid_size = "", - std::string overlap_size = "2", - double t_end = TestCaseType::t_end, + size_t quad_refinements = size_t(-1), + size_t grid_size = size_t(-1), + size_t overlap_size = 2, + double t_end = 0., std::string filename = "") { using namespace Dune; @@ -205,9 +205,9 @@ struct HyperbolicPnDiscretization //******************* create grid and FV space *************************************** auto grid_config = ProblemType::default_grid_cfg(); - if (!grid_size.empty()) - grid_config["num_elements"] = grid_size; - grid_config["overlap_size"] = overlap_size; + if (grid_size != size_t(-1)) + grid_config["num_elements"] = XT::Common::to_string(grid_size); + grid_config["overlap_size"] = XT::Common::to_string(overlap_size); const auto grid_ptr = Dune::XT::Grid::CubeGridProviderFactory<GridType>::create(grid_config, MPIHelper::getCommunicator()).grid_ptr(); assert(grid_ptr->comm().size() == 1 || grid_ptr->overlapSize(0) > 0); @@ -216,9 +216,9 @@ struct HyperbolicPnDiscretization const AdvectionSourceSpaceType advection_source_space(grid_view, 1); //******************* create EquationType object *************************************** - std::shared_ptr<const MomentBasis> basis_functions = (quad_order == size_t(-1)) - ? std::make_shared<const MomentBasis>() - : std::make_shared<const MomentBasis>(quad_order); + std::shared_ptr<const MomentBasis> basis_functions = std::make_shared<const MomentBasis>( + quad_order == size_t(-1) ? MomentBasis::default_quad_order() : quad_order, + quad_refinements == size_t(-1) ? MomentBasis::default_quad_refinements() : quad_refinements); const std::unique_ptr<ProblemType> problem_ptr = XT::Common::make_unique<ProblemType>(*basis_functions, grid_config); const auto& problem = *problem_ptr; @@ -307,8 +307,10 @@ struct HyperbolicPnDiscretization FvOperatorType& fv_operator = FvOperatorChooser<TestCaseType::reconstruction>::choose(advection_operator, reconstruction_fv_operator); - filename += "_" + ProblemType::static_id(); - filename += "_grid_" + grid_size; + if (!filename.empty()) + filename += "_"; + filename += ProblemType::static_id(); + filename += "_grid_" + grid_config["num_elements"]; filename += "_tend_" + XT::Common::to_string(t_end); filename += TestCaseType::reconstruction ? "_ord2" : "_ord1"; filename += "_" + basis_functions->pn_name(); @@ -366,7 +368,8 @@ struct HyperbolicPnTest { void run() { - auto norms = HyperbolicPnDiscretization<TestCaseType>::run(); + auto norms = HyperbolicPnDiscretization<TestCaseType>::run( + 1, 0, size_t(-1), size_t(-1), size_t(-1), 2, TestCaseType::t_end, "test"); const double l1norm = norms[0]; const double l2norm = norms[1]; const double linfnorm = norms[2];