diff --git a/dune/gdt/tools/hyperbolic.hh b/dune/gdt/tools/hyperbolic.hh new file mode 100644 index 0000000000000000000000000000000000000000..9857739b4001c48f2876dd8b9f981f897e3650de --- /dev/null +++ b/dune/gdt/tools/hyperbolic.hh @@ -0,0 +1,91 @@ +// This file is part of the dune-gdt project: +// https://github.com/dune-community/dune-gdt +// Copyright 2010-2017 dune-gdt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2018) + +#ifndef DUNE_GDT_TOOLS_HYPERBOLIC_HH +#define DUNE_GDT_TOOLS_HYPERBOLIC_HH + +#include <dune/geometry/quadraturerules.hh> + +#include <dune/grid/common/gridview.hh> +#include <dune/grid/common/rangegenerators.hh> +#include <dune/grid/yaspgrid.hh> + +#include <dune/xt/common/fvector.hh> +#include <dune/xt/grid/gridprovider/cube.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> +#include <dune/xt/functions/interfaces/function.hh> + +namespace Dune { +namespace GDT { + + +/** + * \brief Estimates dt via [Cockburn, Coquel, LeFloch, 1995] + */ +template <class GV, + size_t m_as_size_t, + class R, + int m_as_int = m_as_size_t, + typename = std::enable_if_t<ssize_t(m_as_size_t) == ssize_t(m_as_int), void>> +double estimate_dt_for_hyperbolic_system( + const GridView<GV>& grid_view, + const XT::Functions::GridFunctionInterface<XT::Grid::extract_entity_t<GridView<GV>>, m_as_size_t, 1, R>& state, + const XT::Functions::FunctionInterface<m_as_size_t, GridView<GV>::dimension, m_as_size_t, R>& flux, + const std::pair<XT::Common::FieldVector<R, m_as_int>, XT::Common::FieldVector<R, m_as_int>>& boundary_data_range = { + XT::Common::FieldVector<R, m_as_int>(std::numeric_limits<R>::max()), + XT::Common::FieldVector<R, m_as_int>(std::numeric_limits<R>::min())}) +{ + using D = typename GridView<GV>::ctype; + static const constexpr size_t d = GridView<GV>::dimension; + static const constexpr size_t m = m_as_size_t; + // estimate data range + auto data_minimum = boundary_data_range.first; + auto data_maximum = boundary_data_range.second; + auto local_state = state.local_function(); + for (auto&& element : elements(grid_view)) { + local_state->bind(element); + for (const auto& quadrature_point : QuadratureRules<D, d>::rule(element.type(), local_state->order())) { + const auto state_value = local_state->evaluate(quadrature_point.position()); + for (size_t ii = 0; ii < m; ++ii) { + data_minimum[ii] = std::min(data_minimum[ii], state_value[ii]); + data_maximum[ii] = std::max(data_maximum[ii], state_value[ii]); + } + } + } + // ensure distinct minima/maxima (otherwise the grid creation below will fail) + for (size_t ii = 0; ii < m; ++ii) + if (!(data_minimum[ii] < data_maximum[ii])) + data_maximum[ii] = data_minimum[ii] + 1e-6 * data_minimum[ii]; + // estimate flux derivative range + R max_flux_derivative = std::numeric_limits<R>::min(); + const auto flux_range_grid = XT::Grid::make_cube_grid<YaspGrid<m, EquidistantOffsetCoordinates<double, m>>>( + data_minimum, data_maximum, XT::Common::FieldVector<unsigned int, m>(1)); + const auto flux_range = *flux_range_grid.leaf_view().template begin<0>(); + for (const auto& quadrature_point : QuadratureRules<R, m>::rule(flux_range.type(), flux.order())) { + const auto df = flux.jacobian(flux_range.geometry().global(quadrature_point.position())); + for (size_t ss = 0; ss < d; ++ss) + max_flux_derivative = std::max(max_flux_derivative, df[ss].infinity_norm()); + } + D perimeter_over_volume = std::numeric_limits<D>::min(); + for (auto&& element : elements(grid_view)) { + D perimeter = 0; + for (auto&& intersection : intersections(grid_view, element)) + perimeter += intersection.geometry().volume(); + perimeter_over_volume = std::max(perimeter_over_volume, perimeter / element.geometry().volume()); + } + const auto dt = 1. / (perimeter_over_volume * max_flux_derivative); + return dt; +} // ... estimate_dt_for_hyperbolic_system(...) + + +} // namespace GDT +} // namespace Dune + +#endif // DUNE_GDT_TOOLS_HYPERBOLIC_HH