LCOV - code coverage report
Current view: top level - src/error_estimation - uniform_refinement_estimator.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 0 303 0.0 %
Date: 2025-08-19 19:27:09 Functions: 0 10 0.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             : // Local Includes
      20             : #include "libmesh/dof_map.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/equation_systems.h"
      23             : #include "libmesh/error_vector.h"
      24             : #include "libmesh/fe.h"
      25             : #include "libmesh/libmesh_common.h"
      26             : #include "libmesh/libmesh_logging.h"
      27             : #include "libmesh/mesh_base.h"
      28             : #include "libmesh/mesh_refinement.h"
      29             : #include "libmesh/numeric_vector.h"
      30             : #include "libmesh/quadrature.h"
      31             : #include "libmesh/system.h"
      32             : #include "libmesh/uniform_refinement_estimator.h"
      33             : #include "libmesh/partitioner.h"
      34             : #include "libmesh/tensor_tools.h"
      35             : #include "libmesh/enum_error_estimator_type.h"
      36             : #include "libmesh/enum_norm_type.h"
      37             : #include "libmesh/int_range.h"
      38             : 
      39             : // C++ includes
      40             : #include <algorithm> // for std::fill
      41             : #include <sstream>
      42             : #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
      43             : #include <cmath>    // for sqrt
      44             : #include <memory>
      45             : 
      46             : #ifdef LIBMESH_ENABLE_AMR
      47             : 
      48             : namespace libMesh
      49             : {
      50             : 
      51             : //-----------------------------------------------------------------
      52             : // ErrorEstimator implementations
      53             : 
      54           0 : UniformRefinementEstimator::UniformRefinementEstimator() :
      55             :     ErrorEstimator(),
      56           0 :     number_h_refinements(1),
      57           0 :     number_p_refinements(0),
      58           0 :     _extra_order(1)
      59             : {
      60           0 :   error_norm = H1;
      61           0 : }
      62             : 
      63             : 
      64             : 
      65           0 : ErrorEstimatorType UniformRefinementEstimator::type() const
      66             : {
      67           0 :   return UNIFORM_REFINEMENT;
      68             : }
      69             : 
      70             : 
      71           0 : void UniformRefinementEstimator::estimate_error (const System & _system,
      72             :                                                  ErrorVector & error_per_cell,
      73             :                                                  const NumericVector<Number> * solution_vector,
      74             :                                                  bool estimate_parent_error)
      75             : {
      76           0 :   LOG_SCOPE("estimate_error()", "UniformRefinementEstimator");
      77           0 :   std::map<const System *, const NumericVector<Number> *> solution_vectors;
      78           0 :   solution_vectors[&_system] = solution_vector;
      79           0 :   this->_estimate_error (nullptr,
      80             :                          &_system,
      81             :                          &error_per_cell,
      82             :                          nullptr,
      83             :                          nullptr,
      84             :                          &solution_vectors,
      85           0 :                          estimate_parent_error);
      86           0 : }
      87             : 
      88           0 : void UniformRefinementEstimator::estimate_errors (const EquationSystems & _es,
      89             :                                                   ErrorVector & error_per_cell,
      90             :                                                   const std::map<const System *, SystemNorm> & error_norms,
      91             :                                                   const std::map<const System *, const NumericVector<Number> *> * solution_vectors,
      92             :                                                   bool estimate_parent_error)
      93             : {
      94           0 :   LOG_SCOPE("estimate_errors()", "UniformRefinementEstimator");
      95           0 :   this->_estimate_error (&_es,
      96             :                          nullptr,
      97             :                          &error_per_cell,
      98             :                          nullptr,
      99             :                          &error_norms,
     100             :                          solution_vectors,
     101           0 :                          estimate_parent_error);
     102           0 : }
     103             : 
     104           0 : void UniformRefinementEstimator::estimate_errors (const EquationSystems & _es,
     105             :                                                   ErrorMap & errors_per_cell,
     106             :                                                   const std::map<const System *, const NumericVector<Number> *> * solution_vectors,
     107             :                                                   bool estimate_parent_error)
     108             : {
     109           0 :   LOG_SCOPE("estimate_errors()", "UniformRefinementEstimator");
     110           0 :   this->_estimate_error (&_es,
     111             :                          nullptr,
     112             :                          nullptr,
     113             :                          &errors_per_cell,
     114             :                          nullptr,
     115             :                          solution_vectors,
     116           0 :                          estimate_parent_error);
     117           0 : }
     118             : 
     119           0 : void UniformRefinementEstimator::_estimate_error (const EquationSystems * _es,
     120             :                                                   const System * _system,
     121             :                                                   ErrorVector * error_per_cell,
     122             :                                                   ErrorMap * errors_per_cell,
     123             :                                                   const std::map<const System *, SystemNorm> * _error_norms,
     124             :                                                   const std::map<const System *, const NumericVector<Number> *> * solution_vectors,
     125             :                                                   bool)
     126             : {
     127             :   // Get a vector of the Systems we're going to work on,
     128             :   // and set up a error_norms map if necessary
     129           0 :   std::vector<System *> system_list;
     130           0 :   auto error_norms = std::make_unique<std::map<const System *, SystemNorm>>();
     131             : 
     132           0 :   if (_es)
     133             :     {
     134           0 :       libmesh_assert(!_system);
     135           0 :       libmesh_assert(_es->n_systems());
     136           0 :       _system = &(_es->get_system(0));
     137           0 :       libmesh_assert_equal_to (&(_system->get_equation_systems()), _es);
     138             : 
     139           0 :       libmesh_assert(_es->n_systems());
     140           0 :       for (auto i : make_range(_es->n_systems()))
     141             :         // We have to break the rules here, because we can't refine a const System
     142           0 :         system_list.push_back(const_cast<System *>(&(_es->get_system(i))));
     143             : 
     144             :       // If we're computing one vector, we need to know how to scale
     145             :       // each variable's contributions to it.
     146           0 :       if (_error_norms)
     147             :         {
     148           0 :           libmesh_assert(!errors_per_cell);
     149             :         }
     150             :       else
     151             :         // If we're computing many vectors, we just need to know which
     152             :         // variables to skip
     153             :         {
     154           0 :           libmesh_assert (errors_per_cell);
     155             : 
     156           0 :           _error_norms = error_norms.get();
     157             : 
     158           0 :           for (auto i : make_range(_es->n_systems()))
     159             :             {
     160           0 :               const System & sys = _es->get_system(i);
     161           0 :               unsigned int n_vars = sys.n_vars();
     162             : 
     163           0 :               std::vector<Real> weights(n_vars, 0.0);
     164           0 :               for (unsigned int v = 0; v != n_vars; ++v)
     165             :                 {
     166           0 :                   if (!errors_per_cell->count(std::make_pair(&sys, v)))
     167           0 :                     continue;
     168             : 
     169           0 :                   weights[v] = 1.0;
     170             :                 }
     171           0 :               (*error_norms)[&sys] =
     172           0 :                 SystemNorm(std::vector<FEMNormType>(n_vars, error_norm.type(0)),
     173           0 :                            weights);
     174             :             }
     175             :         }
     176             :     }
     177             :   else
     178             :     {
     179           0 :       libmesh_assert(_system);
     180             :       // We have to break the rules here, because we can't refine a const System
     181           0 :       system_list.push_back(const_cast<System *>(_system));
     182             : 
     183           0 :       libmesh_assert(!_error_norms);
     184           0 :       (*error_norms)[_system] = error_norm;
     185           0 :       _error_norms = error_norms.get();
     186             :     }
     187             : 
     188             :   // An EquationSystems reference will be convenient.
     189             :   // We have to break the rules here, because we can't refine a const System
     190             :   EquationSystems & es =
     191           0 :     const_cast<EquationSystems &>(_system->get_equation_systems());
     192             : 
     193             :   // The current mesh
     194           0 :   MeshBase & mesh = es.get_mesh();
     195             : 
     196             :   // The dimensionality of the mesh
     197           0 :   const unsigned int dim = mesh.mesh_dimension();
     198             : 
     199             :   // Resize the error_per_cell vectors to be
     200             :   // the number of elements, initialize them to 0.
     201           0 :   if (error_per_cell)
     202             :     {
     203           0 :       error_per_cell->clear();
     204           0 :       error_per_cell->resize (mesh.max_elem_id(), 0.);
     205             :     }
     206             :   else
     207             :     {
     208           0 :       libmesh_assert(errors_per_cell);
     209           0 :       for (const auto & pr : *errors_per_cell)
     210             :         {
     211           0 :           ErrorVector * e = pr.second.get();
     212           0 :           e->clear();
     213           0 :           e->resize(mesh.max_elem_id(), 0.);
     214             :         }
     215             :     }
     216             : 
     217             :   // We'll want to back up all coarse grid vectors
     218           0 :   std::vector<std::map<std::string, std::unique_ptr<NumericVector<Number>>>> coarse_vectors(system_list.size());
     219           0 :   std::vector<std::unique_ptr<NumericVector<Number>>> coarse_solutions(system_list.size());
     220           0 :   std::vector<std::unique_ptr<NumericVector<Number>>> coarse_local_solutions(system_list.size());
     221             :   // And make copies of projected solutions
     222           0 :   std::vector<std::unique_ptr<NumericVector<Number>>> projected_solutions(system_list.size());
     223             : 
     224             :   // And we'll need to temporarily change solution projection settings
     225           0 :   std::vector<bool> old_projection_settings(system_list.size());
     226             : 
     227             :   // And it'll be best to avoid any repartitioning
     228           0 :   std::unique_ptr<Partitioner> old_partitioner(mesh.partitioner().release());
     229             : 
     230             :   // And we can't allow any renumbering
     231           0 :   const bool old_renumbering_setting = mesh.allow_renumbering();
     232           0 :   mesh.allow_renumbering(false);
     233             : 
     234           0 :   for (auto i : index_range(system_list))
     235             :     {
     236           0 :       System & system = *system_list[i];
     237             : 
     238             :       // Check for valid error_norms
     239           0 :       libmesh_assert (_error_norms->find(&system) !=
     240             :                       _error_norms->end());
     241             : 
     242             :       // Back up the solution vector
     243           0 :       coarse_solutions[i] = system.solution->clone();
     244           0 :       coarse_local_solutions[i] = system.current_local_solution->clone();
     245             : 
     246             :       // Back up all other coarse grid vectors
     247           0 :       for (System::vectors_iterator vec = system.vectors_begin(); vec !=
     248           0 :              system.vectors_end(); ++vec)
     249             :         {
     250             :           // The (string) name of this vector
     251           0 :           const std::string & var_name = vec->first;
     252             : 
     253           0 :           coarse_vectors[i][var_name] = vec->second->clone();
     254             :         }
     255             : 
     256             :       // Use a non-standard solution vector if necessary
     257           0 :       if (solution_vectors &&
     258           0 :           solution_vectors->find(&system) != solution_vectors->end() &&
     259           0 :           solution_vectors->find(&system)->second &&
     260           0 :           solution_vectors->find(&system)->second != system.solution.get())
     261             :         {
     262             :           NumericVector<Number> * newsol =
     263             :             const_cast<NumericVector<Number> *>
     264           0 :             (solution_vectors->find(&system)->second);
     265           0 :           newsol->swap(*system.solution);
     266           0 :           system.update();
     267             :         }
     268             : 
     269             :       // Make sure the solution is projected when we refine the mesh
     270           0 :       old_projection_settings[i] = system.project_solution_on_reinit();
     271           0 :       system.project_solution_on_reinit() = true;
     272             :     }
     273             : 
     274             :   // Find the number of coarse mesh elements, to make it possible
     275             :   // to find correct coarse elem ids later
     276           0 :   const dof_id_type max_coarse_elem_id = mesh.max_elem_id();
     277             : #ifndef NDEBUG
     278             :   // n_coarse_elem is only used in an assertion later so
     279             :   // avoid declaring it unless asserts are active.
     280           0 :   const dof_id_type n_coarse_elem = mesh.n_elem();
     281             : #endif
     282             : 
     283             :   // Uniformly refine the mesh
     284           0 :   MeshRefinement mesh_refinement(mesh);
     285             : 
     286           0 :   libmesh_assert (number_h_refinements > 0 || number_p_refinements > 0);
     287             : 
     288             :   // FIXME: this may break if there is more than one System
     289             :   // on this mesh but estimate_error was still called instead of
     290             :   // estimate_errors
     291           0 :   for (unsigned int i = 0; i != number_h_refinements; ++i)
     292             :     {
     293           0 :       mesh_refinement.uniformly_refine(1);
     294           0 :       es.reinit();
     295             :     }
     296             : 
     297           0 :   for (unsigned int i = 0; i != number_p_refinements; ++i)
     298             :     {
     299           0 :       mesh_refinement.uniformly_p_refine(1);
     300           0 :       es.reinit();
     301             :     }
     302             : 
     303           0 :   for (auto i : index_range(system_list))
     304             :     {
     305           0 :       System & system = *system_list[i];
     306             : 
     307             :       // Copy the projected coarse grid solutions, which will be
     308             :       // overwritten by solve()
     309           0 :       projected_solutions[i] = NumericVector<Number>::build(system.comm());
     310           0 :       projected_solutions[i]->init(system.solution->size(),
     311           0 :                                    system.solution->local_size(),
     312           0 :                                    system.get_dof_map().get_send_list(),
     313           0 :                                    true, GHOSTED);
     314           0 :       system.solution->localize(*projected_solutions[i],
     315           0 :                                 system.get_dof_map().get_send_list());
     316             :     }
     317             : 
     318             :   // Are we doing a forward or an adjoint solve?
     319           0 :   bool solve_adjoint = false;
     320           0 :   if (solution_vectors)
     321             :     {
     322           0 :       System * sys = system_list[0];
     323           0 :       libmesh_assert (solution_vectors->find(sys) !=
     324             :                       solution_vectors->end());
     325           0 :       const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
     326           0 :       for (auto j : make_range(sys->n_qois()))
     327             :         {
     328           0 :           std::ostringstream adjoint_name;
     329           0 :           adjoint_name << "adjoint_solution" << j;
     330             : 
     331           0 :           if (vec == sys->request_vector(adjoint_name.str()))
     332             :             {
     333           0 :               solve_adjoint = true;
     334           0 :               break;
     335             :             }
     336           0 :         }
     337             :     }
     338             : 
     339             :   // Get the uniformly refined solution.
     340             : 
     341           0 :   if (_es)
     342             :     {
     343             :       // Even if we had a decent preconditioner, valid matrix etc. before
     344             :       // refinement, we don't any more.
     345           0 :       for (auto i : make_range(_es->n_systems()))
     346           0 :         es.get_system(i).disable_cache();
     347             : 
     348             :       // No specified vectors == forward solve
     349           0 :       if (!solution_vectors)
     350           0 :         es.solve();
     351             :       else
     352             :         {
     353           0 :           libmesh_assert_equal_to (solution_vectors->size(), es.n_systems());
     354           0 :           libmesh_assert (solution_vectors->find(system_list[0]) !=
     355             :                           solution_vectors->end());
     356           0 :           libmesh_assert(solve_adjoint ||
     357             :                          (solution_vectors->find(system_list[0])->second ==
     358             :                           system_list[0]->solution.get()) ||
     359             :                          !solution_vectors->find(system_list[0])->second);
     360             : 
     361             : #ifdef DEBUG
     362           0 :           for (const auto & sys : system_list)
     363             :             {
     364           0 :               libmesh_assert (solution_vectors->find(sys) !=
     365             :                               solution_vectors->end());
     366           0 :               const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
     367           0 :               if (solve_adjoint)
     368             :                 {
     369           0 :                   bool found_vec = false;
     370           0 :                   for (auto j : make_range(sys->n_qois()))
     371             :                     {
     372           0 :                       std::ostringstream adjoint_name;
     373           0 :                       adjoint_name << "adjoint_solution" << j;
     374             : 
     375           0 :                       if (vec == sys->request_vector(adjoint_name.str()))
     376             :                         {
     377           0 :                           found_vec = true;
     378           0 :                           break;
     379             :                         }
     380             :                     }
     381           0 :                   libmesh_assert(found_vec);
     382             :                 }
     383             :               else
     384           0 :                 libmesh_assert(vec == sys->solution.get() || !vec);
     385             :             }
     386             : #endif
     387             : 
     388           0 :           if (solve_adjoint)
     389             :             {
     390             :               std::vector<unsigned int> adjs(system_list.size(),
     391           0 :                                              libMesh::invalid_uint);
     392             :               // Set up proper initial guesses
     393           0 :               for (auto i : index_range(system_list))
     394             :                 {
     395           0 :                   System * sys = system_list[i];
     396           0 :                   libmesh_assert (solution_vectors->find(sys) !=
     397             :                                   solution_vectors->end());
     398           0 :                   const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
     399           0 :                   for (auto j : make_range(sys->n_qois()))
     400             :                     {
     401           0 :                       std::ostringstream adjoint_name;
     402           0 :                       adjoint_name << "adjoint_solution" << j;
     403             : 
     404           0 :                       if (vec == sys->request_vector(adjoint_name.str()))
     405             :                         {
     406           0 :                           adjs[i] = j;
     407           0 :                           break;
     408             :                         }
     409           0 :                     }
     410           0 :                   libmesh_assert_not_equal_to (adjs[i], libMesh::invalid_uint);
     411           0 :                   sys->get_adjoint_solution(adjs[i]) = *sys->solution;
     412             :                 }
     413             : 
     414           0 :               es.adjoint_solve();
     415             : 
     416             :               // Put the adjoint_solution into solution for
     417             :               // comparisons
     418           0 :               for (auto i : index_range(system_list))
     419             :                 {
     420           0 :                   system_list[i]->get_adjoint_solution(adjs[i]).swap(*system_list[i]->solution);
     421           0 :                   system_list[i]->update();
     422             :                 }
     423             :             }
     424             :           else
     425           0 :             es.solve();
     426             :         }
     427             :     }
     428             :   else
     429             :     {
     430           0 :       System * sys = system_list[0];
     431             : 
     432             :       // Even if we had a decent preconditioner, valid matrix etc. before
     433             :       // refinement, we don't any more.
     434           0 :       sys->disable_cache();
     435             : 
     436             :       // No specified vectors == forward solve
     437           0 :       if (!solution_vectors)
     438           0 :         sys->solve();
     439             :       else
     440             :         {
     441           0 :           libmesh_assert (solution_vectors->find(sys) !=
     442             :                           solution_vectors->end());
     443             : 
     444           0 :           const NumericVector<Number> * vec = solution_vectors->find(sys)->second;
     445             : 
     446           0 :           libmesh_assert(solve_adjoint ||
     447             :                          (solution_vectors->find(sys)->second ==
     448             :                           sys->solution.get()) ||
     449             :                          !solution_vectors->find(sys)->second);
     450             : 
     451           0 :           if (solve_adjoint)
     452             :             {
     453           0 :               unsigned int adj = libMesh::invalid_uint;
     454           0 :               for (unsigned int j=0, n_qois = sys->n_qois();
     455           0 :                    j != n_qois; ++j)
     456             :                 {
     457           0 :                   std::ostringstream adjoint_name;
     458           0 :                   adjoint_name << "adjoint_solution" << j;
     459             : 
     460           0 :                   if (vec == sys->request_vector(adjoint_name.str()))
     461             :                     {
     462           0 :                       adj = j;
     463           0 :                       break;
     464             :                     }
     465           0 :                 }
     466           0 :               libmesh_assert_not_equal_to (adj, libMesh::invalid_uint);
     467             : 
     468             :               // Set up proper initial guess
     469           0 :               sys->get_adjoint_solution(adj) = *sys->solution;
     470           0 :               sys->adjoint_solve();
     471             :               // Put the adjoint_solution into solution for
     472             :               // comparisons
     473           0 :               sys->get_adjoint_solution(adj).swap(*sys->solution);
     474           0 :               sys->update();
     475             :             }
     476             :           else
     477           0 :             sys->solve();
     478             :         }
     479             :     }
     480             : 
     481             :   // Get the error in the uniformly refined solution(s).
     482           0 :   for (auto sysnum : index_range(system_list))
     483             :     {
     484           0 :       System & system = *system_list[sysnum];
     485             : 
     486           0 :       unsigned int n_vars = system.n_vars();
     487             : 
     488           0 :       DofMap & dof_map = system.get_dof_map();
     489             : 
     490             :       const SystemNorm & system_i_norm =
     491           0 :         _error_norms->find(&system)->second;
     492             : 
     493           0 :       NumericVector<Number> * projected_solution = projected_solutions[sysnum].get();
     494             : 
     495             :       // Loop over all the variables in the system
     496           0 :       for (unsigned int var=0; var<n_vars; var++)
     497             :         {
     498             :           // Get the error vector to fill for this system and variable
     499           0 :           ErrorVector * err_vec = error_per_cell;
     500           0 :           if (!err_vec)
     501             :             {
     502           0 :               libmesh_assert(errors_per_cell);
     503             :               err_vec =
     504           0 :                 (*errors_per_cell)[std::make_pair(&system,var)].get();
     505             :             }
     506             : 
     507             :           // The type of finite element to use for this variable
     508           0 :           const FEType & fe_type = dof_map.variable_type (var);
     509             : 
     510             :           // Finite element object for each fine element
     511           0 :           std::unique_ptr<FEBase> fe (FEBase::build (dim, fe_type));
     512             : 
     513             :           // Build and attach an appropriate quadrature rule
     514           0 :           std::unique_ptr<QBase> qrule = fe_type.default_quadrature_rule(dim, _extra_order);
     515           0 :           fe->attach_quadrature_rule (qrule.get());
     516             : 
     517           0 :           const std::vector<Real> &  JxW = fe->get_JxW();
     518           0 :           const std::vector<std::vector<Real>> & phi = fe->get_phi();
     519             :           const std::vector<std::vector<RealGradient>> & dphi =
     520           0 :             fe->get_dphi();
     521             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     522             :           const std::vector<std::vector<RealTensor>> & d2phi =
     523           0 :             fe->get_d2phi();
     524             : #endif
     525             : 
     526             :           // The global DOF indices for the fine element
     527           0 :           std::vector<dof_id_type> dof_indices;
     528             : 
     529             :           // Iterate over all the active elements in the fine mesh
     530             :           // that live on this processor.
     531           0 :           for (const auto & elem : mesh.active_local_element_ptr_range())
     532             :             {
     533             :               // Find the element id for the corresponding coarse grid element
     534           0 :               const Elem * coarse = elem;
     535           0 :               dof_id_type e_id = coarse->id();
     536           0 :               while (e_id >= max_coarse_elem_id)
     537             :                 {
     538           0 :                   libmesh_assert (coarse->parent());
     539           0 :                   coarse = coarse->parent();
     540           0 :                   e_id = coarse->id();
     541             :                 }
     542             : 
     543           0 :               Real L2normsq = 0., H1seminormsq = 0.;
     544             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     545           0 :               Real H2seminormsq = 0.;
     546             : #endif
     547             : 
     548             :               // reinitialize the element-specific data
     549             :               // for the current element
     550           0 :               fe->reinit (elem);
     551             : 
     552             :               // Get the local to global degree of freedom maps
     553           0 :               dof_map.dof_indices (elem, dof_indices, var);
     554             : 
     555             :               // The number of quadrature points
     556           0 :               const unsigned int n_qp = qrule->n_points();
     557             : 
     558             :               // The number of shape functions
     559             :               const unsigned int n_sf =
     560           0 :                 cast_int<unsigned int>(dof_indices.size());
     561             : 
     562             :               //
     563             :               // Begin the loop over the Quadrature points.
     564             :               //
     565           0 :               for (unsigned int qp=0; qp<n_qp; qp++)
     566             :                 {
     567           0 :                   Number u_fine = 0., u_coarse = 0.;
     568             : 
     569           0 :                   Gradient grad_u_fine, grad_u_coarse;
     570             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     571           0 :                   Tensor grad2_u_fine, grad2_u_coarse;
     572             : #endif
     573             : 
     574             :                   // Compute solution values at the current
     575             :                   // quadrature point.  This requires a sum
     576             :                   // over all the shape functions evaluated
     577             :                   // at the quadrature point.
     578           0 :                   for (unsigned int i=0; i<n_sf; i++)
     579             :                     {
     580           0 :                       u_fine            += phi[i][qp]*system.current_solution (dof_indices[i]);
     581           0 :                       u_coarse          += phi[i][qp]*(*projected_solution) (dof_indices[i]);
     582           0 :                       grad_u_fine       += dphi[i][qp]*system.current_solution (dof_indices[i]);
     583           0 :                       grad_u_coarse     += dphi[i][qp]*(*projected_solution) (dof_indices[i]);
     584             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     585           0 :                       grad2_u_fine      += d2phi[i][qp]*system.current_solution (dof_indices[i]);
     586           0 :                       grad2_u_coarse    += d2phi[i][qp]*(*projected_solution) (dof_indices[i]);
     587             : #endif
     588             :                     }
     589             : 
     590             :                   // Compute the value of the error at this quadrature point
     591           0 :                   const Number val_error = u_fine - u_coarse;
     592             : 
     593             :                   // Add the squares of the error to each contribution
     594           0 :                   if (system_i_norm.type(var) == L2 ||
     595           0 :                       system_i_norm.type(var) == H1 ||
     596           0 :                       system_i_norm.type(var) == H2)
     597             :                     {
     598           0 :                       L2normsq += JxW[qp] * system_i_norm.weight_sq(var) *
     599           0 :                         TensorTools::norm_sq(val_error);
     600           0 :                       libmesh_assert_greater_equal (L2normsq, 0.);
     601             :                     }
     602             : 
     603             : 
     604             :                   // Compute the value of the error in the gradient at this
     605             :                   // quadrature point
     606           0 :                   if (system_i_norm.type(var) == H1 ||
     607           0 :                       system_i_norm.type(var) == H2 ||
     608           0 :                       system_i_norm.type(var) == H1_SEMINORM)
     609             :                     {
     610           0 :                       Gradient grad_error = grad_u_fine - grad_u_coarse;
     611             : 
     612           0 :                       H1seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
     613           0 :                         grad_error.norm_sq();
     614           0 :                       libmesh_assert_greater_equal (H1seminormsq, 0.);
     615             :                     }
     616             : 
     617             :                   // Compute the value of the error in the hessian at this
     618             :                   // quadrature point
     619           0 :                   if (system_i_norm.type(var) == H2 ||
     620           0 :                       system_i_norm.type(var) == H2_SEMINORM)
     621             :                     {
     622             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     623           0 :                       Tensor grad2_error = grad2_u_fine - grad2_u_coarse;
     624             : 
     625           0 :                       H2seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
     626           0 :                         grad2_error.norm_sq();
     627           0 :                       libmesh_assert_greater_equal (H2seminormsq, 0.);
     628             : #else
     629             :                       libmesh_error_msg
     630             :                         ("libMesh was not configured with --enable-second");
     631             : #endif
     632             :                     }
     633             :                 } // end qp loop
     634             : 
     635           0 :               if (system_i_norm.type(var) == L2 ||
     636           0 :                   system_i_norm.type(var) == H1 ||
     637           0 :                   system_i_norm.type(var) == H2)
     638           0 :                 (*err_vec)[e_id] +=
     639           0 :                   static_cast<ErrorVectorReal>(L2normsq);
     640           0 :               if (system_i_norm.type(var) == H1 ||
     641           0 :                   system_i_norm.type(var) == H2 ||
     642           0 :                   system_i_norm.type(var) == H1_SEMINORM)
     643           0 :                 (*err_vec)[e_id] +=
     644           0 :                   static_cast<ErrorVectorReal>(H1seminormsq);
     645             : 
     646             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     647           0 :               if (system_i_norm.type(var) == H2 ||
     648           0 :                   system_i_norm.type(var) == H2_SEMINORM)
     649           0 :                 (*err_vec)[e_id] +=
     650           0 :                   static_cast<ErrorVectorReal>(H2seminormsq);
     651             : #endif
     652           0 :             } // End loop over active local elements
     653           0 :         } // End loop over variables
     654             : 
     655             :       // Don't bother projecting the solution; we'll restore from backup
     656             :       // after coarsening
     657           0 :       system.project_solution_on_reinit() = false;
     658             :     }
     659             : 
     660             : 
     661             :   // Uniformly coarsen the mesh, without projecting the solution
     662           0 :   libmesh_assert (number_h_refinements > 0 || number_p_refinements > 0);
     663             : 
     664           0 :   for (unsigned int i = 0; i != number_h_refinements; ++i)
     665             :     {
     666           0 :       mesh_refinement.uniformly_coarsen(1);
     667             :       // FIXME - should the reinits here be necessary? - RHS
     668           0 :       es.reinit();
     669             :     }
     670             : 
     671           0 :   for (unsigned int i = 0; i != number_p_refinements; ++i)
     672             :     {
     673           0 :       mesh_refinement.uniformly_p_coarsen(1);
     674           0 :       es.reinit();
     675             :     }
     676             : 
     677             :   // We should be back where we started
     678           0 :   libmesh_assert_equal_to (n_coarse_elem, mesh.n_elem());
     679             : 
     680             :   // Each processor has now computed the error contributions
     681             :   // for its local elements.  We need to sum the vector
     682             :   // and then take the square-root of each component.  Note
     683             :   // that we only need to sum if we are running on multiple
     684             :   // processors, and we only need to take the square-root
     685             :   // if the value is nonzero.  There will in general be many
     686             :   // zeros for the inactive elements.
     687             : 
     688           0 :   if (error_per_cell)
     689             :     {
     690             :       // First sum the vector of estimated error values
     691           0 :       this->reduce_error(*error_per_cell, es.comm());
     692             : 
     693             :       // Compute the square-root of each component.
     694           0 :       LOG_SCOPE("std::sqrt()", "UniformRefinementEstimator");
     695           0 :       for (auto & val : *error_per_cell)
     696           0 :         if (val != 0.)
     697           0 :           val = std::sqrt(val);
     698             :     }
     699             :   else
     700             :     {
     701           0 :       for (const auto & pr : *errors_per_cell)
     702             :         {
     703           0 :           ErrorVector & e = *(pr.second);
     704             :           // First sum the vector of estimated error values
     705           0 :           this->reduce_error(e, es.comm());
     706             : 
     707             :           // Compute the square-root of each component.
     708           0 :           LOG_SCOPE("std::sqrt()", "UniformRefinementEstimator");
     709           0 :           for (auto & val : e)
     710           0 :             if (val != 0.)
     711           0 :               val = std::sqrt(val);
     712             :         }
     713             :     }
     714             : 
     715             :   // Restore old solutions and clean up the heap
     716           0 :   for (auto i : index_range(system_list))
     717             :     {
     718           0 :       System & system = *system_list[i];
     719             : 
     720           0 :       system.project_solution_on_reinit() = old_projection_settings[i];
     721             : 
     722             :       // Restore the coarse solution vectors and delete their copies
     723           0 :       *system.solution = *coarse_solutions[i];
     724           0 :       *system.current_local_solution = *coarse_local_solutions[i];
     725             : 
     726           0 :       for (System::vectors_iterator vec = system.vectors_begin(); vec !=
     727           0 :              system.vectors_end(); ++vec)
     728             :         {
     729             :           // The (string) name of this vector
     730           0 :           const std::string & var_name = vec->first;
     731             : 
     732           0 :           system.get_vector(var_name) = *coarse_vectors[i][var_name];
     733             : 
     734           0 :           coarse_vectors[i][var_name]->clear();
     735             :         }
     736             :     }
     737             : 
     738             :   // Restore old partitioner and renumbering settings
     739           0 :   mesh.partitioner().reset(old_partitioner.release());
     740           0 :   mesh.allow_renumbering(old_renumbering_setting);
     741           0 : }
     742             : 
     743             : } // namespace libMesh
     744             : 
     745             : #endif // #ifdef LIBMESH_ENABLE_AMR

Generated by: LCOV version 1.14