$extrastylesheet
frequency_system.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 
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)