LCOV - code coverage report
Current view: top level - include/systems - variational_smoother_system.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4546 (ebe2b5) with base a20bc7 Lines: 15 15 100.0 %
Date: 2026-09-11 19:50:22 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : #ifndef LIBMESH_VARIATIONAL_SMOOTHER_SYSTEM_H
      19             : #define LIBMESH_VARIATIONAL_SMOOTHER_SYSTEM_H
      20             : 
      21             : // libMesh includes
      22             : #include "libmesh/enum_fe_family.h"
      23             : #include "libmesh/enum_quadrature_type.h"
      24             : #include "libmesh/fem_function_base.h"
      25             : #include "libmesh/fem_system.h"
      26             : #include "libmesh/libmesh_common.h"
      27             : 
      28             : // C++ includes
      29             : #include <map>
      30             : #include <memory>
      31             : 
      32             : namespace libMesh
      33             : {
      34             : 
      35             : /**
      36             :  * Struct to hold smoother-relevant information about the mesh quality.
      37             :  */
      38         216 : struct MeshQualityInfo
      39             : {
      40             :   // dof_id_types will hold the id of the Elem where the metric occurs
      41             :   // IMPORTANT: the Real should be the first entry of the pair so that taking
      42             :   // the min/max accross processors will compare the numeric values instead of
      43             :   // the element ids.
      44             : 
      45             :   std::pair<Real, dof_id_type> max_elem_distortion{std::numeric_limits<Real>::lowest(),
      46             :                                                    DofObject::invalid_id};
      47             :   std::pair<Real, dof_id_type> min_elem_distortion{std::numeric_limits<Real>::max(),
      48             :                                                    DofObject::invalid_id};
      49             :   Real total_distortion = 0.;
      50             : 
      51             :   std::pair<Real, dof_id_type> max_elem_dilation{std::numeric_limits<Real>::lowest(),
      52             :                                                  DofObject::invalid_id};
      53             :   std::pair<Real, dof_id_type> min_elem_dilation{std::numeric_limits<Real>::max(),
      54             :                                                  DofObject::invalid_id};
      55             :   Real total_dilation = 0.;
      56             : 
      57             :   std::pair<Real, dof_id_type> max_elem_combined{std::numeric_limits<Real>::lowest(),
      58             :                                                  DofObject::invalid_id};
      59             :   std::pair<Real, dof_id_type> min_elem_combined{std::numeric_limits<Real>::max(),
      60             :                                                  DofObject::invalid_id};
      61             :   Real total_combined = 0.;
      62             : 
      63             :   std::pair<Real, dof_id_type> max_elem_det_S{std::numeric_limits<Real>::lowest(),
      64             :                                               DofObject::invalid_id};
      65             :   std::pair<Real, dof_id_type> min_elem_det_S{std::numeric_limits<Real>::max(),
      66             :                                               DofObject::invalid_id};
      67             :   Real total_det_S = 0.;
      68             :   Real max_qp_det_S = std::numeric_limits<Real>::lowest();
      69             :   Real min_qp_det_S = std::numeric_limits<Real>::max();
      70             : 
      71             :   bool mesh_is_tangled = false;
      72             :   bool initialized = false;
      73             : };
      74             : 
      75             : // FEMSystem, TimeSolver and  NewtonSolver will handle most tasks,
      76             : // but we must specify element residuals
      77         360 : class VariationalSmootherSystem : public libMesh::FEMSystem
      78             : {
      79             : /**
      80             :  * This is an FEMSystem to solve the optimization probelem posed by the
      81             :  * VariationalMeshSmoother class.
      82             :  *
      83             :  * The residual is coded as the gradient of the distortion-dilation metric, and
      84             :  * the jacobian as analytically coded as the Hessian of the metric.
      85             :  *
      86             :  * The nodes of the system mesh are updated during the solve.
      87             :  */
      88             : public:
      89        2556 :   VariationalSmootherSystem(libMesh::EquationSystems & es,
      90             :                             const std::string & name,
      91             :                             const unsigned int number)
      92        2556 :     : libMesh::FEMSystem(es, name, number),
      93        2412 :       _verbosity(0),
      94        2412 :       _epsilon_squared(TOLERANCE),
      95        2412 :       _epsilon_squared_assembly(0.),
      96        2412 :       _ref_vol(0.),
      97        2412 :       _dilation_weight(0.5),
      98        2412 :       _untangling_solve(false),
      99        2628 :       _quadrature_type(QGAUSS)
     100        2556 :   {}
     101             : 
     102             :   // Default destructor
     103             :   ~VariationalSmootherSystem() override;
     104             : 
     105             :   /**
     106             :    * Assembly method to update the mesh based on the smoother solve.
     107             :    */
     108             :   virtual void assembly (bool get_residual,
     109             :                          bool get_jacobian,
     110             :                          bool apply_heterogeneous_constraints = false,
     111             :                          bool apply_no_constraints = false) override;
     112             : 
     113          72 :   Real & get_dilation_weight() { return _dilation_weight; }
     114             : 
     115             :   /**
     116             :    * Set the quadrature rule type used to integrate the distortion-dilation
     117             :    * metric over each element. The default (\p QGAUSS) samples the element
     118             :    * interior only, which can miss degeneracies localized at element corners
     119             :    * (e.g. an element collapsing toward one of its nodes). A vertex-sampling
     120             :    * rule such as \p QTRAP, \p QSIMPSON, \p QNODAL, or \p QGAUSS_LOBATTO
     121             :    * evaluates the metric at the element nodes, so a folding corner drives the
     122             :    * metric up (and is flagged as tangled) as it should be. The number of
     123             :    * points is set from the default order for the mesh's FE type plus the
     124             :    * System's \p extra_quadrature_order. Not every quadrature type is defined
     125             :    * for every element type (e.g. \p QGAUSS_LOBATTO is only available for
     126             :    * tensor-product elements), so choose a type compatible with the mesh.
     127             :    */
     128        2556 :   void set_quadrature_type(QuadratureType qt) { _quadrature_type = qt; }
     129             : 
     130             :   /**
     131             :    * Get the quadrature rule type used to integrate the distortion-dilation
     132             :    * metric. See set_quadrature_type().
     133             :    */
     134             :   QuadratureType get_quadrature_type() const { return _quadrature_type; }
     135             : 
     136             :   /**
     137             :    * Solves the system to smooth the mesh. If the mesh is initially tangled,
     138             :    * a solve is first performed to untangle the mesh, followed by a solve to
     139             :    * smooth the mesh.
     140             :    */
     141             :   virtual void solve() override;
     142             : 
     143             :   /**
     144             :    * Get the target element for a given element type.
     145             :    * @param type Element type
     146             :    * @return a std::pair containing the target element for type and the
     147             :    * corresponding nodes that must be kept in scope while the target element is
     148             :    * used.
     149             :    */
     150             :   static std::pair<std::unique_ptr<Elem>, std::vector<std::unique_ptr<Node>>>
     151             :   get_target_elem(const ElemType & type);
     152             : 
     153             :   /**
     154             :    * Get the jacobians (and determinants) of the target-to-reference element mapping.
     155             :    * @param target_elem Target element.
     156             :    * @param femcontext Context used to build mapping.
     157             :    * @param jacobian Vector in which to store the jacobians for each quadrature point.
     158             :    * @param jacobian_dets Vector in which to store the determinant of the jacobians
     159             :    * for each quadrature point.
     160             :    */
     161             :   static void get_target_to_reference_jacobian(const Elem * const target_elem,
     162             :                                                const FEMContext & femcontext,
     163             :                                                std::vector<RealTensor> & jacobians,
     164             :                                                std::vector<Real> & jacobian_dets);
     165             : 
     166             :   /**
     167             :    * Getter for the _mesh_info attribute. If this attribute has not yet been
     168             :    * initialized, compute_mesh_quality_info is called to initialize it.
     169             :    */
     170             :   const MeshQualityInfo & get_mesh_info();
     171             : 
     172             :   /*
     173             :    * Computes information about the mesh quality and sets the _mesh_info attribute.
     174             :    */
     175             :   void compute_mesh_quality_info();
     176             : 
     177             :   /*
     178             :    * Sets the verbosity of the object.
     179             :    */
     180        2556 :   void set_verbosity(const unsigned int verbosity) { _verbosity = verbosity; }
     181             : 
     182             : protected:
     183             : 
     184             :   // System initialization
     185             :   virtual void init_data () override;
     186             : 
     187             :   // Context initialization
     188             :   virtual void init_context (libMesh::DiffContext & context) override;
     189             : 
     190             :   // Element residual and jacobian calculations
     191             :   // Time dependent parts
     192             :   virtual bool element_time_derivative (bool request_jacobian,
     193             :                                         libMesh::DiffContext & context) override;
     194             : 
     195             :   /* Computes the element reference volume used in the dilation metric
     196             :    * The reference value is set to the averaged value of all elements' average
     197             :    * |J|. Also computes any applicable target element inverse Jacobians. Target
     198             :    * elements are relavant when the reference element does not minimize the
     199             :    * distortion metric.
     200             :    */
     201             :   void prepare_for_smoothing();
     202             : 
     203             :   /**
     204             :    * Verbosity setting.
     205             :    * The verbosity levels and the corresponding information output are as
     206             :    * follows:
     207             :    *
     208             :    *   verbosity = 0 : No information.
     209             :    *
     210             :    *   0 < verbosity : Prints:
     211             :    *     - Initial mesh quality information
     212             :    *     - The untangled mesh quality (if applicable)
     213             :    *     - The smoothed mesh quality
     214             :    *
     215             :    *   10 < verbosity: Prints:
     216             :    *     - The reference volume used for the dilation metric
     217             :    *
     218             :    *   50 < verbosity: Prints:
     219             :    *     - Mesh quality information after each assembly
     220             :    *
     221             :    *   90 < verbosity: Prints:
     222             :    *     - Quality information about each element after each assembly
     223             :    *
     224             :    */
     225             :   unsigned int _verbosity;
     226             : 
     227             :   /**
     228             :   * The small nonzero constant to prevent zero denominators (degenerate meshes only)
     229             :   */
     230             :   const Real _epsilon_squared;
     231             : 
     232             :   /**
     233             :    * Epsilon squared value determined at runtime during each assembly. The value
     234             :    * depends on whether the mesh is tangled.
     235             :    */
     236             :   Real _epsilon_squared_assembly;
     237             : 
     238             :   /**
     239             :   * The reference volume for each element
     240             :   */
     241             :   Real _ref_vol;
     242             : 
     243             :   /**
     244             :   * The relative weight to give the dilation metric. The distortion metric is given weight 1 - _dilation_weight.
     245             :   */
     246             :   Real _dilation_weight;
     247             : 
     248             :   /* Map to hold target qp-dependent element target-to-reference mapping
     249             :    * Jacobians, if any
     250             :    */
     251             :   std::map<ElemType, std::vector<RealTensor>> _target_jacobians;
     252             : 
     253             :   /*
     254             :    * Map to hold the determinants of _target_jacobians.
     255             :    */
     256             :   std::map<ElemType, std::vector<Real>> _target_jacobian_dets;
     257             : 
     258             :   /**
     259             :    * Information about the mesh quality.
     260             :    */
     261             :   MeshQualityInfo _mesh_info;
     262             : 
     263             :   /**
     264             :    * Flag to indicate if the current solve is to untangle or smooth
     265             :    */
     266             :   bool _untangling_solve;
     267             : 
     268             :   /**
     269             :    * The quadrature rule type used to integrate the distortion-dilation metric.
     270             :    * See set_quadrature_type().
     271             :    */
     272             :   QuadratureType _quadrature_type;
     273             : };
     274             : 
     275             : } // namespace libMesh
     276             : 
     277             : #endif // LIBMESH_VARIATIONAL_SMOOTHER_SYSTEM_H

Generated by: LCOV version 1.14