$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 00019 00020 // Local includes 00021 #include "libmesh/libmesh_config.h" 00022 00023 /* 00024 * Require complex arithmetic 00025 */ 00026 #if defined(LIBMESH_USE_COMPLEX_NUMBERS) 00027 00028 00029 // C++ includes 00030 #include <cstdio> // for sprintf 00031 00032 // Local includes 00033 #include "libmesh/frequency_system.h" 00034 #include "libmesh/equation_systems.h" 00035 #include "libmesh/libmesh_logging.h" 00036 #include "libmesh/linear_solver.h" 00037 #include "libmesh/numeric_vector.h" 00038 00039 namespace libMesh 00040 { 00041 00042 00043 00044 // ------------------------------------------------------------ 00045 // FrequencySystem implementation 00046 FrequencySystem::FrequencySystem (EquationSystems& es, 00047 const std::string& name_in, 00048 const unsigned int number_in) : 00049 LinearImplicitSystem (es, name_in, number_in), 00050 solve_system (NULL), 00051 _finished_set_frequencies (false), 00052 _keep_solution_duplicates (true), 00053 _finished_init (false), 00054 _finished_assemble (false) 00055 { 00056 // default value for wave speed & fluid density 00057 //_equation_systems.parameters.set<Real>("wave speed") = 340.; 00058 //_equation_systems.parameters.set<Real>("rho") = 1.225; 00059 } 00060 00061 00062 00063 FrequencySystem::~FrequencySystem () 00064 { 00065 this->clear (); 00066 00067 // the additional matrices and vectors are cleared and zero'ed in System 00068 } 00069 00070 00071 00072 00073 void FrequencySystem::clear () 00074 { 00075 LinearImplicitSystem::clear(); 00076 00077 _finished_set_frequencies = false; 00078 _keep_solution_duplicates = true; 00079 _finished_init = false; 00080 _finished_assemble = false; 00081 00082 /* 00083 * We have to distinguish between the 00084 * simple straightforward "clear()" 00085 * and the clear that also touches the 00086 * EquationSystems parameters "current frequency" etc. 00087 * Namely, when reading from file (through equation_systems_io.C 00088 * methods), the param's are read in, then the systems. 00089 * Prior to reading a system, this system gets cleared... 00090 * And there, all the previously loaded frequency parameters 00091 * would get lost... 00092 */ 00093 } 00094 00095 00096 00097 void FrequencySystem::clear_all () 00098 { 00099 this->clear (); 00100 00101 EquationSystems& es = 00102 this->get_equation_systems(); 00103 00104 // clear frequencies in the parameters section of the 00105 // EquationSystems object 00106 if (es.parameters.have_parameter<unsigned int> ("n_frequencies")) 00107 { 00108 unsigned int n_freq = es.parameters.get<unsigned int>("n_frequencies"); 00109 for (unsigned int n=0; n < n_freq; n++) 00110 es.parameters.remove(this->form_freq_param_name(n)); 00111 es.parameters.remove("current frequency"); 00112 } 00113 } 00114 00115 00116 00117 00118 void FrequencySystem::init_data () 00119 { 00120 // initialize parent data and additional solution vectors 00121 LinearImplicitSystem::init_data(); 00122 00123 // Log how long initializing the system takes 00124 START_LOG("init()", "FrequencySystem"); 00125 00126 EquationSystems& es = 00127 this->get_equation_systems(); 00128 00129 // make sure we have frequencies to solve for 00130 if (!_finished_set_frequencies) 00131 { 00132 /* 00133 * when this system was read from file, check 00134 * if this has a "n_frequencies" parameter, 00135 * and initialize us with these. 00136 */ 00137 if (es.parameters.have_parameter<unsigned int> ("n_frequencies")) 00138 { 00139 const unsigned int n_freq = 00140 es.parameters.get<unsigned int>("n_frequencies"); 00141 00142 libmesh_assert_greater (n_freq, 0); 00143 00144 _finished_set_frequencies = true; 00145 00146 this->set_current_frequency(0); 00147 } 00148 else 00149 libmesh_error_msg("ERROR: Need to set frequencies before calling init()."); 00150 } 00151 00152 _finished_init = true; 00153 00154 // Stop logging init() 00155 STOP_LOG("init()", "FrequencySystem"); 00156 } 00157 00158 00159 00160 void FrequencySystem::assemble () 00161 { 00162 libmesh_assert (_finished_init); 00163 00164 if (_finished_assemble) 00165 libmesh_error_msg("ERROR: Matrices already assembled."); 00166 00167 // Log how long assemble() takes 00168 START_LOG("assemble()", "FrequencySystem"); 00169 00170 // prepare matrix with the help of the _dof_map, 00171 // fill with sparsity pattern, initialize the 00172 // additional matrices 00173 LinearImplicitSystem::assemble(); 00174 00175 //matrix.print (); 00176 //rhs.print (); 00177 00178 _finished_assemble = true; 00179 00180 // Log how long assemble() takes 00181 STOP_LOG("assemble()", "FrequencySystem"); 00182 } 00183 00184 00185 00186 void FrequencySystem::set_frequencies_by_steps (const Real base_freq, 00187 const Real freq_step, 00188 const unsigned int n_freq, 00189 const bool allocate_solution_duplicates) 00190 { 00191 this->_keep_solution_duplicates = allocate_solution_duplicates; 00192 00193 // sanity check 00194 if (_finished_set_frequencies) 00195 libmesh_error_msg("ERROR: frequencies already initialized."); 00196 00197 EquationSystems& es = 00198 this->get_equation_systems(); 00199 00200 // store number of frequencies as parameter 00201 es.parameters.set<unsigned int>("n_frequencies") = n_freq; 00202 00203 for (unsigned int n=0; n<n_freq; n++) 00204 { 00205 // remember frequencies as parameters 00206 es.parameters.set<Real>(this->form_freq_param_name(n)) = 00207 base_freq + n * freq_step; 00208 00209 // build storage for solution vector, if wanted 00210 if (this->_keep_solution_duplicates) 00211 this->add_vector(this->form_solu_vec_name(n)); 00212 } 00213 00214 _finished_set_frequencies = true; 00215 00216 // set the current frequency 00217 this->set_current_frequency(0); 00218 } 00219 00220 00221 00222 void FrequencySystem::set_frequencies_by_range (const Real min_freq, 00223 const Real max_freq, 00224 const unsigned int n_freq, 00225 const bool allocate_solution_duplicates) 00226 { 00227 this->_keep_solution_duplicates = allocate_solution_duplicates; 00228 00229 // sanity checks 00230 libmesh_assert_greater (max_freq, min_freq); 00231 libmesh_assert_greater (n_freq, 0); 00232 00233 if (_finished_set_frequencies) 00234 libmesh_error_msg("ERROR: frequencies already initialized."); 00235 00236 EquationSystems& es = 00237 this->get_equation_systems(); 00238 00239 // store number of frequencies as parameter 00240 es.parameters.set<unsigned int>("n_frequencies") = n_freq; 00241 00242 // set frequencies, build solution storage 00243 for (unsigned int n=0; n<n_freq; n++) 00244 { 00245 // remember frequencies as parameters 00246 es.parameters.set<Real>(this->form_freq_param_name(n)) = 00247 min_freq + n*(max_freq-min_freq)/(n_freq-1); 00248 00249 // build storage for solution vector, if wanted 00250 if (this->_keep_solution_duplicates) 00251 System::add_vector(this->form_solu_vec_name(n)); 00252 } 00253 00254 _finished_set_frequencies = true; 00255 00256 // set the current frequency 00257 this->set_current_frequency(0); 00258 } 00259 00260 00261 00262 void FrequencySystem::set_frequencies (const std::vector<Real>& frequencies, 00263 const bool allocate_solution_duplicates) 00264 { 00265 this->_keep_solution_duplicates = allocate_solution_duplicates; 00266 00267 // sanity checks 00268 libmesh_assert(!frequencies.empty()); 00269 00270 if (_finished_set_frequencies) 00271 libmesh_error_msg("ERROR: frequencies already initialized."); 00272 00273 EquationSystems& es = 00274 this->get_equation_systems(); 00275 00276 // store number of frequencies as parameter 00277 es.parameters.set<unsigned int>("n_frequencies") = frequencies.size(); 00278 00279 // set frequencies, build solution storage 00280 for (unsigned int n=0; n<frequencies.size(); n++) 00281 { 00282 // remember frequencies as parameters 00283 es.parameters.set<Real>(this->form_freq_param_name(n)) = frequencies[n]; 00284 00285 // build storage for solution vector, if wanted 00286 if (this->_keep_solution_duplicates) 00287 System::add_vector(this->form_solu_vec_name(n)); 00288 } 00289 00290 _finished_set_frequencies = true; 00291 00292 // set the current frequency 00293 this->set_current_frequency(0); 00294 } 00295 00296 00297 00298 00299 unsigned int FrequencySystem::n_frequencies () const 00300 { 00301 libmesh_assert(_finished_set_frequencies); 00302 return this->get_equation_systems().parameters.get<unsigned int>("n_frequencies"); 00303 } 00304 00305 00306 00307 void FrequencySystem::solve () 00308 { 00309 libmesh_assert_greater (this->n_frequencies(), 0); 00310 00311 // Solve for all the specified frequencies 00312 this->solve (0, this->n_frequencies()-1); 00313 } 00314 00315 00316 00317 void FrequencySystem::solve (const unsigned int n_start, 00318 const unsigned int n_stop) 00319 { 00320 // Assemble the linear system, if not already done 00321 if (!_finished_assemble) 00322 this->assemble (); 00323 00324 // the user-supplied solve method _has_ to be provided by the user 00325 libmesh_assert(solve_system); 00326 00327 // existence & range checks 00328 libmesh_assert_greater (this->n_frequencies(), 0); 00329 libmesh_assert_less (n_stop, this->n_frequencies()); 00330 00331 EquationSystems& es = 00332 this->get_equation_systems(); 00333 00334 // Get the user-specified linear solver tolerance, 00335 // the user-specified maximum # of linear solver iterations, 00336 // the user-specified wave speed 00337 const Real tol = 00338 es.parameters.get<Real>("linear solver tolerance"); 00339 const unsigned int maxits = 00340 es.parameters.get<unsigned int>("linear solver maximum iterations"); 00341 00342 00343 // // return values 00344 // std::vector< std::pair<unsigned int, Real> > vec_rval; 00345 00346 // start solver loop 00347 for (unsigned int n=n_start; n<= n_stop; n++) 00348 { 00349 // set the current frequency 00350 this->set_current_frequency(n); 00351 00352 // Call the user-supplied pre-solve method 00353 START_LOG("user_pre_solve()", "FrequencySystem"); 00354 00355 this->solve_system (es, this->name()); 00356 00357 STOP_LOG("user_pre_solve()", "FrequencySystem"); 00358 00359 00360 // Solve the linear system for this specific frequency 00361 const std::pair<unsigned int, Real> rval = 00362 linear_solver->solve (*matrix, *solution, *rhs, tol, maxits); 00363 00364 _n_linear_iterations = rval.first; 00365 _final_linear_residual = rval.second; 00366 00367 vec_rval.push_back(rval); 00368 00372 if (this->_keep_solution_duplicates) 00373 this->get_vector(this->form_solu_vec_name(n)) = *solution; 00374 } 00375 00376 // sanity check 00377 //libmesh_assert_equal_to (vec_rval.size(), (n_stop-n_start+1)); 00378 00379 //return vec_rval; 00380 } 00381 00382 00383 00384 void FrequencySystem::attach_solve_function(void fptr(EquationSystems& es, 00385 const std::string& name)) 00386 { 00387 libmesh_assert(fptr); 00388 00389 solve_system = fptr; 00390 } 00391 00392 00393 00394 void FrequencySystem::set_current_frequency(unsigned int n) 00395 { 00396 libmesh_assert_less (n, n_frequencies()); 00397 00398 EquationSystems& es = 00399 this->get_equation_systems(); 00400 00401 es.parameters.set<Real>("current frequency") = 00402 es.parameters.get<Real>(this->form_freq_param_name(n)); 00403 } 00404 00405 00406 00407 std::string FrequencySystem::form_freq_param_name(const unsigned int n) const 00408 { 00409 libmesh_assert_less (n, 9999); 00410 char buf[15]; 00411 sprintf(buf, "frequency %04u", n); 00412 return (buf); 00413 } 00414 00415 00416 00417 std::string FrequencySystem::form_solu_vec_name(const unsigned int n) const 00418 { 00419 libmesh_assert_less (n, 9999); 00420 char buf[15]; 00421 sprintf(buf, "solution %04u", n); 00422 return (buf); 00423 } 00424 00425 } // namespace libMesh 00426 00427 00428 #endif // if defined(LIBMESH_USE_COMPLEX_NUMBERS)