adapt(3rheolef)

πŸ“¦
version 7.2 Β· 4 versions
, in debian trixie, ubuntu noble, ubuntu questing

πŸ’… adapt β€” adaptive mesh generation (rheolef-7.2) πŸ’…

okay bestie, sit down, because this one is a whole mood. this is adapt from the rheolef-7.2 era, living in section 3 of the manual, and it is genuinely iconic if you love meshes that rearrange themselves like they're getting ready for prom. πŸŽ€


✨ NAME ✨

adapt β€” adaptive mesh generation, and yes it's the rheolef-7.2 flavour. periodt. πŸ’–


🌸 SYNOPSIS 🌸

geo adapt (const field& criterion);
geo adapt (const field& criterion, const adapt_option& aopt);

two ways in, bestie. either you hand it a criterion and let it cook, or you hand it a criterion plus an adapt_option and get specific. πŸ¦‹


πŸ‘‘ DESCRIPTION πŸ‘‘

So the adapt function runs an adaptive mesh procedure, and it does it using either of two mesh generators: gmsh (isotropic, the chill one) or bamg(1) (anisotropic, the dramatic one). And like… in two dimensions, bamg(1) is the default. no cap.

For dimension one or dimension three, gmsh is the only generator supported yet. yeah. only one. πŸ™ˆ

And in the 2D case, gmsh corresponds to the option aopt.generator='gmsh', where aopt is an adap_option variable (see adapt(3)).


🧚 CRITERION AND METRIC 🧚

The whole strategy is based on a metric determined by the Hessian of a scalar criterion field, called here phi, which you supply as the first argument of the adapt function. yes you. you're the main character here. πŸ’…

So let's denote H=Hessian(phi) as the Hessian tensor field of the scalar field phi. Then |H| is the tensor that has the same eigenvector as H, but with the absolute value of its eigenvalues:

|H| = Q*diag(|lambda_i|)*Qt

And the metric M is determined from |H|. Quick refresher, because it matters: an isotropic metric is one where M(x)=hloc(x)^(-2)*Id, where hloc(x) is the element size field and Id is the identity d*d matrix, and d=1,2,3 is the physical space dimension. 🌈


πŸ“ GMSH ISOTROPIC METRIC πŸ“

look at her. so clean. so isotropic.

                      max_(i=0..d-1)(|lambda_i(x)|)*Id
           M(x) = -----------------------------------------
                  err*hcoef^2*(sup_y(phi(y))-inf_y(phi(y)))

Notice that the denominator involves a global (absolute) normalization sup_y(phi(y))-inf_y(phi(y)) of the criterion field phi, plus two parameters: aopt.err, the target error, and aopt.hcoef, a secondary normalization parameter which defaults to 1. 🫢


πŸ’œ BAMG ANISOTROPIC METRIC πŸ’œ

okay this is the spicy one, there are two approaches for the normalization of the metric.

Approach the first: a global (absolute) normalization:

                                  |H(x))|
           M(x) = -----------------------------------------
                  err*hcoef^2*(sup_y(phi(y))-inf_y(phi(y)))

Approach the other (the original says "the first one" again, we love a little chaos 😭): a local (relative) normalization:

                                  |H(x))|
           M(x) = -----------------------------------------
                  err*hcoef^2*(|phi(x)|, cutoff*max_y|phi(y)|)

Notice that this denominator involves a local value phi(x). The parameter comes from the optional variable aopt.cutoff, and its default value is 1e-7. The default strategy is the local normalization. If you want the global one, you enforce it by setting aopt.additional='-AbsError'. πŸ’…

πŸ€” When choosing global or local normalization ?

Okay so, when the governing field phi is bounded, i.e. when err*hcoef^2*(sup_y(phi(y))-inf_y(phi(y))) will converge versus mesh refinement to a bounded value, then the global normalization defines a metric that is mesh-independent, and thus the adaptation loop will converge. slay. ✨

Otherwise β€” when phi presents singularities, with unbounded values (like corner singularity, i.e. presents picks when represented in elevation view) β€” then the mesh adaptation procedure is more difficult. Because the global normalization divides by quantities that can be very large, and the mesh adaptation can diverge when focusing on the singularities. πŸ’€ In that case the local normalization is preferable. Also, the focus on singularities can be controlled by setting aopt.hmin not too small.

The local normalization was chosen as the default since it's more robust. And when your field phi does not present singularities, you can switch to the global numbering, which leads to a best equirepartition of the error over the domain. iykyk. πŸ”₯


πŸŽ€ OPTIONS πŸŽ€

here she is, the struct, in all her glory:

struct adapt_option {
    typedef std::vector<int>::size_type size_type;
    std::string generator;
    bool isotropic;
    Float err;
    Float errg;
    Float hcoef;
    Float hmin;
    Float hmax;
    Float ratio;
    Float cutoff;
    size_type n_vertices_max;
    size_type n_smooth_metric;
    bool splitpbedge;
    Float thetaquad;
    Float anisomax;
    bool clean;
    std::string additional;
    bool double_precision;
    Float anglecorner;  // angle below which bamg considers 2 consecutive edge to be part of
                        // the same spline
    adapt_option() :
        generator(""),
        isotropic(true), err(1e-2), errg(1e-1), hcoef(1), hmin(0.0001), hmax(0.3), ratio(0), cutoff(1e-7),
        n_vertices_max(50000), n_smooth_metric(1),
        splitpbedge(true), thetaquad(std::numeric_limits<Float>::max()),
        anisomax(1e6), clean(false), additional("-RelError"), double_precision(false),
        anglecorner(0)
     {}
};

The fields this page actually spills tea about, so you know what they do:

  • generator β€” picks the mesh generator. Setting aopt.generator='gmsh' in the two dimensional case gets you gmsh instead of the default bamg(1). Default is "".
  • isotropic β€” the isotropic flag, defaulting to true.
  • err β€” the target error, default 1e-2. shows up in both metric formulas. ⭐
  • hcoef β€” the secondary normalization parameter, default 1. also shows up in both formulas.
  • hmin β€” set this not too small if you're trying to control the focus on singularities. default 0.0001.
  • cutoff β€” the parameter for the local normalization denominator, default 1e-7.
  • additional β€” set it to '-AbsError' to enforce the global normalization. Default is "-RelError", which is why local normalization is the default strategy.
  • anglecorner β€” per the comment right there in the struct: angle below which bamg considers 2 consecutive edge to be part of the same spline. default 0.

And the rest of the fields β€” errg, hmax, ratio, n_vertices_max, n_smooth_metric, splitpbedge, thetaquad, anisomax, clean, double_precision β€” are just… there. sitting pretty with their defaults. not me being jealous of a struct's completeness. πŸ™ˆ


🧡 IMPLEMENTATION 🧡

This documentation has been generated from file main/lib/adapt.h. that's the source of truth bestie, go look. πŸ‘‘


πŸ’– AUTHOR πŸ’–

Pierre Saramito <Pierre.Saramito@imag.fr> β€” the icon, the legend. 🌟


Copyright   (C)  2000-2018  Pierre  Saramito  <Pierre.Saramito@imag.fr>
GPLv3+: GNU GPL version 3 or later  <http://gnu.org/licenses/gpl.html>.
This  is  free  software:  you  are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

like, it's free software, you can change it, you can redistribute it, but there is NO WARRANTY to the extent permitted by law. read that again. no warranty. πŸ’€


and that's the whole page, bestie β€” rheolef Version 7.2, section adapt(3rheolef), dated as it says on the tin. go forth and adapt your meshes. mwah. πŸ’…βœ¨πŸŽ€

πŸ“¦ where this page comes from