LCOV - code coverage report
Current view: top level - src/utils - error_vector.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 63 126 50.0 %
Date: 2025-08-19 19:27:09 Functions: 5 10 50.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             : 
      19             : // C++ includes
      20             : #include <limits>
      21             : 
      22             : // Local includes
      23             : #include "libmesh/dof_map.h"
      24             : #include "libmesh/elem.h"
      25             : #include "libmesh/enum_xdr_mode.h"
      26             : #include "libmesh/error_vector.h"
      27             : #include "libmesh/equation_systems.h"
      28             : #include "libmesh/explicit_system.h"
      29             : #include "libmesh/libmesh_logging.h"
      30             : #include "libmesh/mesh_base.h"
      31             : #include "libmesh/numeric_vector.h"
      32             : 
      33             : #include "libmesh/exodusII_io.h"
      34             : #include "libmesh/gmv_io.h"
      35             : #include "libmesh/nemesis_io.h"
      36             : #include "libmesh/tecplot_io.h"
      37             : #include "libmesh/xdr_io.h"
      38             : 
      39             : namespace libMesh
      40             : {
      41             : 
      42             : 
      43             : 
      44             : // ------------------------------------------------------------
      45             : // ErrorVector class member functions
      46           0 : ErrorVectorReal ErrorVector::minimum() const
      47             : {
      48           0 :   LOG_SCOPE ("minimum()", "ErrorVector");
      49             : 
      50           0 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
      51           0 :   ErrorVectorReal min = std::numeric_limits<ErrorVectorReal>::max();
      52             : 
      53           0 :   for (dof_id_type i=0; i<n; i++)
      54             :     {
      55             :       // Only positive (or zero) values in the error vector
      56           0 :       libmesh_assert_greater_equal ((*this)[i], 0.);
      57           0 :       if (this->is_active_elem(i))
      58           0 :         min = std::min (min, (*this)[i]);
      59             :     }
      60             : 
      61             :   // ErrorVectors are for positive values
      62           0 :   libmesh_assert_greater_equal (min, 0.);
      63             : 
      64           0 :   return min;
      65             : }
      66             : 
      67             : 
      68             : 
      69       14409 : Real ErrorVector::mean() const
      70             : {
      71         457 :   LOG_SCOPE ("mean()", "ErrorVector");
      72             : 
      73         914 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
      74             : 
      75         457 :   Real the_mean  = 0;
      76         457 :   dof_id_type nnz = 0;
      77             : 
      78      762634 :   for (dof_id_type i=0; i<n; i++)
      79      748225 :     if (this->is_active_elem(i))
      80             :       {
      81      550350 :         the_mean += ( static_cast<Real>((*this)[i]) - the_mean ) / (nnz + 1);
      82             : 
      83       15837 :         nnz++;
      84             :       }
      85             : 
      86       14866 :   return the_mean;
      87             : }
      88             : 
      89             : 
      90             : 
      91             : 
      92           0 : Real ErrorVector::median()
      93             : {
      94           0 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
      95             : 
      96           0 :   if (n == 0)
      97           0 :     return 0.;
      98             : 
      99             : 
     100             :   // Build a StatisticsVector<ErrorVectorReal> containing
     101             :   // only our active entries and take its mean
     102           0 :   StatisticsVector<ErrorVectorReal> sv;
     103             : 
     104           0 :   sv.reserve (n);
     105             : 
     106           0 :   for (dof_id_type i=0; i<n; i++)
     107           0 :     if (this->is_active_elem(i))
     108           0 :       sv.push_back((*this)[i]);
     109             : 
     110           0 :   return sv.median();
     111             : }
     112             : 
     113             : 
     114             : 
     115             : 
     116           0 : Real ErrorVector::median() const
     117             : {
     118           0 :   ErrorVector ev = (*this);
     119             : 
     120           0 :   return ev.median();
     121             : }
     122             : 
     123             : 
     124             : 
     125             : 
     126        2982 : Real ErrorVector::variance(const Real mean_in) const
     127             : {
     128         168 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
     129             : 
     130          84 :   LOG_SCOPE ("variance()", "ErrorVector");
     131             : 
     132          84 :   Real the_variance = 0;
     133          84 :   dof_id_type nnz = 0;
     134             : 
     135      178658 :   for (dof_id_type i=0; i<n; i++)
     136      175676 :     if (this->is_active_elem(i))
     137             :       {
     138      135236 :         const Real delta = ( static_cast<Real>((*this)[i]) - mean_in );
     139      135236 :         the_variance += (delta * delta - the_variance) / (nnz + 1);
     140             : 
     141        3812 :         nnz++;
     142             :       }
     143             : 
     144        3066 :   return the_variance;
     145             : }
     146             : 
     147             : 
     148             : 
     149             : 
     150           0 : std::vector<dof_id_type> ErrorVector::cut_below(Real cut) const
     151             : {
     152           0 :   LOG_SCOPE ("cut_below()", "ErrorVector");
     153             : 
     154           0 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
     155             : 
     156           0 :   std::vector<dof_id_type> cut_indices;
     157           0 :   cut_indices.reserve(n/2);  // Arbitrary
     158             : 
     159           0 :   for (dof_id_type i=0; i<n; i++)
     160           0 :     if (this->is_active_elem(i))
     161             :       {
     162           0 :         if ((*this)[i] < cut)
     163             :           {
     164           0 :             cut_indices.push_back(i);
     165             :           }
     166             :       }
     167             : 
     168           0 :   return cut_indices;
     169             : }
     170             : 
     171             : 
     172             : 
     173             : 
     174           0 : std::vector<dof_id_type> ErrorVector::cut_above(Real cut) const
     175             : {
     176           0 :   LOG_SCOPE ("cut_above()", "ErrorVector");
     177             : 
     178           0 :   const dof_id_type n = cast_int<dof_id_type>(this->size());
     179             : 
     180           0 :   std::vector<dof_id_type> cut_indices;
     181           0 :   cut_indices.reserve(n/2);  // Arbitrary
     182             : 
     183           0 :   for (dof_id_type i=0; i<n; i++)
     184           0 :     if (this->is_active_elem(i))
     185             :       {
     186           0 :         if ((*this)[i] > cut)
     187             :           {
     188           0 :             cut_indices.push_back(i);
     189             :           }
     190             :       }
     191             : 
     192           0 :   return cut_indices;
     193             : }
     194             : 
     195             : 
     196             : 
     197      923901 : bool ErrorVector::is_active_elem (dof_id_type i) const
     198             : {
     199       27383 :   libmesh_assert_less (i, this->size());
     200             : 
     201      923901 :   if (_mesh)
     202             :     {
     203           0 :       return _mesh->elem_ptr(i)->active();
     204             :     }
     205             :   else
     206      951288 :     return ((*this)[i] != 0.);
     207             : }
     208             : 
     209             : 
     210       11117 : void ErrorVector::plot_error(const std::string & filename,
     211             :                              const MeshBase & oldmesh,
     212             :                              const std::string & data_type) const
     213             : {
     214       11505 :   std::unique_ptr<MeshBase> meshptr = oldmesh.clone();
     215         388 :   MeshBase & mesh = *meshptr;
     216             : 
     217             :   // The all_first_order routine will prepare_for_use(), which would
     218             :   // break our ordering if elements get changed.
     219         388 :   mesh.allow_renumbering(false);
     220       11117 :   mesh.all_first_order();
     221             : 
     222             : #ifdef LIBMESH_ENABLE_AMR
     223             :   // We don't want p elevation when plotting a single constant value
     224             :   // per element
     225      480398 :   for (auto & elem : mesh.element_ptr_range())
     226             :     {
     227      255194 :       elem->set_p_refinement_flag(Elem::DO_NOTHING);
     228      255194 :       elem->set_p_level(0);
     229       10341 :     }
     230             : #endif // LIBMESH_ENABLE_AMR
     231             : 
     232       11893 :   EquationSystems temp_es (mesh);
     233             :   ExplicitSystem & error_system
     234       11117 :     = temp_es.add_system<ExplicitSystem> ("Error");
     235       11505 :   error_system.add_variable(data_type, CONSTANT, MONOMIAL);
     236             : 
     237       11117 :   temp_es.init();
     238             : 
     239         388 :   const DofMap & error_dof_map = error_system.get_dof_map();
     240         776 :   std::vector<dof_id_type> dof_indices;
     241             : 
     242      178194 :   for (const auto & elem : mesh.active_local_element_ptr_range())
     243             :     {
     244       91417 :       error_dof_map.dof_indices(elem, dof_indices);
     245             : 
     246       91417 :       const dof_id_type elem_id = elem->id();
     247             : 
     248             :       //0 for the monomial basis
     249       91417 :       const dof_id_type solution_index = dof_indices[0];
     250             : 
     251             :       // libMesh::out << "elem_number=" << elem_number << std::endl;
     252        9608 :       libmesh_assert_less (elem_id, (*this).size());
     253             : 
     254             :       // We may have zero error values in special circumstances
     255             :       // libmesh_assert_greater ((*this)[elem_id], 0.);
     256      101025 :       error_system.solution->set(solution_index, (*this)[elem_id]);
     257       10341 :     }
     258       11117 :   error_system.solution->close();
     259       11117 :   error_system.update();
     260             : 
     261             :   // We may have to renumber if the original numbering was not
     262             :   // contiguous.  Since this is just a temporary mesh, that's probably
     263             :   // fine.
     264       22234 :   if (mesh.max_elem_id() != mesh.n_elem() ||
     265       11117 :       mesh.max_node_id() != mesh.n_nodes())
     266             :     {
     267         384 :       mesh.allow_renumbering(true);
     268        9644 :       mesh.renumber_nodes_and_elements();
     269             :     }
     270             : 
     271       11117 :   if (Utility::contains(filename, ".gmv"))
     272             :     {
     273        3946 :       GMVIO(mesh).write_discontinuous_gmv(filename,
     274             :                                           temp_es, false);
     275             :     }
     276        7171 :   else if (Utility::contains(filename, ".plt"))
     277             :     {
     278           0 :       TecplotIO (mesh).write_equation_systems
     279           0 :         (filename, temp_es);
     280             :     }
     281             : #if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_HAVE_NEMESIS_API)
     282       14342 :   else if (Utility::contains(filename, ".nem") ||
     283        7373 :            Utility::contains(filename, ".n"))
     284             :     {
     285        7575 :       Nemesis_IO io(mesh);
     286        7171 :       io.write(filename);
     287        7171 :       io.write_element_data(temp_es);
     288        6767 :     }
     289             : #endif
     290             : #ifdef LIBMESH_HAVE_EXODUS_API
     291           0 :   else if (Utility::contains(filename, ".exo") ||
     292           0 :            Utility::contains(filename, ".e"))
     293             :     {
     294           0 :       ExodusII_IO io(mesh);
     295           0 :       io.write(filename);
     296           0 :       io.write_element_data(temp_es);
     297           0 :     }
     298             : #endif
     299           0 :   else if (Utility::contains(filename, ".xda"))
     300             :     {
     301           0 :       XdrIO(mesh).write("mesh-"+filename);
     302           0 :       temp_es.write("soln-"+filename,WRITE,
     303             :                     EquationSystems::WRITE_DATA |
     304             :                     EquationSystems::WRITE_ADDITIONAL_DATA);
     305             :     }
     306           0 :   else if (Utility::contains(filename, ".xdr"))
     307             :     {
     308           0 :       XdrIO(mesh,true).write("mesh-"+filename);
     309           0 :       temp_es.write("soln-"+filename,ENCODE,
     310             :                     EquationSystems::WRITE_DATA |
     311             :                     EquationSystems::WRITE_ADDITIONAL_DATA);
     312             :     }
     313             :   else
     314             :     {
     315           0 :       libmesh_here();
     316           0 :       libMesh::err << "Warning: ErrorVector::plot_error currently only"
     317           0 :                    << " supports .gmv, .plt, .xdr/.xda, and .exo/.e (if enabled) output;" << std::endl;
     318           0 :       libMesh::err << "Could not recognize filename: " << filename
     319           0 :                    << std::endl;
     320             :     }
     321       11117 : }
     322             : 
     323             : } // namespace libMesh

Generated by: LCOV version 1.14