LCOV - code coverage report
Current view: top level - include/systems - variational_smoother_system.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4249 (f45222) with base 7cab9a Lines: 11 11 100.0 %
Date: 2025-09-10 12:25:45 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 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/fem_function_base.h"
      24             : #include "libmesh/fem_system.h"
      25             : #include "libmesh/libmesh_common.h"
      26             : 
      27             : // C++ includes
      28             : #include <map>
      29             : #include <memory>
      30             : 
      31             : namespace libMesh
      32             : {
      33             : 
      34             : /**
      35             :  * Struct to hold smoother-relevant information about the mesh quality.
      36             :  */
      37         114 : struct MeshQualityInfo
      38             : {
      39             :   // dof_id_types will hold the id of the Elem where the metric occurs
      40             :   // IMPORTANT: the Real should be the first entry of the pair so that taking
      41             :   // the min/max accross processors will compare the numeric values instead of
      42             :   // the element ids.
      43             : 
      44             :   std::pair<Real, dof_id_type> max_elem_distortion{std::numeric_limits<Real>::lowest(),
      45             :                                                    DofObject::invalid_id};
      46             :   std::pair<Real, dof_id_type> min_elem_distortion{std::numeric_limits<Real>::max(),
      47             :                                                    DofObject::invalid_id};
      48             :   Real total_distortion = 0.;
      49             : 
      50             :   std::pair<Real, dof_id_type> max_elem_dilation{std::numeric_limits<Real>::lowest(),
      51             :                                                  DofObject::invalid_id};
      52             :   std::pair<Real, dof_id_type> min_elem_dilation{std::numeric_limits<Real>::max(),
      53             :                                                  DofObject::invalid_id};
      54             :   Real total_dilation = 0.;
      55             : 
      56             :   std::pair<Real, dof_id_type> max_elem_combined{std::numeric_limits<Real>::lowest(),
      57             :                                                  DofObject::invalid_id};
      58             :   std::pair<Real, dof_id_type> min_elem_combined{std::numeric_limits<Real>::max(),
      59             :                                                  DofObject::invalid_id};
      60             :   Real total_combined = 0.;
      61             : 
      62             :   std::pair<Real, dof_id_type> max_elem_det_S{std::numeric_limits<Real>::lowest(),
      63             :                                               DofObject::invalid_id};
      64             :   std::pair<Real, dof_id_type> min_elem_det_S{std::numeric_limits<Real>::max(),
      65             :                                               DofObject::invalid_id};
      66             :   Real total_det_S = 0.;
      67             :   Real max_qp_det_S = std::numeric_limits<Real>::lowest();
      68             :   Real min_qp_det_S = std::numeric_limits<Real>::max();
      69             : 
      70             :   bool mesh_is_tangled = false;
      71             :   bool initialized = false;
      72             : };
      73             : 
      74             : // FEMSystem, TimeSolver and  NewtonSolver will handle most tasks,
      75             : // but we must specify element residuals
      76         190 : class VariationalSmootherSystem : public libMesh::FEMSystem
      77             : {
      78             : /**
      79             :  * This is an FEMSystem to solve the optimization probelem posed by the
      80             :  * VariationalMeshSmoother class.
      81             :  *
      82             :  * The residual is coded as the gradient of the distortion-dilation metric, and
      83             :  * the jacobian as analytically coded as the Hessian of the metric.
      84             :  *
      85             :  * The nodes of the system mesh are updated during the solve.
      86             :  */
      87             : public:
      88        1349 :   VariationalSmootherSystem(libMesh::EquationSystems & es,
      89             :                             const std::string & name,
      90             :                             const unsigned int number)
      91        1349 :     : libMesh::FEMSystem(es, name, number),
      92        1273 :       _epsilon_squared(TOLERANCE),
      93        1273 :       _epsilon_squared_assembly(0.),
      94        1273 :       _ref_vol(0.),
      95        1273 :       _dilation_weight(0.5),
      96        1387 :       _untangling_solve(false)
      97        1349 :   {}
      98             : 
      99             :   // Default destructor
     100             :   ~VariationalSmootherSystem() override;
     101             : 
     102             :   /**
     103             :    * Assembly method to update the mesh based on the smoother solve.
     104             :    */
     105             :   virtual void assembly (bool get_residual,
     106             :                          bool get_jacobian,
     107             :                          bool apply_heterogeneous_constraints = false,
     108             :                          bool apply_no_constraints = false) override;
     109             : 
     110          38 :   Real & get_dilation_weight() { return _dilation_weight; }
     111             : 
     112             :   /**
     113             :    * Solves the system to smooth the mesh. If the mesh is initially tangled,
     114             :    * a solve is first performed to untangle the mesh, followed by a solve to
     115             :    * smooth the mesh.
     116             :    */
     117             :   virtual void solve() override;
     118             : 
     119             :   /**
     120             :    * Get the target element for a given element type.
     121             :    * @param type Element type
     122             :    * @return a std::pair containing the target element for type and the
     123             :    * corresponding nodes that must be kept in scope while the target element is
     124             :    * used.
     125             :    */
     126             :   static std::pair<std::unique_ptr<Elem>, std::vector<std::unique_ptr<Node>>>
     127             :   get_target_elem(const ElemType & type);
     128             : 
     129             :   /**
     130             :    * Get the jacobians (and determinants) of the target-to-reference element mapping.
     131             :    * @param target_elem Target element.
     132             :    * @param femcontext Context used to build mapping.
     133             :    * @param jacobian Vector in which to store the jacobians for each quadrature point.
     134             :    * @param jacobian_dets Vector in which to store the determinant of the jacobians
     135             :    * for each quadrature point.
     136             :    */
     137             :   static void get_target_to_reference_jacobian(const Elem * const target_elem,
     138             :                                                const FEMContext & femcontext,
     139             :                                                std::vector<RealTensor> & jacobians,
     140             :                                                std::vector<Real> & jacobian_dets);
     141             : 
     142             :   /**
     143             :    * Getter for the _mesh_info attribute. If this attribute has not yet been
     144             :    * initialized, compute_mesh_quality_info is called to initialize it.
     145             :    */
     146             :   const MeshQualityInfo & get_mesh_info();
     147             : 
     148             :   /*
     149             :    * Computes information about the mesh quality and sets the _mesh_info attribute.
     150             :    */
     151             :   void compute_mesh_quality_info();
     152             : 
     153             : protected:
     154             : 
     155             :   // System initialization
     156             :   virtual void init_data () override;
     157             : 
     158             :   // Context initialization
     159             :   virtual void init_context (libMesh::DiffContext & context) override;
     160             : 
     161             :   // Element residual and jacobian calculations
     162             :   // Time dependent parts
     163             :   virtual bool element_time_derivative (bool request_jacobian,
     164             :                                         libMesh::DiffContext & context) override;
     165             : 
     166             :   /* Computes the element reference volume used in the dilation metric
     167             :    * The reference value is set to the averaged value of all elements' average
     168             :    * |J|. Also computes any applicable target element inverse Jacobians. Target
     169             :    * elements are relavant when the reference element does not minimize the
     170             :    * distortion metric.
     171             :    */
     172             :   void prepare_for_smoothing();
     173             : 
     174             :   /**
     175             :   * The small nonzero constant to prevent zero denominators (degenerate meshes only)
     176             :   */
     177             :   const Real _epsilon_squared;
     178             : 
     179             :   /**
     180             :    * Epsilon squared value determined at runtime during each assembly. The value
     181             :    * depends on whether the mesh is tangled.
     182             :    */
     183             :   Real _epsilon_squared_assembly;
     184             : 
     185             :   /**
     186             :   * The reference volume for each element
     187             :   */
     188             :   Real _ref_vol;
     189             : 
     190             :   /**
     191             :   * The relative weight to give the dilation metric. The distortion metric is given weight 1 - _dilation_weight.
     192             :   */
     193             :   Real _dilation_weight;
     194             : 
     195             :   /* Map to hold target qp-dependent element target-to-reference mapping
     196             :    * Jacobians, if any
     197             :    */
     198             :   std::map<ElemType, std::vector<RealTensor>> _target_jacobians;
     199             : 
     200             :   /*
     201             :    * Map to hold the determinants of _target_jacobians.
     202             :    */
     203             :   std::map<ElemType, std::vector<Real>> _target_jacobian_dets;
     204             : 
     205             :   /**
     206             :    * Information about the mesh quality.
     207             :    */
     208             :   MeshQualityInfo _mesh_info;
     209             : 
     210             :   /**
     211             :    * Flag to indicate if the current solve is to untangle or smooth
     212             :    */
     213             :   bool _untangling_solve;
     214             : };
     215             : 
     216             : } // namespace libMesh
     217             : 
     218             : #endif // LIBMESH_VARIATIONAL_SMOOTHER_SYSTEM_H

Generated by: LCOV version 1.14