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_FUZZY_EQUAL_H 19 : #define LIBMESH_FUZZY_EQUAL_H 20 : 21 : #include "libmesh/libmesh_common.h" 22 : #include "libmesh/tensor_tools.h" 23 : #include "libmesh/compare_types.h" 24 : #include "libmesh/int_range.h" 25 : 26 : #ifdef LIBMESH_HAVE_METAPHYSICL 27 : #include "metaphysicl/raw_type.h" 28 : #endif 29 : 30 : namespace libMesh 31 : { 32 : /** 33 : * Computes the L1 norm 34 : */ 35 : template <typename T, typename std::enable_if<ScalarTraits<T>::value, int>::type = 0> 36 : auto 37 883 : l1_norm(const T & var) 38 : { 39 883 : return std::abs(var); 40 : } 41 : 42 : /** 43 : * Computes the L1 norm of the diff between \p var1 and \p var2 44 : */ 45 : template <typename T, 46 : typename T2, 47 : typename std::enable_if<ScalarTraits<T>::value && ScalarTraits<T2>::value, int>::type = 0> 48 : auto 49 883 : l1_norm_diff(const T & var1, const T2 & var2) 50 : { 51 14448682 : return l1_norm(var1 - var2); 52 : } 53 : 54 : #ifdef LIBMESH_HAVE_METAPHYSICL 55 : /** 56 : * Function to check whether two variables are equal within an absolute tolerance 57 : * @param var1 The first variable to be checked 58 : * @param var2 The second variable to be checked 59 : * @param tol The tolerance to be used 60 : * @return true if var1 and var2 are equal within tol 61 : */ 62 : template <typename T, typename T2> 63 : bool 64 35190752 : absolute_fuzzy_equals(const T & var1, const T2 & var2, const Real tol = TOLERANCE * TOLERANCE) 65 : { 66 440143926 : return MetaPhysicL::raw_value(l1_norm_diff(var1, var2)) <= tol; 67 : } 68 : 69 : /** 70 : * Function to check whether two variables are equal within a relative tolerance 71 : * @param var1 The first variable to be checked 72 : * @param var2 The second variable to be checked 73 : * @param tol The relative tolerance to be used 74 : * @return true if var1 and var2 are equal within relative tol 75 : */ 76 : template <typename T, typename T2> 77 : bool 78 410485149 : relative_fuzzy_equals(const T & var1, const T2 & var2, const Real tol = TOLERANCE * TOLERANCE) 79 : { 80 445593035 : return absolute_fuzzy_equals( 81 : var1, 82 : var2, 83 410485149 : tol * (MetaPhysicL::raw_value(l1_norm(var1)) + MetaPhysicL::raw_value(l1_norm(var2)))); 84 : } 85 : #else 86 : /** 87 : * Function to check whether two variables are equal within an absolute tolerance 88 : * @param var1 The first variable to be checked 89 : * @param var2 The second variable to be checked 90 : * @param tol The tolerance to be used 91 : * @return true if var1 and var2 are equal within tol 92 : */ 93 : template <typename T, typename T2> 94 : bool 95 : absolute_fuzzy_equals(const T & var1, const T2 & var2, const Real tol = TOLERANCE * TOLERANCE) 96 : { 97 : return l1_norm_diff(var1, var2) <= tol; 98 : } 99 : 100 : /** 101 : * Function to check whether two variables are equal within a relative tolerance 102 : * @param var1 The first variable to be checked 103 : * @param var2 The second variable to be checked 104 : * @param tol The relative tolerance to be used 105 : * @return true if var1 and var2 are equal within relative tol 106 : */ 107 : template <typename T, typename T2> 108 : bool 109 : relative_fuzzy_equals(const T & var1, const T2 & var2, const Real tol = TOLERANCE * TOLERANCE) 110 : { 111 : return absolute_fuzzy_equals(var1, var2, tol * (l1_norm(var1) + l1_norm(var2))); 112 : } 113 : #endif 114 : 115 : } // namespace libMesh 116 : 117 : #endif // LIBMESH_FUZZY_EQUAL_H