$extrastylesheet
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