SpECTRE  v2024.03.19
amr::Criteria Namespace Reference

Criteria for deciding how a mesh should be adapted. More...

Namespaces

namespace  OptionTags
 Option tags for AMR criteria.
 
namespace  Tags
 Tags for adaptive mesh refinement criteria
 

Classes

class  Constraints
 Refine the grid towards the target constraint violation. More...
 
class  DriveToTarget
 Refine the grid towards the target number of grid points and refinement levels in each dimension and then oscillate about the target. More...
 
class  IncreaseResolution
 Uniformly increases the number of grid points by one. More...
 
class  Loehner
 h-refine the grid based on a smoothness indicator More...
 
class  Persson
 h-refine the grid based on power in the highest modes More...
 
class  Random
 Randomly refine (or coarsen) an Element in each dimension. More...
 
class  TruncationError
 Refine the grid towards the target truncation error. More...
 

Typedefs

template<size_t Dim, typename TensorTags >
using standard_criteria = tmpl::list< ::amr::Criteria::IncreaseResolution< Dim >, ::amr::Criteria::TruncationError< Dim, TensorTags >, ::amr::Criteria::Loehner< Dim, TensorTags >, ::amr::Criteria::Persson< Dim, TensorTags >, ::amr::Criteria::DriveToTarget< Dim >, ::amr::Criteria::Random >
 AMR criteria that are generally applicable. More...
 

Functions

template<size_t Dim>
double loehner_smoothness_indicator (gsl::not_null< DataVector * > first_deriv_buffer, gsl::not_null< DataVector * > second_deriv_buffer, const DataVector &tensor_component, const Mesh< Dim > &mesh, size_t dimension)
 Computes an anisotropic smoothness indicator based on the magnitude of second derivatives. More...
 
template<size_t Dim>
std::array< double, Dim > loehner_smoothness_indicator (const DataVector &tensor_component, const Mesh< Dim > &mesh)
 Computes an anisotropic smoothness indicator based on the magnitude of second derivatives. More...
 
template<size_t Dim>
double persson_smoothness_indicator (gsl::not_null< DataVector * > filtered_component_buffer, const DataVector &tensor_component, const Mesh< Dim > &mesh, size_t dimension, size_t num_highest_modes)
 Computes an anisotropic smoothness indicator based on the power in the highest modes. More...
 
template<size_t Dim>
std::array< double, Dim > persson_smoothness_indicator (const DataVector &tensor_component, const Mesh< Dim > &mesh, size_t num_highest_modes)
 Computes an anisotropic smoothness indicator based on the power in the highest modes. More...
 

Detailed Description

Criteria for deciding how a mesh should be adapted.

Typedef Documentation

◆ standard_criteria

template<size_t Dim, typename TensorTags >
using amr::Criteria::standard_criteria = typedef tmpl::list< ::amr::Criteria::IncreaseResolution<Dim>, ::amr::Criteria::TruncationError<Dim, TensorTags>, ::amr::Criteria::Loehner<Dim, TensorTags>, ::amr::Criteria::Persson<Dim, TensorTags>, ::amr::Criteria::DriveToTarget<Dim>, ::amr::Criteria::Random>

AMR criteria that are generally applicable.

Template Parameters
Dimthe spatial dimension
TensorTagsthe tensor fields to monitor

Function Documentation

◆ loehner_smoothness_indicator() [1/2]

template<size_t Dim>
std::array< double, Dim > amr::Criteria::loehner_smoothness_indicator ( const DataVector tensor_component,
const Mesh< Dim > &  mesh 
)

Computes an anisotropic smoothness indicator based on the magnitude of second derivatives.

This smoothness indicator is simply the L2 norm of the logical second derivative of the tensor component in the given dimension:

\begin{equation} \epsilon_k = \sqrt{\frac{1}{N_\mathrm{points}} \sum_{p=1}^N_\mathrm{points} \left(\partial^2 u / \partial \xi_k^2\right)^2} \end{equation}

If the smoothness indicator is large in a direction, meaning the tensor component has a large second derivative in that direction, the element should be h-refined. If the smoothness indicator is small, the element should be h-coarsened. A coarsing threshold of about a third of the refinement threshold seems to work well, but this will need more testing.

Note that it is not at all clear that a smoothness indicator based on the magnitude of second derivatives is useful in a DG context. Smooth functions with higher-order derivatives can be approximated just fine by higher-order DG elements without the need for h-refinement. The use of second derivatives to indicate the need for refinement originated in the finite element context with linear elements. Other smoothness indicators might prove more useful for DG elements, e.g. based on jumps or oscillations of the solution. We can also explore applying the troubled-cell indicators (TCIs) used in hydrodynamic simulations as h-refinement indicators.

Specifically, this smoothness indicator is based on [122] (hence the name of the function), which is popular in the finite element community and also used in a DG context by [58], Eq. (34), and by [153], Eq. (15). We make several modifications:

  • The original smoothness indicator is isotropic, i.e. it computes the norm over all (mixed) second derivatives. Here we compute an anisotropic indicator by computing second derivatives in each dimension separately and ignoring mixed derivatives.
  • The original smoothness indicator is normalized by measures of the first derivative which don't generalize well to spectral elements. Therefore, we simplify the normalization to a standard relative and absolute tolerance. An alternative approach is proposed in [153], Eq.(15), where the authors take the absolute value of the differentiation matrix and apply the resulting matrix to the absolute value of the data on the grid to compute the normalization. However, this quantity can produce quite large numbers and hence overestimates the smoothness by suppressing the second derivative.
  • We compute the second derivative in logical coordinates. This seems easiest for spectral elements, but note that [153] seem to use inertial coordinates.

In addition to the above modifications, we can consider approximating the second derivative using finite differences, as explored in the prototype https://github.com/sxs-collaboration/dg-charm/blob/HpAmr/Evolution/HpAmr/LohnerRefiner.hpp. This would allow falling back to the normalization used by Löhner and might be cheaper to compute, but it requires an interpolation to the center and maybe also to the faces, depending on the desired stencil.

◆ loehner_smoothness_indicator() [2/2]

template<size_t Dim>
double amr::Criteria::loehner_smoothness_indicator ( gsl::not_null< DataVector * >  first_deriv_buffer,
gsl::not_null< DataVector * >  second_deriv_buffer,
const DataVector tensor_component,
const Mesh< Dim > &  mesh,
size_t  dimension 
)

Computes an anisotropic smoothness indicator based on the magnitude of second derivatives.

This smoothness indicator is simply the L2 norm of the logical second derivative of the tensor component in the given dimension:

\begin{equation} \epsilon_k = \sqrt{\frac{1}{N_\mathrm{points}} \sum_{p=1}^N_\mathrm{points} \left(\partial^2 u / \partial \xi_k^2\right)^2} \end{equation}

If the smoothness indicator is large in a direction, meaning the tensor component has a large second derivative in that direction, the element should be h-refined. If the smoothness indicator is small, the element should be h-coarsened. A coarsing threshold of about a third of the refinement threshold seems to work well, but this will need more testing.

Note that it is not at all clear that a smoothness indicator based on the magnitude of second derivatives is useful in a DG context. Smooth functions with higher-order derivatives can be approximated just fine by higher-order DG elements without the need for h-refinement. The use of second derivatives to indicate the need for refinement originated in the finite element context with linear elements. Other smoothness indicators might prove more useful for DG elements, e.g. based on jumps or oscillations of the solution. We can also explore applying the troubled-cell indicators (TCIs) used in hydrodynamic simulations as h-refinement indicators.

Specifically, this smoothness indicator is based on [122] (hence the name of the function), which is popular in the finite element community and also used in a DG context by [58], Eq. (34), and by [153], Eq. (15). We make several modifications:

  • The original smoothness indicator is isotropic, i.e. it computes the norm over all (mixed) second derivatives. Here we compute an anisotropic indicator by computing second derivatives in each dimension separately and ignoring mixed derivatives.
  • The original smoothness indicator is normalized by measures of the first derivative which don't generalize well to spectral elements. Therefore, we simplify the normalization to a standard relative and absolute tolerance. An alternative approach is proposed in [153], Eq.(15), where the authors take the absolute value of the differentiation matrix and apply the resulting matrix to the absolute value of the data on the grid to compute the normalization. However, this quantity can produce quite large numbers and hence overestimates the smoothness by suppressing the second derivative.
  • We compute the second derivative in logical coordinates. This seems easiest for spectral elements, but note that [153] seem to use inertial coordinates.

In addition to the above modifications, we can consider approximating the second derivative using finite differences, as explored in the prototype https://github.com/sxs-collaboration/dg-charm/blob/HpAmr/Evolution/HpAmr/LohnerRefiner.hpp. This would allow falling back to the normalization used by Löhner and might be cheaper to compute, but it requires an interpolation to the center and maybe also to the faces, depending on the desired stencil.

◆ persson_smoothness_indicator() [1/2]

template<size_t Dim>
std::array< double, Dim > amr::Criteria::persson_smoothness_indicator ( const DataVector tensor_component,
const Mesh< Dim > &  mesh,
size_t  num_highest_modes 
)

Computes an anisotropic smoothness indicator based on the power in the highest modes.

This smoothness indicator is the L2 norm of the tensor component with the lowest N - M modes filtered out, where N is the number of grid points in the given dimension and M is num_highest_modes.

This strategy is similar to the Persson troubled-cell indicator (see evolution::dg::subcell::persson_tci) with a few modifications:

  • The indicator is computed in each dimension separately for an anisotropic measure.
  • The number of highest modes to keep can be chosen as a parameter.
  • We don't normalize by the L2 norm of the unfiltered data \(u\) here. This function just returns the L2 norm of the filtered data.

◆ persson_smoothness_indicator() [2/2]

template<size_t Dim>
double amr::Criteria::persson_smoothness_indicator ( gsl::not_null< DataVector * >  filtered_component_buffer,
const DataVector tensor_component,
const Mesh< Dim > &  mesh,
size_t  dimension,
size_t  num_highest_modes 
)

Computes an anisotropic smoothness indicator based on the power in the highest modes.

This smoothness indicator is the L2 norm of the tensor component with the lowest N - M modes filtered out, where N is the number of grid points in the given dimension and M is num_highest_modes.

This strategy is similar to the Persson troubled-cell indicator (see evolution::dg::subcell::persson_tci) with a few modifications:

  • The indicator is computed in each dimension separately for an anisotropic measure.
  • The number of highest modes to keep can be chosen as a parameter.
  • We don't normalize by the L2 norm of the unfiltered data \(u\) here. This function just returns the L2 norm of the filtered data.