LCOV - code coverage report
Current view: top level - include/systems - variational_smoother_system.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4232 (290bfc) with base 82cc40 Lines: 10 10 100.0 %
Date: 2025-08-27 15:46:53 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 :       _ref_vol(0.),
      94        1273 :       _dilation_weight(0.5),
      95        1387 :       _untangling_solve(false)
      96        1349 :   {}
      97             : 
      98             :   // Default destructor
      99             :   ~VariationalSmootherSystem() override;
     100             : 
     101             :   /**
     102             :    * Assembly method to update the mesh based on the smoother solve.
     103             :    */
     104             :   virtual void assembly (bool get_residual,
     105             :                          bool get_jacobian,
     106             :                          bool apply_heterogeneous_constraints = false,
     107             :                          bool apply_no_constraints = false) override;
     108             : 
     109          38 :   Real & get_dilation_weight() { return _dilation_weight; }
     110             : 
     111             :   /**
     112             :    * Solves the system to smooth the mesh. If the mesh is initially tangled,
     113             :    * a solve is first performed to untangle the mesh, followed by a solve to
     114             :    * smooth the mesh.
     115             :    */
     116             :   virtual void solve() override;
     117             : 
     118             :   /**
     119             :    * Get the target element for a given element type.
     120             :    * @param type Element type
     121             :    * @return a std::pair containing the target element for type and the
     122             :    * corresponding nodes that must be kept in scope while the target element is
     123             :    * used.
     124             :    */
     125             :   static std::pair<std::unique_ptr<Elem>, std::vector<std::unique_ptr<Node>>>
     126             :   get_target_elem(const ElemType & type);
     127             : 
     128             :   /**
     129             :    * Get the jacobians (and determinants) of the target-to-reference element mapping.
     130             :    * @param target_elem Target element.
     131             :    * @param femcontext Context used to build mapping.
     132             :    * @param jacobian Vector in which to store the jacobians for each quadrature point.
     133             :    * @param jacobian_dets Vector in which to store the determinant of the jacobians
     134             :    * for each quadrature point.
     135             :    */
     136             :   static void get_target_to_reference_jacobian(const Elem * const target_elem,
     137             :                                                const FEMContext & femcontext,
     138             :                                                std::vector<RealTensor> & jacobians,
     139             :                                                std::vector<Real> & jacobian_dets);
     140             : 
     141             :   /**
     142             :    * Getter for the _mesh_info attribute. If this attribute has not yet been
     143             :    * initialized, compute_mesh_quality_info is called to initialize it.
     144             :    */
     145             :   const MeshQualityInfo & get_mesh_info();
     146             : 
     147             :   /*
     148             :    * Computes information about the mesh quality and sets the _mesh_info attribute.
     149             :    */
     150             :   void compute_mesh_quality_info();
     151             : 
     152             : protected:
     153             : 
     154             :   // System initialization
     155             :   virtual void init_data () override;
     156             : 
     157             :   // Context initialization
     158             :   virtual void init_context (libMesh::DiffContext & context) override;
     159             : 
     160             :   // Element residual and jacobian calculations
     161             :   // Time dependent parts
     162             :   virtual bool element_time_derivative (bool request_jacobian,
     163             :                                         libMesh::DiffContext & context) override;
     164             : 
     165             :   /* Computes the element reference volume used in the dilation metric
     166             :    * The reference value is set to the averaged value of all elements' average
     167             :    * |J|. Also computes any applicable target element inverse Jacobians. Target
     168             :    * elements are relavant when the reference element does not minimize the
     169             :    * distortion metric.
     170             :    */
     171             :   void prepare_for_smoothing();
     172             : 
     173             :   /**
     174             :   * The small nonzero constant to prevent zero denominators (degenerate meshes only)
     175             :   */
     176             :   const Real _epsilon_squared;
     177             : 
     178             :   /**
     179             :    * Epsilon squared value determined at runtime during each assembly. The value
     180             :    * depends on whether the mesh is tangled.
     181             :    */
     182             :   Real _epsilon_squared_assembly;
     183             : 
     184             :   /**
     185             :   * The reference volume for each element
     186             :   */
     187             :   Real _ref_vol;
     188             : 
     189             :   /**
     190             :   * The relative weight to give the dilation metric. The distortion metric is given weight 1 - _dilation_weight.
     191             :   */
     192             :   Real _dilation_weight;
     193             : 
     194             :   /* Map to hold target qp-dependent element target-to-reference mapping
     195             :    * Jacobians, if any
     196             :    */
     197             :   std::map<ElemType, std::vector<RealTensor>> _target_jacobians;
     198             : 
     199             :   /*
     200             :    * Map to hold the determinants of _target_jacobians.
     201             :    */
     202             :   std::map<ElemType, std::vector<Real>> _target_jacobian_dets;
     203             : 
     204             :   /**
     205             :    * Information about the mesh quality.
     206             :    */
     207             :   MeshQualityInfo _mesh_info;
     208             : 
     209             :   /**
     210             :    * Flag to indicate if the current solve is to untangle or smooth
     211             :    */
     212             :   bool _untangling_solve;
     213             : };
     214             : 
     215             : } // namespace libMesh
     216             : 
     217             : #endif // LIBMESH_VARIATIONAL_SMOOTHER_SYSTEM_H

Generated by: LCOV version 1.14