LCOV - code coverage report
Current view: top level - include/error_estimation - exact_solution.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 1 3 33.3 %
Date: 2025-08-19 19:27:09 Functions: 1 3 33.3 %
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_EXACT_SOLUTION_H
      19             : #define LIBMESH_EXACT_SOLUTION_H
      20             : 
      21             : 
      22             : // Local Includes
      23             : #include "libmesh/libmesh_common.h" // for Number
      24             : 
      25             : // C++ includes
      26             : #include <map>
      27             : #include <vector>
      28             : #include <memory>
      29             : #include <set>
      30             : 
      31             : namespace libMesh
      32             : {
      33             : 
      34             : 
      35             : // Forward Declarations
      36             : class Point;
      37             : class EquationSystems;
      38             : class Parameters;
      39             : class Mesh;
      40             : template <typename Output> class FunctionBase;
      41             : template <typename Output> class FEMFunctionBase;
      42             : enum FEMNormType : int;
      43             : 
      44             : // Is there any way to simplify this?
      45             : // All we need are Tensor and Gradient. - RHS
      46             : template <typename T> class TensorValue;
      47             : template <typename T> class VectorValue;
      48             : typedef TensorValue<Number> NumberTensorValue;
      49             : typedef NumberTensorValue   Tensor;
      50             : typedef VectorValue<Number> NumberVectorValue;
      51             : typedef NumberVectorValue   Gradient;
      52             : 
      53             : /**
      54             :  * This class handles the computation of the L2 and/or H1 error for
      55             :  * the Systems in the EquationSystems object which is passed to it.
      56             :  *
      57             :  * \note For this to be useful, the user must attach at least one, and
      58             :  * possibly two, functions which can compute the exact solution and
      59             :  * its derivative for any component of any system.  These are the \p
      60             :  * exact_value and \p exact_deriv functions below.
      61             :  *
      62             :  * \author Benjamin S. Kirk
      63             :  * \author John W. Peterson (modifications for libmesh)
      64             :  * \date 2004
      65             :  */
      66         606 : class ExactSolution
      67             : {
      68             : 
      69             : public:
      70             :   /**
      71             :    * Constructor.  The ExactSolution object
      72             :    * must be initialized with an EquationSystems
      73             :    * object.
      74             :    */
      75             :   explicit
      76             :   ExactSolution (const EquationSystems & es);
      77             : 
      78             :   /**
      79             :    * The copy constructor and copy/move assignment operators are
      80             :    * deleted.  This class has containers of unique_ptrs so it can't be
      81             :    * default (shallow) copied, and it has a const reference so it
      82             :    * can't be assigned to after creation.
      83             :    */
      84             :   ExactSolution(const ExactSolution &) = delete;
      85             :   ExactSolution & operator= (const ExactSolution &) = delete;
      86             :   ExactSolution & operator= (ExactSolution &&) = delete;
      87             : 
      88             :   /**
      89             :    * Move constructor and destructor are defaulted out-of-line (in the
      90             :    * C file) to play nicely with our forward declarations.
      91             :    */
      92             :   ExactSolution(ExactSolution &&);
      93             :   ~ExactSolution();
      94             : 
      95             :   /**
      96             :    * The user can indicate that elements in certain subdomains should be
      97             :    * excluded from the error calculation by passing in a set of subdomain
      98             :    * ids to ignore. By default, all subdomains are considered in the error
      99             :    * calculation.
     100             :    */
     101             :   void set_excluded_subdomains(const std::set<subdomain_id_type> & excluded);
     102             : 
     103             :   /**
     104             :    * Attach function similar to system.h which
     105             :    * allows the user to attach a second EquationSystems
     106             :    * object with a reference fine grid solution.
     107             :    */
     108             :   void attach_reference_solution (const EquationSystems * es_fine);
     109             : 
     110             :   /**
     111             :    * Clone and attach arbitrary functors which compute the exact
     112             :    * values of the EquationSystems' solutions at any point.
     113             :    */
     114             :   void attach_exact_values (const std::vector<FunctionBase<Number> *> & f);
     115             : 
     116             :   /**
     117             :    * Clone and attach arbitrary functors which compute the exact
     118             :    * values of the EquationSystems' solutions at any point.
     119             :    */
     120             :   void attach_exact_values (const std::vector<FEMFunctionBase<Number> *> & f);
     121             : 
     122             :   /**
     123             :    * Clone and attach an arbitrary functor which computes the exact
     124             :    * value of the system \p sys_num solution at any point.
     125             :    */
     126             :   void attach_exact_value (unsigned int sys_num,
     127             :                            FunctionBase<Number> * f);
     128             : 
     129             :   /**
     130             :    * Clone and attach an arbitrary functor which computes the exact
     131             :    * value of the system \p sys_num solution at any point.
     132             :    */
     133             :   void attach_exact_value (unsigned int sys_num,
     134             :                            FEMFunctionBase<Number> * f);
     135             : 
     136             :   /**
     137             :    * Attach an arbitrary function which computes the exact value of
     138             :    * the solution at any point.
     139             :    */
     140             :   typedef Number (*ValueFunctionPointer)(const Point & p,
     141             :                                          const Parameters & Parameters,
     142             :                                          const std::string & sys_name,
     143             :                                          const std::string & unknown_name);
     144             :   void attach_exact_value (ValueFunctionPointer fptr);
     145             : 
     146             :   /**
     147             :    * Clone and attach arbitrary functors which compute the exact
     148             :    * gradients of the EquationSystems' solutions at any point.
     149             :    */
     150             :   void attach_exact_derivs (const std::vector<FunctionBase<Gradient> *> & g);
     151             : 
     152             :   /**
     153             :    * Clone and attach arbitrary functors which compute the exact
     154             :    * gradients of the EquationSystems' solutions at any point.
     155             :    */
     156             :   void attach_exact_derivs (const std::vector<FEMFunctionBase<Gradient> *> & g);
     157             : 
     158             :   /**
     159             :    * Clone and attach an arbitrary functor which computes the exact
     160             :    * gradient of the system \p sys_num solution at any point.
     161             :    */
     162             :   void attach_exact_deriv (unsigned int sys_num,
     163             :                            FunctionBase<Gradient> * g);
     164             : 
     165             :   /**
     166             :    * Clone and attach an arbitrary functor which computes the exact
     167             :    * gradient of the system \p sys_num solution at any point.
     168             :    */
     169             :   void attach_exact_deriv (unsigned int sys_num,
     170             :                            FEMFunctionBase<Gradient> * g);
     171             : 
     172             :   /**
     173             :    * Attach an arbitrary function which computes the exact gradient of
     174             :    * the solution at any point.
     175             :    */
     176             :   typedef Gradient (*GradientFunctionPointer)(const Point & p,
     177             :                                               const Parameters & parameters,
     178             :                                               const std::string & sys_name,
     179             :                                               const std::string & unknown_name);
     180             :   void attach_exact_deriv (GradientFunctionPointer gptr);
     181             : 
     182             :   /**
     183             :    * Clone and attach arbitrary functors which compute the exact
     184             :    * second derivatives of the EquationSystems' solutions at any point.
     185             :    */
     186             :   void attach_exact_hessians (std::vector<FunctionBase<Tensor> *> h);
     187             :   /**
     188             :    * Clone and attach arbitrary functors which compute the exact
     189             :    * second derivatives of the EquationSystems' solutions at any point.
     190             :    */
     191             :   void attach_exact_hessians (std::vector<FEMFunctionBase<Tensor> *> h);
     192             : 
     193             :   /**
     194             :    * Clone and attach an arbitrary functor which computes the exact
     195             :    * second derivatives of the system \p sys_num solution at any point.
     196             :    */
     197             :   void attach_exact_hessian (unsigned int sys_num,
     198             :                              FunctionBase<Tensor> * h);
     199             : 
     200             :   /**
     201             :    * Clone and attach an arbitrary functor which computes the exact
     202             :    * second derivatives of the system \p sys_num solution at any point.
     203             :    */
     204             :   void attach_exact_hessian (unsigned int sys_num,
     205             :                              FEMFunctionBase<Tensor> * h);
     206             : 
     207             :   /**
     208             :    * Attach an arbitrary function which computes the exact second
     209             :    * derivatives of the solution at any point.
     210             :    */
     211             :   typedef Tensor (*HessianFunctionPointer)(const Point & p,
     212             :                                            const Parameters & parameters,
     213             :                                            const std::string & sys_name,
     214             :                                            const std::string & unknown_name);
     215             :   void attach_exact_hessian (HessianFunctionPointer hptr);
     216             : 
     217             :   /**
     218             :    * Increases or decreases the order of the quadrature rule used for numerical
     219             :    * integration.  The default \p extraorder is 1, because properly
     220             :    * integrating L2 error requires integrating the squares of terms
     221             :    * with order p+1, and 2p+2 is 1 higher than what we default to
     222             :    * using for reasonable mass matrix integration.
     223             :    */
     224           0 :   void extra_quadrature_order (const int extraorder)
     225           0 :   { _extra_order = extraorder; }
     226             : 
     227             :   /**
     228             :    * Computes and stores the error in the solution value e = u-u_h,
     229             :    * the gradient grad(e) = grad(u) - grad(u_h), and possibly the hessian
     230             :    * grad(grad(e)) = grad(grad(u)) - grad(grad(u_h)).  Does not return
     231             :    * any value.  For that you need to call the l2_error(), h1_error()
     232             :    * or h2_error() functions respectively.
     233             :    */
     234             :   void compute_error(std::string_view sys_name,
     235             :                      std::string_view unknown_name);
     236             : 
     237             :   /**
     238             :    * \returns The integrated L2 error for the system \p sys_name for the
     239             :    * unknown \p unknown_name.
     240             :    *
     241             :    * \note No error computations are actually performed, you must call
     242             :    * \p compute_error() for that.
     243             :    */
     244             :   Real l2_error(std::string_view sys_name,
     245             :                 std::string_view unknown_name);
     246             : 
     247             :   /**
     248             :    * \returns The integrated L1 error for the system \p sys_name for
     249             :    * the unknown \p unknown_name.
     250             :    *
     251             :    * \note No error computations are actually performed, you must call
     252             :    * \p compute_error() for that.
     253             :    */
     254             :   Real l1_error(std::string_view sys_name,
     255             :                 std::string_view unknown_name);
     256             : 
     257             :   /**
     258             :    * \returns The L_INF error for the system \p sys_name for
     259             :    * the unknown \p unknown_name.
     260             :    *
     261             :    * \note No error computations are actually performed, you must call
     262             :    * compute_error() for that.
     263             :    *
     264             :    * \note The result (as for the other norms as well) is not exact,
     265             :    * but an approximation based on the chosen quadrature rule: to
     266             :    * compute it, we take the max of the absolute value of the error
     267             :    * over all the quadrature points.
     268             :    */
     269             :   Real l_inf_error(std::string_view sys_name,
     270             :                    std::string_view unknown_name);
     271             : 
     272             :   /**
     273             :    * \returns The H1 error for the system \p sys_name for the unknown
     274             :    * \p unknown_name.
     275             :    *
     276             :    * \note No error computations are actually performed, you must call
     277             :    * \p compute_error() for that.
     278             :    */
     279             :   Real h1_error(std::string_view sys_name,
     280             :                 std::string_view unknown_name);
     281             : 
     282             :   /**
     283             :    * \returns The H(curl) error for the system \p sys_name for the
     284             :    * unknown \p unknown_name.
     285             :    *
     286             :    * \note No error computations are actually performed, you must call
     287             :    * \p compute_error() for that.
     288             :    *
     289             :    * \note This is only valid for vector-valued elements. An error is
     290             :    * thrown if requested for scalar-valued elements.
     291             :    */
     292             :   Real hcurl_error(std::string_view sys_name,
     293             :                    std::string_view unknown_name);
     294             : 
     295             :   /**
     296             :    * \returns The H(div) error for the system \p sys_name for the
     297             :    * unknown \p unknown_name.
     298             :    *
     299             :    * \note No error computations are actually performed, you must call
     300             :    * \p compute_error() for that.
     301             :    *
     302             :    * \note This is only valid for vector-valued elements. An error is
     303             :    * thrown if requested for scalar-valued elements.
     304             :    */
     305             :   Real hdiv_error(std::string_view sys_name,
     306             :                   std::string_view unknown_name);
     307             : 
     308             :   /**
     309             :    * \returns The H2 error for the system \p sys_name for the unknown
     310             :    * \p unknown_name.
     311             :    *
     312             :    * \note No error computations are actually performed, you must call
     313             :    * \p compute_error() for that.
     314             :    */
     315             :   Real h2_error(std::string_view sys_name,
     316             :                 std::string_view unknown_name);
     317             : 
     318             :   /**
     319             :    * \returns The error in the requested norm for the system \p
     320             :    * sys_name for the unknown \p unknown_name.
     321             :    *
     322             :    * \note No error computations are actually performed, you must call
     323             :    * \p compute_error() for that.
     324             :    *
     325             :    * \note The result is not exact, but an approximation based on the
     326             :    * chosen quadrature rule.
     327             :    */
     328             :   Real error_norm(std::string_view sys_name,
     329             :                   std::string_view unknown_name,
     330             :                   const FEMNormType & norm);
     331             : private:
     332             : 
     333             :   /**
     334             :    * This function computes the error (in the solution and its first
     335             :    * derivative) for a single unknown in a single system.  It is a
     336             :    * private function since it is used by the implementation when
     337             :    * solving for several unknowns in several systems.
     338             :    */
     339             :   template<typename OutputShape>
     340             :   void _compute_error(std::string_view sys_name,
     341             :                       std::string_view unknown_name,
     342             :                       std::vector<Real> & error_vals);
     343             : 
     344             :   /**
     345             :    * This function is responsible for checking the validity of the \p
     346             :    * sys_name and \p unknown_name inputs.
     347             :    *
     348             :    * \returns A reference to the proper vector for storing the values.
     349             :    */
     350             :   std::vector<Real> & _check_inputs(std::string_view sys_name,
     351             :                                     std::string_view unknown_name);
     352             : 
     353             :   /**
     354             :    * User-provided functors which compute the exact value of the
     355             :    * solution for each system.
     356             :    */
     357             :   std::vector<std::unique_ptr<FEMFunctionBase<Number>>> _exact_values;
     358             : 
     359             :   /**
     360             :    * User-provided functors which compute the exact derivative of the
     361             :    * solution for each system.
     362             :    */
     363             :   std::vector<std::unique_ptr<FEMFunctionBase<Gradient>>> _exact_derivs;
     364             : 
     365             :   /**
     366             :    * User-provided functors which compute the exact hessians of the
     367             :    * solution for each system.
     368             :    */
     369             :   std::vector<std::unique_ptr<FEMFunctionBase<Tensor>>> _exact_hessians;
     370             : 
     371             :   /**
     372             :    * Data structure which stores the errors:
     373             :    * ||e|| = ||u - u_h||
     374             :    * ||grad(e)|| = ||grad(u) - grad(u_h)||
     375             :    * for each unknown in a single system.
     376             :    * The name of the unknown is
     377             :    * the key for the map.
     378             :    */
     379             :   typedef std::map<std::string, std::vector<Real>, std::less<>>
     380             :     SystemErrorMap;
     381             : 
     382             :   /**
     383             :    * A map of SystemErrorMaps, which contains entries
     384             :    * for each system in the EquationSystems object.
     385             :    * This is required, since it is possible for two
     386             :    * systems to have unknowns with the *same name*.
     387             :    */
     388             :   std::map<std::string, SystemErrorMap, std::less<>> _errors;
     389             : 
     390             :   /**
     391             :    * Constant reference to the \p EquationSystems object
     392             :    * used for the simulation.
     393             :    */
     394             :   const EquationSystems & _equation_systems;
     395             : 
     396             :   /**
     397             :    * Constant pointer to the \p EquationSystems object
     398             :    * containing the fine grid solution.
     399             :    */
     400             :   const EquationSystems * _equation_systems_fine;
     401             : 
     402             :   /**
     403             :    * Extra order to use for quadrature rule
     404             :    */
     405             :   int _extra_order;
     406             : 
     407             :   /**
     408             :    * Elements in a subdomain from this set are skipped during the
     409             :    * error computation.
     410             :    */
     411             :   std::set<subdomain_id_type> _excluded_subdomains;
     412             : };
     413             : 
     414             : 
     415             : 
     416             : } // namespace libMesh
     417             : 
     418             : 
     419             : #endif // LIBMESH_EXACT_SOLUTION_H

Generated by: LCOV version 1.14