$extrastylesheet
uniform_refinement_estimator.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 // C++ includes
00019 #include <algorithm> // for std::fill
00020 #include <sstream>
00021 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00022 #include <cmath>    // for sqrt
00023 
00024 
00025 // Local Includes
00026 #include "libmesh/dof_map.h"
00027 #include "libmesh/elem.h"
00028 #include "libmesh/equation_systems.h"
00029 #include "libmesh/error_vector.h"
00030 #include "libmesh/fe.h"
00031 #include "libmesh/libmesh_common.h"
00032 #include "libmesh/libmesh_logging.h"
00033 #include "libmesh/mesh_base.h"
00034 #include "libmesh/mesh_refinement.h"
00035 #include "libmesh/numeric_vector.h"
00036 #include "libmesh/quadrature.h"
00037 #include "libmesh/system.h"
00038 #include "libmesh/uniform_refinement_estimator.h"
00039 #include "libmesh/partitioner.h"
00040 #include "libmesh/tensor_tools.h"
00041 
00042 #ifdef LIBMESH_ENABLE_AMR
00043 
00044 namespace libMesh
00045 {
00046 
00047 //-----------------------------------------------------------------
00048 // ErrorEstimator implementations
00049 void UniformRefinementEstimator::estimate_error (const System& _system,
00050                                                  ErrorVector& error_per_cell,
00051                                                  const NumericVector<Number>* solution_vector,
00052                                                  bool estimate_parent_error)
00053 {
00054   START_LOG("estimate_error()", "UniformRefinementEstimator");
00055   std::map<const System*, const NumericVector<Number>* > solution_vectors;
00056   solution_vectors[&_system] = solution_vector;
00057   this->_estimate_error (NULL, &_system, &error_per_cell, NULL, NULL,
00058                          &solution_vectors, estimate_parent_error);
00059   STOP_LOG("estimate_error()", "UniformRefinementEstimator");
00060 }
00061 
00062 void UniformRefinementEstimator::estimate_errors (const EquationSystems& _es,
00063                                                   ErrorVector& error_per_cell,
00064                                                   const std::map<const System*, SystemNorm>& error_norms,
00065                                                   const std::map<const System*, const NumericVector<Number>* >* solution_vectors,
00066                                                   bool estimate_parent_error)
00067 {
00068   START_LOG("estimate_errors()", "UniformRefinementEstimator");
00069   this->_estimate_error (&_es, NULL, &error_per_cell, NULL,
00070                          &error_norms, solution_vectors,
00071                          estimate_parent_error);
00072   STOP_LOG("estimate_errors()", "UniformRefinementEstimator");
00073 }
00074 
00075 void UniformRefinementEstimator::estimate_errors (const EquationSystems& _es,
00076                                                   ErrorMap& errors_per_cell,
00077                                                   const std::map<const System*, const NumericVector<Number>* >* solution_vectors,
00078                                                   bool estimate_parent_error)
00079 {
00080   START_LOG("estimate_errors()", "UniformRefinementEstimator");
00081   this->_estimate_error (&_es, NULL, NULL, &errors_per_cell, NULL,
00082                          solution_vectors, estimate_parent_error);
00083   STOP_LOG("estimate_errors()", "UniformRefinementEstimator");
00084 }
00085 
00086 void UniformRefinementEstimator::_estimate_error (const EquationSystems* _es,
00087                                                   const System* _system,
00088                                                   ErrorVector* error_per_cell,
00089                                                   ErrorMap* errors_per_cell,
00090                                                   const std::map<const System*, SystemNorm > *_error_norms,
00091                                                   const std::map<const System*, const NumericVector<Number>* >* solution_vectors,
00092                                                   bool)
00093 {
00094   // Get a vector of the Systems we're going to work on,
00095   // and set up a error_norms map if necessary
00096   std::vector<System *> system_list;
00097   UniquePtr<std::map<const System*, SystemNorm > > error_norms =
00098     UniquePtr<std::map<const System*, SystemNorm > >
00099     (new std::map<const System*, SystemNorm>);
00100 
00101   if (_es)
00102     {
00103       libmesh_assert(!_system);
00104       libmesh_assert(_es->n_systems());
00105       _system = &(_es->get_system(0));
00106       libmesh_assert_equal_to (&(_system->get_equation_systems()), _es);
00107 
00108       libmesh_assert(_es->n_systems());
00109       for (unsigned int i=0; i != _es->n_systems(); ++i)
00110         // We have to break the rules here, because we can't refine a const System
00111         system_list.push_back(const_cast<System *>(&(_es->get_system(i))));
00112 
00113       // If we're computing one vector, we need to know how to scale
00114       // each variable's contributions to it.
00115       if (_error_norms)
00116         {
00117           libmesh_assert(!errors_per_cell);
00118         }
00119       else
00120         // If we're computing many vectors, we just need to know which
00121         // variables to skip
00122         {
00123           libmesh_assert (errors_per_cell);
00124 
00125           _error_norms = error_norms.get();
00126 
00127           for (unsigned int i=0; i!= _es->n_systems(); ++i)
00128             {
00129               const System &sys = _es->get_system(i);
00130               unsigned int n_vars = sys.n_vars();
00131 
00132               std::vector<Real> weights(n_vars, 0.0);
00133               for (unsigned int v = 0; v != n_vars; ++v)
00134                 {
00135                   if (errors_per_cell->find(std::make_pair(&sys, v)) ==
00136                       errors_per_cell->end())
00137                     continue;
00138 
00139                   weights[v] = 1.0;
00140                 }
00141               (*error_norms)[&sys] =
00142                 SystemNorm(std::vector<FEMNormType>(n_vars, error_norm.type(0)),
00143                            weights);
00144             }
00145         }
00146     }
00147   else
00148     {
00149       libmesh_assert(_system);
00150       // We have to break the rules here, because we can't refine a const System
00151       system_list.push_back(const_cast<System *>(_system));
00152 
00153       libmesh_assert(!_error_norms);
00154       (*error_norms)[_system] = error_norm;
00155       _error_norms = error_norms.get();
00156     }
00157 
00158   // An EquationSystems reference will be convenient.
00159   // We have to break the rules here, because we can't refine a const System
00160   EquationSystems& es =
00161     const_cast<EquationSystems &>(_system->get_equation_systems());
00162 
00163   // The current mesh
00164   MeshBase& mesh = es.get_mesh();
00165 
00166   // The dimensionality of the mesh
00167   const unsigned int dim = mesh.mesh_dimension();
00168 
00169   // Resize the error_per_cell vectors to be
00170   // the number of elements, initialize them to 0.
00171   if (error_per_cell)
00172     {
00173       error_per_cell->clear();
00174       error_per_cell->resize (mesh.max_elem_id(), 0.);
00175     }
00176   else
00177     {
00178       libmesh_assert(errors_per_cell);
00179       for (ErrorMap::iterator i = errors_per_cell->begin();
00180            i != errors_per_cell->end(); ++i)
00181         {
00182           ErrorVector *e = i->second;
00183           e->clear();
00184           e->resize(mesh.max_elem_id(), 0.);
00185         }
00186     }
00187 
00188   // We'll want to back up all coarse grid vectors
00189   std::vector<std::map<std::string, NumericVector<Number> *> >
00190     coarse_vectors(system_list.size());
00191   std::vector<NumericVector<Number> *>
00192     coarse_solutions(system_list.size());
00193   std::vector<NumericVector<Number> *>
00194     coarse_local_solutions(system_list.size());
00195   // And make copies of projected solutions
00196   std::vector<NumericVector<Number> *>
00197     projected_solutions(system_list.size());
00198 
00199   // And we'll need to temporarily change solution projection settings
00200   std::vector<bool> old_projection_settings(system_list.size());
00201 
00202   // And it'll be best to avoid any repartitioning
00203   UniquePtr<Partitioner> old_partitioner(mesh.partitioner().release());
00204 
00205   for (unsigned int i=0; i != system_list.size(); ++i)
00206     {
00207       System &system = *system_list[i];
00208 
00209       // Check for valid error_norms
00210       libmesh_assert (_error_norms->find(&system) !=
00211                       _error_norms->end());
00212 
00213       // Back up the solution vector
00214       coarse_solutions[i] = system.solution->clone().release();
00215       coarse_local_solutions[i] =
00216         system.current_local_solution->clone().release();
00217 
00218       // Back up all other coarse grid vectors
00219       for (System::vectors_iterator vec = system.vectors_begin(); vec !=
00220              system.vectors_end(); ++vec)
00221         {
00222           // The (string) name of this vector
00223           const std::string& var_name = vec->first;
00224 
00225           coarse_vectors[i][var_name] = vec->second->clone().release();
00226         }
00227 
00228       // Use a non-standard solution vector if necessary
00229       if (solution_vectors &&
00230           solution_vectors->find(&system) != solution_vectors->end() &&
00231           solution_vectors->find(&system)->second &&
00232           solution_vectors->find(&system)->second != system.solution.get())
00233         {
00234           NumericVector<Number>* newsol =
00235             const_cast<NumericVector<Number>*>
00236             (solution_vectors->find(&system)->second);
00237           newsol->swap(*system.solution);
00238           system.update();
00239         }
00240 
00241       // Make sure the solution is projected when we refine the mesh
00242       old_projection_settings[i] = system.project_solution_on_reinit();
00243       system.project_solution_on_reinit() = true;
00244     }
00245 
00246   // Find the number of coarse mesh elements, to make it possible
00247   // to find correct coarse elem ids later
00248   const dof_id_type max_coarse_elem_id = mesh.max_elem_id();
00249 #ifndef NDEBUG
00250   // n_coarse_elem is only used in an assertion later so
00251   // avoid declaring it unless asserts are active.
00252   const dof_id_type n_coarse_elem = mesh.n_elem();
00253 #endif
00254 
00255   // Uniformly refine the mesh
00256   MeshRefinement mesh_refinement(mesh);
00257 
00258   libmesh_assert (number_h_refinements > 0 || number_p_refinements > 0);
00259 
00260   // FIXME: this may break if there is more than one System
00261   // on this mesh but estimate_error was still called instead of
00262   // estimate_errors
00263   for (unsigned int i = 0; i != number_h_refinements; ++i)
00264     {
00265       mesh_refinement.uniformly_refine(1);
00266       es.reinit();
00267     }
00268 
00269   for (unsigned int i = 0; i != number_p_refinements; ++i)
00270     {
00271       mesh_refinement.uniformly_p_refine(1);
00272       es.reinit();
00273     }
00274 
00275   for (unsigned int i=0; i != system_list.size(); ++i)
00276     {
00277       System &system = *system_list[i];
00278 
00279       // Copy the projected coarse grid solutions, which will be
00280       // overwritten by solve()
00281       //      projected_solutions[i] = system.solution->clone().release();
00282       projected_solutions[i] = NumericVector<Number>::build(system.comm()).release();
00283       projected_solutions[i]->init(system.solution->size(), true, SERIAL);
00284       system.solution->localize(*projected_solutions[i],
00285                                 system.get_dof_map().get_send_list());
00286     }
00287 
00288   // Are we doing a forward or an adjoint solve?
00289   bool solve_adjoint = false;
00290   if (solution_vectors)
00291     {
00292       System *sys = system_list[0];
00293       libmesh_assert (solution_vectors->find(sys) !=
00294                       solution_vectors->end());
00295       const NumericVector<Number> *vec = solution_vectors->find(sys)->second;
00296       for (unsigned int j=0; j != sys->qoi.size(); ++j)
00297         {
00298           std::ostringstream adjoint_name;
00299           adjoint_name << "adjoint_solution" << j;
00300 
00301           if (vec == sys->request_vector(adjoint_name.str()))
00302             {
00303               solve_adjoint = true;
00304               break;
00305             }
00306         }
00307     }
00308 
00309   // Get the uniformly refined solution.
00310 
00311   if (_es)
00312     {
00313       // Even if we had a decent preconditioner, valid matrix etc. before
00314       // refinement, we don't any more.
00315       for (unsigned int i=0; i != es.n_systems(); ++i)
00316         es.get_system(i).disable_cache();
00317 
00318       // No specified vectors == forward solve
00319       if (!solution_vectors)
00320         es.solve();
00321       else
00322         {
00323           libmesh_assert_equal_to (solution_vectors->size(), es.n_systems());
00324           libmesh_assert (solution_vectors->find(system_list[0]) !=
00325                           solution_vectors->end());
00326           libmesh_assert(solve_adjoint ||
00327                          (solution_vectors->find(system_list[0])->second ==
00328                           system_list[0]->solution.get()) ||
00329                          !solution_vectors->find(system_list[0])->second);
00330 
00331 #ifdef DEBUG
00332           for (unsigned int i=0; i != system_list.size(); ++i)
00333             {
00334               System *sys = system_list[i];
00335               libmesh_assert (solution_vectors->find(sys) !=
00336                               solution_vectors->end());
00337               const NumericVector<Number> *vec = solution_vectors->find(sys)->second;
00338               if (solve_adjoint)
00339                 {
00340                   bool found_vec = false;
00341                   for (unsigned int j=0; j != sys->qoi.size(); ++j)
00342                     {
00343                       std::ostringstream adjoint_name;
00344                       adjoint_name << "adjoint_solution" << j;
00345 
00346                       if (vec == sys->request_vector(adjoint_name.str()))
00347                         {
00348                           found_vec = true;
00349                           break;
00350                         }
00351                     }
00352                   libmesh_assert(found_vec);
00353                 }
00354               else
00355                 libmesh_assert(vec == sys->solution.get() || !vec);
00356             }
00357 #endif
00358 
00359           if (solve_adjoint)
00360             {
00361               std::vector<unsigned int> adjs(system_list.size(),
00362                                              libMesh::invalid_uint);
00363               // Set up proper initial guesses
00364               for (unsigned int i=0; i != system_list.size(); ++i)
00365                 {
00366                   System *sys = system_list[i];
00367                   libmesh_assert (solution_vectors->find(sys) !=
00368                                   solution_vectors->end());
00369                   const NumericVector<Number> *vec = solution_vectors->find(sys)->second;
00370                   for (unsigned int j=0; j != sys->qoi.size(); ++j)
00371                     {
00372                       std::ostringstream adjoint_name;
00373                       adjoint_name << "adjoint_solution" << j;
00374 
00375                       if (vec == sys->request_vector(adjoint_name.str()))
00376                         {
00377                           adjs[i] = j;
00378                           break;
00379                         }
00380                     }
00381                   libmesh_assert_not_equal_to (adjs[i], libMesh::invalid_uint);
00382                   system_list[i]->get_adjoint_solution(adjs[i]) =
00383                     *system_list[i]->solution;
00384                 }
00385 
00386               es.adjoint_solve();
00387 
00388               // Put the adjoint_solution into solution for
00389               // comparisons
00390               for (unsigned int i=0; i != system_list.size(); ++i)
00391                 {
00392                   system_list[i]->get_adjoint_solution(adjs[i]).swap(*system_list[i]->solution);
00393                   system_list[i]->update();
00394                 }
00395             }
00396           else
00397             es.solve();
00398         }
00399     }
00400   else
00401     {
00402       System *sys = system_list[0];
00403 
00404       // Even if we had a decent preconditioner, valid matrix etc. before
00405       // refinement, we don't any more.
00406       sys->disable_cache();
00407 
00408       // No specified vectors == forward solve
00409       if (!solution_vectors)
00410         sys->solve();
00411       else
00412         {
00413           libmesh_assert (solution_vectors->find(sys) !=
00414                           solution_vectors->end());
00415 
00416           const NumericVector<Number> *vec = solution_vectors->find(sys)->second;
00417 
00418           libmesh_assert(solve_adjoint ||
00419                          (solution_vectors->find(sys)->second ==
00420                           sys->solution.get()) ||
00421                          !solution_vectors->find(sys)->second);
00422 
00423           if (solve_adjoint)
00424             {
00425               unsigned int adj = libMesh::invalid_uint;
00426               for (unsigned int j=0; j != sys->qoi.size(); ++j)
00427                 {
00428                   std::ostringstream adjoint_name;
00429                   adjoint_name << "adjoint_solution" << j;
00430 
00431                   if (vec == sys->request_vector(adjoint_name.str()))
00432                     {
00433                       adj = j;
00434                       break;
00435                     }
00436                 }
00437               libmesh_assert_not_equal_to (adj, libMesh::invalid_uint);
00438 
00439               // Set up proper initial guess
00440               sys->get_adjoint_solution(adj) = *sys->solution;
00441               sys->adjoint_solve();
00442               // Put the adjoint_solution into solution for
00443               // comparisons
00444               sys->get_adjoint_solution(adj).swap(*sys->solution);
00445               sys->update();
00446             }
00447           else
00448             sys->solve();
00449         }
00450     }
00451 
00452   // Get the error in the uniformly refined solution(s).
00453 
00454   for (unsigned int sysnum=0; sysnum != system_list.size(); ++sysnum)
00455     {
00456       System &system = *system_list[sysnum];
00457 
00458       unsigned int n_vars = system.n_vars();
00459 
00460       DofMap &dof_map = system.get_dof_map();
00461 
00462       const SystemNorm &system_i_norm =
00463         _error_norms->find(&system)->second;
00464 
00465       NumericVector<Number> *projected_solution = projected_solutions[sysnum];
00466 
00467       // Loop over all the variables in the system
00468       for (unsigned int var=0; var<n_vars; var++)
00469         {
00470           // Get the error vector to fill for this system and variable
00471           ErrorVector *err_vec = error_per_cell;
00472           if (!err_vec)
00473             {
00474               libmesh_assert(errors_per_cell);
00475               err_vec =
00476                 (*errors_per_cell)[std::make_pair(&system,var)];
00477             }
00478 
00479           // The type of finite element to use for this variable
00480           const FEType& fe_type = dof_map.variable_type (var);
00481 
00482           // Finite element object for each fine element
00483           UniquePtr<FEBase> fe (FEBase::build (dim, fe_type));
00484 
00485           // Build and attach an appropriate quadrature rule
00486           UniquePtr<QBase> qrule = fe_type.default_quadrature_rule(dim);
00487           fe->attach_quadrature_rule (qrule.get());
00488 
00489           const std::vector<Real>&  JxW = fe->get_JxW();
00490           const std::vector<std::vector<Real> >& phi = fe->get_phi();
00491           const std::vector<std::vector<RealGradient> >& dphi =
00492             fe->get_dphi();
00493 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00494           const std::vector<std::vector<RealTensor> >& d2phi =
00495             fe->get_d2phi();
00496 #endif
00497 
00498           // The global DOF indices for the fine element
00499           std::vector<dof_id_type> dof_indices;
00500 
00501           // Iterate over all the active elements in the fine mesh
00502           // that live on this processor.
00503           MeshBase::const_element_iterator       elem_it  = mesh.active_local_elements_begin();
00504           const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end();
00505 
00506           for (; elem_it != elem_end; ++elem_it)
00507             {
00508               // e is necessarily an active element on the local processor
00509               const Elem* elem = *elem_it;
00510 
00511               // Find the element id for the corresponding coarse grid element
00512               const Elem* coarse = elem;
00513               dof_id_type e_id = coarse->id();
00514               while (e_id >= max_coarse_elem_id)
00515                 {
00516                   libmesh_assert (coarse->parent());
00517                   coarse = coarse->parent();
00518                   e_id = coarse->id();
00519                 }
00520 
00521               Real L2normsq = 0., H1seminormsq = 0.;
00522 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00523               Real H2seminormsq = 0.;
00524 #endif
00525 
00526               // reinitialize the element-specific data
00527               // for the current element
00528               fe->reinit (elem);
00529 
00530               // Get the local to global degree of freedom maps
00531               dof_map.dof_indices (elem, dof_indices, var);
00532 
00533               // The number of quadrature points
00534               const unsigned int n_qp = qrule->n_points();
00535 
00536               // The number of shape functions
00537               const unsigned int n_sf =
00538                 cast_int<unsigned int>(dof_indices.size());
00539 
00540               //
00541               // Begin the loop over the Quadrature points.
00542               //
00543               for (unsigned int qp=0; qp<n_qp; qp++)
00544                 {
00545                   Number u_fine = 0., u_coarse = 0.;
00546 
00547                   Gradient grad_u_fine, grad_u_coarse;
00548 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00549                   Tensor grad2_u_fine, grad2_u_coarse;
00550 #endif
00551 
00552                   // Compute solution values at the current
00553                   // quadrature point.  This reqiures a sum
00554                   // over all the shape functions evaluated
00555                   // at the quadrature point.
00556                   for (unsigned int i=0; i<n_sf; i++)
00557                     {
00558                       u_fine            += phi[i][qp]*system.current_solution (dof_indices[i]);
00559                       u_coarse          += phi[i][qp]*(*projected_solution) (dof_indices[i]);
00560                       grad_u_fine       += dphi[i][qp]*system.current_solution (dof_indices[i]);
00561                       grad_u_coarse     += dphi[i][qp]*(*projected_solution) (dof_indices[i]);
00562 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00563                       grad2_u_fine      += d2phi[i][qp]*system.current_solution (dof_indices[i]);
00564                       grad2_u_coarse    += d2phi[i][qp]*(*projected_solution) (dof_indices[i]);
00565 #endif
00566                     }
00567 
00568                   // Compute the value of the error at this quadrature point
00569                   const Number val_error = u_fine - u_coarse;
00570 
00571                   // Add the squares of the error to each contribution
00572                   if (system_i_norm.type(var) == L2 ||
00573                       system_i_norm.type(var) == H1 ||
00574                       system_i_norm.type(var) == H2)
00575                     {
00576                       L2normsq += JxW[qp] * system_i_norm.weight_sq(var) *
00577                         TensorTools::norm_sq(val_error);
00578                       libmesh_assert_greater_equal (L2normsq, 0.);
00579                     }
00580 
00581 
00582                   // Compute the value of the error in the gradient at this
00583                   // quadrature point
00584                   if (system_i_norm.type(var) == H1 ||
00585                       system_i_norm.type(var) == H2 ||
00586                       system_i_norm.type(var) == H1_SEMINORM)
00587                     {
00588                       Gradient grad_error = grad_u_fine - grad_u_coarse;
00589 
00590                       H1seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
00591                         grad_error.size_sq();
00592                       libmesh_assert_greater_equal (H1seminormsq, 0.);
00593                     }
00594 
00595 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00596                   // Compute the value of the error in the hessian at this
00597                   // quadrature point
00598                   if (system_i_norm.type(var) == H2 ||
00599                       system_i_norm.type(var) == H2_SEMINORM)
00600                     {
00601                       Tensor grad2_error = grad2_u_fine - grad2_u_coarse;
00602 
00603                       H2seminormsq += JxW[qp] * system_i_norm.weight_sq(var) *
00604                         grad2_error.size_sq();
00605                       libmesh_assert_greater_equal (H2seminormsq, 0.);
00606                     }
00607 #endif
00608                 } // end qp loop
00609 
00610               if (system_i_norm.type(var) == L2 ||
00611                   system_i_norm.type(var) == H1 ||
00612                   system_i_norm.type(var) == H2)
00613                 (*err_vec)[e_id] +=
00614                   static_cast<ErrorVectorReal>(L2normsq);
00615               if (system_i_norm.type(var) == H1 ||
00616                   system_i_norm.type(var) == H2 ||
00617                   system_i_norm.type(var) == H1_SEMINORM)
00618                 (*err_vec)[e_id] +=
00619                   static_cast<ErrorVectorReal>(H1seminormsq);
00620 
00621               if (system_i_norm.type(var) == H2 ||
00622                   system_i_norm.type(var) == H2_SEMINORM)
00623                 (*err_vec)[e_id] +=
00624                   static_cast<ErrorVectorReal>(H2seminormsq);
00625             } // End loop over active local elements
00626         } // End loop over variables
00627 
00628       // Don't bother projecting the solution; we'll restore from backup
00629       // after coarsening
00630       system.project_solution_on_reinit() = false;
00631     }
00632 
00633 
00634   // Uniformly coarsen the mesh, without projecting the solution
00635   libmesh_assert (number_h_refinements > 0 || number_p_refinements > 0);
00636 
00637   for (unsigned int i = 0; i != number_h_refinements; ++i)
00638     {
00639       mesh_refinement.uniformly_coarsen(1);
00640       // FIXME - should the reinits here be necessary? - RHS
00641       es.reinit();
00642     }
00643 
00644   for (unsigned int i = 0; i != number_p_refinements; ++i)
00645     {
00646       mesh_refinement.uniformly_p_coarsen(1);
00647       es.reinit();
00648     }
00649 
00650   // We should be back where we started
00651   libmesh_assert_equal_to (n_coarse_elem, mesh.n_elem());
00652 
00653   // Each processor has now computed the error contribuions
00654   // for its local elements.  We need to sum the vector
00655   // and then take the square-root of each component.  Note
00656   // that we only need to sum if we are running on multiple
00657   // processors, and we only need to take the square-root
00658   // if the value is nonzero.  There will in general be many
00659   // zeros for the inactive elements.
00660 
00661   if (error_per_cell)
00662     {
00663       // First sum the vector of estimated error values
00664       this->reduce_error(*error_per_cell, es.comm());
00665 
00666       // Compute the square-root of each component.
00667       START_LOG("std::sqrt()", "UniformRefinementEstimator");
00668       for (unsigned int i=0; i<error_per_cell->size(); i++)
00669         if ((*error_per_cell)[i] != 0.)
00670           (*error_per_cell)[i] = std::sqrt((*error_per_cell)[i]);
00671       STOP_LOG("std::sqrt()", "UniformRefinementEstimator");
00672     }
00673   else
00674     {
00675       for (ErrorMap::iterator it = errors_per_cell->begin();
00676            it != errors_per_cell->end(); ++it)
00677         {
00678           ErrorVector *e = it->second;
00679           // First sum the vector of estimated error values
00680           this->reduce_error(*e, es.comm());
00681 
00682           // Compute the square-root of each component.
00683           START_LOG("std::sqrt()", "UniformRefinementEstimator");
00684           for (unsigned int i=0; i<e->size(); i++)
00685             if ((*e)[i] != 0.)
00686               (*e)[i] = std::sqrt((*e)[i]);
00687           STOP_LOG("std::sqrt()", "UniformRefinementEstimator");
00688         }
00689     }
00690 
00691   // Restore old solutions and clean up the heap
00692   for (unsigned int i=0; i != system_list.size(); ++i)
00693     {
00694       System &system = *system_list[i];
00695 
00696       system.project_solution_on_reinit() = old_projection_settings[i];
00697 
00698       // Restore the coarse solution vectors and delete their copies
00699       *system.solution = *coarse_solutions[i];
00700       delete coarse_solutions[i];
00701       *system.current_local_solution = *coarse_local_solutions[i];
00702       delete coarse_local_solutions[i];
00703       delete projected_solutions[i];
00704 
00705       for (System::vectors_iterator vec = system.vectors_begin(); vec !=
00706              system.vectors_end(); ++vec)
00707         {
00708           // The (string) name of this vector
00709           const std::string& var_name = vec->first;
00710 
00711           system.get_vector(var_name) = *coarse_vectors[i][var_name];
00712 
00713           coarse_vectors[i][var_name]->clear();
00714           delete coarse_vectors[i][var_name];
00715         }
00716     }
00717 
00718   // Restore old partitioner settings
00719   mesh.partitioner().reset(old_partitioner.release());
00720 }
00721 
00722 } // namespace libMesh
00723 
00724 #endif // #ifdef LIBMESH_ENABLE_AMR