adjoint_residual_error_estimator.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 00019 // C++ includes 00020 #include <iostream> 00021 #include <iomanip> 00022 #include <sstream> 00023 00024 // Local Includes 00025 #include "libmesh/adjoint_residual_error_estimator.h" 00026 #include "libmesh/error_vector.h" 00027 #include "libmesh/patch_recovery_error_estimator.h" 00028 #include "libmesh/libmesh_logging.h" 00029 #include "libmesh/numeric_vector.h" 00030 #include "libmesh/system.h" 00031 #include "libmesh/system_norm.h" 00032 #include "libmesh/qoi_set.h" 00033 00034 00035 namespace libMesh 00036 { 00037 00038 //----------------------------------------------------------------- 00039 // AdjointResidualErrorEstimator implementations 00040 AdjointResidualErrorEstimator::AdjointResidualErrorEstimator () : 00041 error_plot_suffix(), 00042 _primal_error_estimator(new PatchRecoveryErrorEstimator()), 00043 _dual_error_estimator(new PatchRecoveryErrorEstimator()), 00044 _qoi_set(QoISet()) 00045 { 00046 } 00047 00048 00049 00050 void AdjointResidualErrorEstimator::estimate_error (const System& _system, 00051 ErrorVector& error_per_cell, 00052 const NumericVector<Number>* solution_vector, 00053 bool estimate_parent_error) 00054 { 00055 START_LOG("estimate_error()", "AdjointResidualErrorEstimator"); 00056 00057 // The current mesh 00058 const MeshBase& mesh = _system.get_mesh(); 00059 00060 // Resize the error_per_cell vector to be 00061 // the number of elements, initialize it to 0. 00062 error_per_cell.resize (mesh.max_elem_id()); 00063 std::fill (error_per_cell.begin(), error_per_cell.end(), 0.); 00064 00065 // Get the number of variables in the system 00066 unsigned int n_vars = _system.n_vars(); 00067 00068 // We need to make a map of the pointer to the solution vector 00069 std::map<const System*, const NumericVector<Number>*>solutionvecs; 00070 solutionvecs[&_system] = _system.solution.get(); 00071 00072 // Solve the dual problem if we have to 00073 if (!_system.is_adjoint_already_solved()) 00074 { 00075 // FIXME - we'll need to change a lot of APIs to make this trick 00076 // work with a const System... 00077 System& system = const_cast<System&>(_system); 00078 system.adjoint_solve(_qoi_set); 00079 } 00080 00081 // Flag to check whether we have not been asked to weight the variable error contributions in any specific manner 00082 bool error_norm_is_identity = error_norm.is_identity(); 00083 00084 // Create an ErrorMap/ErrorVector to store the primal, dual and total_dual variable errors 00085 ErrorMap primal_errors_per_cell; 00086 ErrorMap dual_errors_per_cell; 00087 ErrorMap total_dual_errors_per_cell; 00088 // Allocate ErrorVectors to this map if we're going to use it 00089 if (!error_norm_is_identity) 00090 for(unsigned int v = 0; v < n_vars; v++) 00091 { 00092 primal_errors_per_cell[std::make_pair(&_system, v)] = new ErrorVector; 00093 dual_errors_per_cell[std::make_pair(&_system, v)] = new ErrorVector; 00094 total_dual_errors_per_cell[std::make_pair(&_system, v)] = new ErrorVector; 00095 } 00096 ErrorVector primal_error_per_cell; 00097 ErrorVector dual_error_per_cell; 00098 ErrorVector total_dual_error_per_cell; 00099 00100 // Have we been asked to weight the variable error contributions in any specific manner 00101 if(!error_norm_is_identity) // If we do 00102 { 00103 // Estimate the primal problem error for each variable 00104 _primal_error_estimator->estimate_errors 00105 (_system.get_equation_systems(), primal_errors_per_cell, &solutionvecs, estimate_parent_error); 00106 } 00107 else // If not 00108 { 00109 // Just get the combined error estimate 00110 _primal_error_estimator->estimate_error 00111 (_system, primal_error_per_cell, solution_vector, estimate_parent_error); 00112 } 00113 00114 // Sum and weight the dual error estimate based on our QoISet 00115 for (unsigned int i = 0; i != _system.qoi.size(); ++i) 00116 { 00117 if (_qoi_set.has_index(i)) 00118 { 00119 // Get the weight for the current QoI 00120 Real error_weight = _qoi_set.weight(i); 00121 00122 // We need to make a map of the pointer to the adjoint solution vector 00123 std::map<const System*, const NumericVector<Number>*>adjointsolutionvecs; 00124 adjointsolutionvecs[&_system] = &_system.get_adjoint_solution(i); 00125 00126 // Have we been asked to weight the variable error contributions in any specific manner 00127 if(!error_norm_is_identity) // If we have 00128 { 00129 _dual_error_estimator->estimate_errors 00130 (_system.get_equation_systems(), dual_errors_per_cell, &adjointsolutionvecs, 00131 estimate_parent_error); 00132 } 00133 else // If not 00134 { 00135 // Just get the combined error estimate 00136 _dual_error_estimator->estimate_error 00137 (_system, dual_error_per_cell, &(_system.get_adjoint_solution(i)), estimate_parent_error); 00138 } 00139 00140 std::size_t error_size; 00141 00142 // Get the size of the first ErrorMap vector; this will give us the number of elements 00143 if(!error_norm_is_identity) // If in non default weights case 00144 { 00145 error_size = dual_errors_per_cell[std::make_pair(&_system, 0)]->size(); 00146 } 00147 else // If in the standard default weights case 00148 { 00149 error_size = dual_error_per_cell.size(); 00150 } 00151 00152 // Resize the ErrorVector(s) 00153 if(!error_norm_is_identity) 00154 { 00155 // Loop over variables 00156 for(unsigned int v = 0; v < n_vars; v++) 00157 { 00158 libmesh_assert(!total_dual_errors_per_cell[std::make_pair(&_system, v)]->size() || 00159 total_dual_errors_per_cell[std::make_pair(&_system, v)]->size() == error_size) ; 00160 total_dual_errors_per_cell[std::make_pair(&_system, v)]->resize(error_size); 00161 } 00162 } 00163 else 00164 { 00165 libmesh_assert(!total_dual_error_per_cell.size() || 00166 total_dual_error_per_cell.size() == error_size); 00167 total_dual_error_per_cell.resize(error_size); 00168 } 00169 00170 for (std::size_t e = 0; e != error_size; ++e) 00171 { 00172 // Have we been asked to weight the variable error contributions in any specific manner 00173 if(!error_norm_is_identity) // If we have 00174 { 00175 // Loop over variables 00176 for(unsigned int v = 0; v < n_vars; v++) 00177 { 00178 // Now fill in total_dual_error ErrorMap with the weight 00179 (*total_dual_errors_per_cell[std::make_pair(&_system, v)])[e] += 00180 static_cast<ErrorVectorReal> 00181 (error_weight * 00182 (*dual_errors_per_cell[std::make_pair(&_system, v)])[e]); 00183 } 00184 } 00185 else // If not 00186 { 00187 total_dual_error_per_cell[e] += 00188 static_cast<ErrorVectorReal>(error_weight * dual_error_per_cell[e]); 00189 } 00190 } 00191 } 00192 } 00193 00194 // Do some debugging plots if requested 00195 if (!error_plot_suffix.empty()) 00196 { 00197 if(!error_norm_is_identity) // If we have 00198 { 00199 // Loop over variables 00200 for(unsigned int v = 0; v < n_vars; v++) 00201 { 00202 std::ostringstream primal_out; 00203 std::ostringstream dual_out; 00204 primal_out << "primal_" << error_plot_suffix << "."; 00205 dual_out << "dual_" << error_plot_suffix << "."; 00206 00207 primal_out << std::setw(1) 00208 << std::setprecision(0) 00209 << std::setfill('0') 00210 << std::right 00211 << v; 00212 00213 dual_out << std::setw(1) 00214 << std::setprecision(0) 00215 << std::setfill('0') 00216 << std::right 00217 << v; 00218 00219 (*primal_errors_per_cell[std::make_pair(&_system, v)]).plot_error(primal_out.str(), _system.get_mesh()); 00220 (*total_dual_errors_per_cell[std::make_pair(&_system, v)]).plot_error(dual_out.str(), _system.get_mesh()); 00221 00222 primal_out.clear(); 00223 dual_out.clear(); 00224 } 00225 } 00226 else // If not 00227 { 00228 std::ostringstream primal_out; 00229 std::ostringstream dual_out; 00230 primal_out << "primal_" << error_plot_suffix ; 00231 dual_out << "dual_" << error_plot_suffix ; 00232 00233 primal_error_per_cell.plot_error(primal_out.str(), _system.get_mesh()); 00234 total_dual_error_per_cell.plot_error(dual_out.str(), _system.get_mesh()); 00235 00236 primal_out.clear(); 00237 dual_out.clear(); 00238 } 00239 } 00240 00241 // Weight the primal error by the dual error using the system norm object 00242 // FIXME: we ought to thread this 00243 for (unsigned int i=0; i != error_per_cell.size(); ++i) 00244 { 00245 // Have we been asked to weight the variable error contributions in any specific manner 00246 if(!error_norm_is_identity) // If we do 00247 { 00248 // Create Error Vectors to pass to calculate_norm 00249 std::vector<Real> cell_primal_error; 00250 std::vector<Real> cell_dual_error; 00251 00252 for(unsigned int v = 0; v < n_vars; v++) 00253 { 00254 cell_primal_error.push_back((*primal_errors_per_cell[std::make_pair(&_system, v)])[i]); 00255 cell_dual_error.push_back((*total_dual_errors_per_cell[std::make_pair(&_system, v)])[i]); 00256 } 00257 00258 error_per_cell[i] = 00259 static_cast<ErrorVectorReal> 00260 (error_norm.calculate_norm(cell_primal_error, cell_dual_error)); 00261 } 00262 else // If not 00263 { 00264 error_per_cell[i] = primal_error_per_cell[i]*total_dual_error_per_cell[i]; 00265 } 00266 } 00267 00268 // Deallocate the ErrorMap contents if we allocated them earlier 00269 if (!error_norm_is_identity) 00270 for(unsigned int v = 0; v < n_vars; v++) 00271 { 00272 delete primal_errors_per_cell[std::make_pair(&_system, v)]; 00273 delete dual_errors_per_cell[std::make_pair(&_system, v)]; 00274 delete total_dual_errors_per_cell[std::make_pair(&_system, v)]; 00275 } 00276 00277 STOP_LOG("estimate_error()", "AdjointResidualErrorEstimator"); 00278 } 00279 00280 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:45 UTC
Hosted By: