system.C

Go to the documentation of this file.
00001 // $Id: system.C 3546 2009-11-06 20:13:28Z roystgnr $
00002 
00003 // The libMesh Finite Element Library.
00004 // Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00005   
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License, or (at your option) any later version.
00010   
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015   
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 
00021 
00022 // C++ includes
00023 #include <sstream>   // for std::ostringstream
00024 
00025 
00026 // Local includes
00027 #include "dof_map.h"
00028 #include "equation_systems.h"
00029 #include "libmesh_logging.h"
00030 #include "mesh_base.h"
00031 #include "numeric_vector.h"
00032 #include "parameter_vector.h"
00033 #include "qoi_set.h"
00034 #include "string_to_enum.h"
00035 #include "system.h"
00036 #include "utility.h"
00037 
00038 // includes for calculate_norm
00039 #include "fe_base.h"
00040 #include "parallel.h"
00041 #include "quadrature.h"
00042 #include "tensor_value.h"
00043 #include "vector_value.h"
00044 
00045 
00046 // ------------------------------------------------------------
00047 // System implementation
00048 System::System (EquationSystems& es,
00049                 const std::string& name,
00050                 const unsigned int number) :
00051 
00052   assemble_before_solve    (true),
00053   solution                 (NumericVector<Number>::build()),
00054   current_local_solution   (NumericVector<Number>::build()),
00055   qoi                      (0),
00056   _init_system             (NULL),
00057   _assemble_system         (NULL),
00058   _constrain_system        (NULL),
00059   _dof_map                 (new DofMap(number)),
00060   _equation_systems        (es),
00061   _mesh                    (es.get_mesh()),
00062   _sys_name                (name),
00063   _sys_number              (number),
00064   _active                  (true),
00065   _solution_projection     (true),
00066   _can_add_vectors         (true),
00067   _additional_data_written (false)
00068 {
00069 }
00070 
00071 
00072 
00073 System::~System ()
00074 {
00075   // Null-out the function pointers.  Since this
00076   // class is getting destructed it is pointless,
00077   // but a good habit.
00078   _init_system = _assemble_system = NULL;
00079 
00080   // Clear data
00081   this->clear ();
00082 
00083   libmesh_assert (!libMesh::closed());
00084 }
00085 
00086 
00087 
00088 unsigned int System::n_dofs() const
00089 {
00090   return _dof_map->n_dofs();
00091 }
00092 
00093 
00094 
00095 unsigned int System::n_constrained_dofs() const
00096 {
00097 #ifdef LIBMESH_ENABLE_AMR
00098 
00099   return _dof_map->n_constrained_dofs();
00100 
00101 #else
00102 
00103   return 0;
00104 
00105 #endif
00106 }
00107 
00108 
00109 
00110 unsigned int System::n_local_dofs() const
00111 {
00112   return _dof_map->n_dofs_on_processor (libMesh::processor_id());
00113 }
00114 
00115 
00116 
00117 Number System::current_solution (const unsigned int global_dof_number) const
00118 {
00119   // Check the sizes
00120   libmesh_assert (global_dof_number < _dof_map->n_dofs());
00121   libmesh_assert (global_dof_number < current_local_solution->size());
00122    
00123   return (*current_local_solution)(global_dof_number);
00124 }
00125 
00126 
00127 
00128 void System::clear ()
00129 {
00130   _variables.clear();
00131   
00132   _variable_numbers.clear();
00133 
00134   _dof_map->clear ();
00135   
00136   solution->clear ();
00137 
00138   current_local_solution->clear ();
00139   
00140   // clear any user-added vectors
00141   {
00142     for (vectors_iterator pos = _vectors.begin(); pos != _vectors.end(); ++pos)
00143       {
00144         pos->second->clear ();
00145         delete pos->second;
00146         pos->second = NULL;
00147       }
00148     
00149     _vectors.clear();
00150     _vector_projections.clear();
00151     _can_add_vectors = true;
00152   }
00153 
00154 }
00155 
00156 
00157 
00158 void System::init ()
00159 { 
00160   // First initialize any required data
00161   this->init_data();
00162   
00163   //If no variables have been added to this system
00164   //don't do anything
00165   if(!this->n_vars())
00166     return;
00167  
00168   // Then call the user-provided intialization function
00169   this->user_initialization();
00170 }
00171 
00172 
00173 
00174 void System::init_data ()
00175 {
00176   MeshBase &mesh = this->get_mesh();
00177 
00178   // Distribute the degrees of freedom on the mesh
00179   _dof_map->distribute_dofs (mesh);
00180 
00181 #ifdef LIBMESH_ENABLE_AMR
00182 
00183   // Recreate any hanging node constraints
00184   _dof_map->create_dof_constraints(mesh);
00185 
00186   // Apply any user-defined constraints
00187   this->user_constrain();
00188 
00189   // Expand any recursive constraints
00190   _dof_map->process_constraints();
00191 
00192   // And clean up the send_list before we first use it
00193   _dof_map->prepare_send_list();
00194 
00195 #endif
00196   
00197   // Resize the solution conformal to the current mesh
00198   solution->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
00199 
00200   // Resize the current_local_solution for the current mesh
00201 #ifdef LIBMESH_ENABLE_GHOSTED
00202   current_local_solution->init (this->n_dofs(), this->n_local_dofs(),
00203                                 _dof_map->get_send_list(), false,
00204                                 GHOSTED);
00205 #else
00206   current_local_solution->init (this->n_dofs(), false, SERIAL);
00207 #endif
00208 
00209   // from now on, no chance to add additional vectors
00210   _can_add_vectors = false;
00211 
00212   // initialize & zero other vectors, if necessary
00213   for (vectors_iterator pos = _vectors.begin(); pos != _vectors.end(); ++pos)
00214       pos->second->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
00215 }
00216 
00217 
00218 
00219 void System::restrict_vectors ()
00220 {
00221 #ifdef LIBMESH_ENABLE_AMR
00222   // Restrict the _vectors on the coarsened cells
00223   for (vectors_iterator pos = _vectors.begin(); pos != _vectors.end(); ++pos)
00224     {
00225       NumericVector<Number>* v = pos->second;
00226       
00227       if (_vector_projections[pos->first])
00228         this->project_vector (*v);
00229       else
00230         v->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
00231     }
00232 
00233   const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
00234 
00235   // Restrict the solution on the coarsened cells
00236   if (_solution_projection)
00237     this->project_vector (*solution);
00238 
00239 #ifdef LIBMESH_ENABLE_GHOSTED
00240   current_local_solution->init(this->n_dofs(),
00241                                this->n_local_dofs(), send_list, 
00242                                false, GHOSTED);
00243 #else
00244   current_local_solution->init(this->n_dofs());
00245 #endif
00246 
00247   if (_solution_projection)
00248     solution->localize (*current_local_solution, send_list); 
00249 
00250 #endif // LIBMESH_ENABLE_AMR
00251 }
00252 
00253 
00254 
00255 void System::prolong_vectors ()
00256 {
00257 #ifdef LIBMESH_ENABLE_AMR
00258   // Currently project_vector handles both restriction and prolongation
00259   this->restrict_vectors();
00260 #endif
00261 }
00262 
00263 
00264 
00265 void System::reinit ()
00266 {
00267 #ifdef LIBMESH_ENABLE_AMR
00268   //If no variables have been added to this system
00269   //don't do anything
00270   if(!this->n_vars())
00271     return;
00272 
00273   // Constraints get handled in EquationSystems::reinit now
00274 //  _dof_map->create_dof_constraints(this->get_mesh());
00275 
00276   // Update the solution based on the projected
00277   // current_local_solution.
00278   solution->init (this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
00279         
00280   libmesh_assert (solution->size() == current_local_solution->size());
00281   // Not true with ghosted vectors
00282   // libmesh_assert (solution->size() == current_local_solution->local_size());
00283 
00284   const unsigned int first_local_dof = solution->first_local_index();
00285   const unsigned int local_size      = solution->local_size();
00286       
00287   for (unsigned int i=0; i<local_size; i++)
00288     solution->set(i+first_local_dof,
00289                   (*current_local_solution)(i+first_local_dof));
00290 #endif
00291 }
00292 
00293 
00294 
00295 void System::update ()
00296 {
00297   const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
00298 
00299   // Check sizes
00300   libmesh_assert (current_local_solution->size() == solution->size());
00301 // More processors than elements => empty send_list
00302 //  libmesh_assert (!send_list.empty());
00303   libmesh_assert (send_list.size() <= solution->size());
00304 
00305   // Create current_local_solution from solution.  This will
00306   // put a local copy of solution into current_local_solution.
00307   // Only the necessary values (specified by the send_list)
00308   // are copied to minimize communication
00309   solution->localize (*current_local_solution, send_list); 
00310 }
00311 
00312 
00313 
00314 void System::re_update ()
00315 {
00316   //const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
00317 
00318   // If this system is empty... don't do anything!
00319   if(!this->n_vars())
00320     return;
00321 
00322   // Explicitly build a send_list
00323   std::vector<unsigned int> send_list(solution->size());
00324   Utility::iota (send_list.begin(), send_list.end(), 0);
00325   
00326   // Check sizes
00327   libmesh_assert (current_local_solution->size()       == solution->size());
00328   // Not true with ghosted vectors
00329   // libmesh_assert (current_local_solution->local_size() == solution->size());
00330   libmesh_assert (!send_list.empty());
00331   libmesh_assert (send_list.size() <= solution->size());
00332 
00333   // Create current_local_solution from solution.  This will
00334   // put a local copy of solution into current_local_solution.
00335   solution->localize (*current_local_solution, send_list);
00336 }
00337 
00338 
00339 
00340 void System::assemble ()
00341 {
00342   // Log how long the user's matrix assembly code takes
00343   START_LOG("assemble()", "System");
00344   
00345   // Call the user-specified assembly function
00346   this->user_assembly();
00347 
00348   // Stop logging the user code
00349   STOP_LOG("assemble()", "System");
00350 }
00351 
00352 
00353 
00354 void System::assemble_qoi (const QoISet& qoi_indices)
00355 {
00356   // Log how long the user's matrix assembly code takes
00357   START_LOG("assemble_qoi()", "System");
00358   
00359   // Call the user-specified quantity of interest function
00360   this->user_QOI(qoi_indices);
00361 
00362   // Stop logging the user code
00363   STOP_LOG("assemble_qoi()", "System");
00364 }
00365 
00366 
00367 
00368 void System::assemble_qoi_derivative (const QoISet& qoi_indices)
00369 {
00370   // Log how long the user's matrix assembly code takes
00371   START_LOG("assemble_qoi_derivative()", "System");
00372   
00373   // Call the user-specified quantity of interest function
00374   this->user_QOI_derivative(qoi_indices);
00375 
00376   // Stop logging the user code
00377   STOP_LOG("assemble_qoi_derivative()", "System");
00378 }
00379 
00380 
00381 
00382 void System::qoi_parameter_sensitivity
00383   (const QoISet& qoi_indices,
00384    const ParameterVector& parameters,
00385    SensitivityData& sensitivities)
00386 {
00387   // Forward sensitivities are more efficient for Nq > Np
00388   if (qoi_indices.size(*this) > parameters.size())
00389     forward_qoi_parameter_sensitivity(qoi_indices, parameters, sensitivities);
00390   // Adjoint sensitivities are more efficient for Np > Nq,
00391   // and an adjoint may be more reusable than a forward 
00392   // solution sensitivity in the Np == Nq case.
00393   else
00394     adjoint_qoi_parameter_sensitivity(qoi_indices, parameters, sensitivities);
00395 }
00396 
00397 
00398 
00399 bool System::compare (const System& other_system, 
00400                       const Real threshold,
00401                       const bool verbose) const
00402 {
00403   // we do not care for matrices, but for vectors
00404   libmesh_assert (!_can_add_vectors);
00405   libmesh_assert (!other_system._can_add_vectors);
00406 
00407   if (verbose)
00408     {
00409       std::cout << "  Systems \"" << _sys_name << "\"" << std::endl;
00410       std::cout << "   comparing matrices not supported." << std::endl;
00411       std::cout << "   comparing names...";
00412     }
00413 
00414   // compare the name: 0 means identical
00415   const int name_result = _sys_name.compare(other_system.name());
00416   if (verbose)
00417     {
00418       if (name_result == 0)
00419         std::cout << " identical." << std::endl;
00420       else
00421         std::cout << "  names not identical." << std::endl;
00422       std::cout << "   comparing solution vector...";
00423     }
00424 
00425 
00426   // compare the solution: -1 means identical
00427   const int solu_result = solution->compare (*other_system.solution.get(),
00428                                              threshold);
00429 
00430   if (verbose)
00431     {
00432       if (solu_result == -1)
00433         std::cout << " identical up to threshold." << std::endl;
00434       else
00435         std::cout << "  first difference occured at index = " 
00436                   << solu_result << "." << std::endl;
00437     }
00438 
00439 
00440   // safety check, whether we handle at least the same number
00441   // of vectors
00442   std::vector<int> ov_result;
00443 
00444   if (this->n_vectors() != other_system.n_vectors())
00445     {
00446       if (verbose)
00447         {
00448           std::cout << "   Fatal difference. This system handles " 
00449                     << this->n_vectors() << " add'l vectors," << std::endl
00450                     << "   while the other system handles "
00451                     << other_system.n_vectors() 
00452                     << " add'l vectors." << std::endl
00453                     << "   Aborting comparison." << std::endl;
00454         }
00455       return false;
00456     }
00457   else if (this->n_vectors() == 0)
00458     {
00459       // there are no additional vectors...
00460       ov_result.clear ();
00461     }
00462   else
00463     {
00464       // compare other vectors
00465       for (const_vectors_iterator pos = _vectors.begin();
00466            pos != _vectors.end(); ++pos)
00467         {
00468           if (verbose)
00469               std::cout << "   comparing vector \""
00470                         << pos->first << "\" ...";
00471 
00472           // assume they have the same name
00473           const NumericVector<Number>& other_system_vector = 
00474               other_system.get_vector(pos->first);
00475 
00476           ov_result.push_back(pos->second->compare (other_system_vector,
00477                                                     threshold));
00478 
00479           if (verbose)
00480             {
00481               if (ov_result[ov_result.size()-1] == -1)
00482                 std::cout << " identical up to threshold." << std::endl;
00483               else
00484                 std::cout << " first difference occured at" << std::endl
00485                           << "   index = " << ov_result[ov_result.size()-1] << "." << std::endl;
00486             }
00487 
00488         }
00489 
00490     } // finished comparing additional vectors
00491 
00492 
00493   bool overall_result;
00494        
00495   // sum up the results
00496   if ((name_result==0) && (solu_result==-1))
00497     {
00498       if (ov_result.size()==0)
00499         overall_result = true;
00500       else
00501         {
00502           bool ov_identical;
00503           unsigned int n    = 0;
00504           do
00505             {
00506               ov_identical = (ov_result[n]==-1);
00507               n++;
00508             }
00509           while (ov_identical && n<ov_result.size());
00510           overall_result = ov_identical;
00511         }
00512     }
00513   else
00514     overall_result = false;
00515 
00516   if (verbose)
00517     {
00518       std::cout << "   finished comparisons, ";
00519       if (overall_result)
00520         std::cout << "found no differences." << std::endl << std::endl;
00521       else 
00522         std::cout << "found differences." << std::endl << std::endl;
00523     }
00524           
00525   return overall_result;
00526 }
00527 
00528 
00529 
00530 void System::update_global_solution (std::vector<Number>& global_soln) const
00531 {
00532   global_soln.resize (solution->size());
00533 
00534   solution->localize (global_soln);
00535 }
00536 
00537 
00538 
00539 void System::update_global_solution (std::vector<Number>& global_soln,
00540                                      const unsigned int   dest_proc) const
00541 {
00542   global_soln.resize        (solution->size());
00543 
00544   solution->localize_to_one (global_soln, dest_proc);
00545 }
00546 
00547 
00548 
00549 NumericVector<Number> & System::add_vector (const std::string& vec_name,
00550                                             const bool projections)
00551 {
00552   // Return the vector if it is already there.
00553   if (this->have_vector(vec_name))
00554     return *(_vectors[vec_name]);
00555 
00556   // Otherwise build the vector
00557   NumericVector<Number>* buf = NumericVector<Number>::build().release();
00558   _vectors.insert (std::make_pair (vec_name, buf));
00559   _vector_projections.insert (std::make_pair (vec_name, projections));
00560 
00561   // Initialize it if necessary
00562   if (!_can_add_vectors)
00563     buf->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
00564 
00565   return *buf;
00566 }
00567 
00568 
00569 
00570 const NumericVector<Number> * System::request_vector (const std::string& vec_name) const
00571 {
00572   const_vectors_iterator pos = _vectors.find(vec_name);
00573   
00574   if (pos == _vectors.end())
00575     return NULL;
00576   
00577   return pos->second;
00578 }
00579 
00580 
00581 
00582 NumericVector<Number> * System::request_vector (const std::string& vec_name)
00583 {
00584   vectors_iterator pos = _vectors.find(vec_name);
00585   
00586   if (pos == _vectors.end())
00587     return NULL;
00588   
00589   return pos->second;
00590 }
00591 
00592 
00593 
00594 const NumericVector<Number> * System::request_vector (const unsigned int vec_num) const
00595 {
00596   const_vectors_iterator v = vectors_begin();
00597   const_vectors_iterator v_end = vectors_end();
00598   unsigned int num = 0;
00599   while((num<vec_num) && (v!=v_end))
00600     {
00601       num++;
00602       ++v;
00603     }
00604   if (v==v_end)
00605     return NULL;
00606   return v->second;
00607 }
00608 
00609 
00610 
00611 NumericVector<Number> * System::request_vector (const unsigned int vec_num)
00612 {
00613   vectors_iterator v = vectors_begin();
00614   vectors_iterator v_end = vectors_end();
00615   unsigned int num = 0;
00616   while((num<vec_num) && (v!=v_end))
00617     {
00618       num++;
00619       ++v;
00620     }
00621   if (v==v_end)
00622     return NULL;
00623   return v->second;
00624 }
00625 
00626 
00627 
00628 const NumericVector<Number> & System::get_vector (const std::string& vec_name) const
00629 {
00630   // Make sure the vector exists
00631   const_vectors_iterator pos = _vectors.find(vec_name);
00632   
00633   if (pos == _vectors.end())
00634     {
00635       std::cerr << "ERROR: vector "
00636                 << vec_name
00637                 << " does not exist in this system!"
00638                 << std::endl;      
00639       libmesh_error();
00640     }
00641   
00642   return *(pos->second);
00643 }
00644 
00645 
00646 
00647 NumericVector<Number> & System::get_vector (const std::string& vec_name)
00648 {
00649   // Make sure the vector exists
00650   vectors_iterator pos = _vectors.find(vec_name);
00651   
00652   if (pos == _vectors.end())
00653     {
00654       std::cerr << "ERROR: vector "
00655                 << vec_name
00656                 << " does not exist in this system!"
00657                 << std::endl;      
00658       libmesh_error();
00659     }
00660   
00661   return *(pos->second);
00662 }
00663 
00664 
00665 
00666 const NumericVector<Number> & System::get_vector (const unsigned int vec_num) const
00667 {
00668   const_vectors_iterator v = vectors_begin();
00669   const_vectors_iterator v_end = vectors_end();
00670   unsigned int num = 0;
00671   while((num<vec_num) && (v!=v_end))
00672     {
00673       num++;
00674       ++v;
00675     }
00676   libmesh_assert(v!=v_end);
00677   return *(v->second);
00678 }
00679 
00680 
00681 
00682 NumericVector<Number> & System::get_vector (const unsigned int vec_num)
00683 {
00684   vectors_iterator v = vectors_begin();
00685   vectors_iterator v_end = vectors_end();
00686   unsigned int num = 0;
00687   while((num<vec_num) && (v!=v_end))
00688     {
00689       num++;
00690       ++v;
00691     }
00692   libmesh_assert(v!=v_end);
00693   return *(v->second);
00694 }
00695 
00696 
00697 
00698 const std::string& System::vector_name (const unsigned int vec_num)
00699 {
00700   const_vectors_iterator v = vectors_begin();
00701   const_vectors_iterator v_end = vectors_end();
00702   unsigned int num = 0;
00703   while((num<vec_num) && (v!=v_end))
00704     {
00705       num++;
00706       ++v;
00707     }
00708   libmesh_assert(v!=v_end);
00709   return v->first;
00710 }
00711 
00712 
00713 
00714 NumericVector<Number> & System::add_sensitivity_solution (unsigned int i)
00715 {
00716   OStringStream sensitivity_name;
00717   sensitivity_name << "sensitivity_solution" << i;
00718 
00719   return this->add_vector(sensitivity_name.str());
00720 }
00721 
00722 
00723 NumericVector<Number> & System::get_sensitivity_solution (unsigned int i)
00724 {
00725   OStringStream sensitivity_name;
00726   sensitivity_name << "sensitivity_solution" << i;
00727 
00728   return this->get_vector(sensitivity_name.str());
00729 }
00730 
00731 
00732 
00733 const NumericVector<Number> & System::get_sensitivity_solution (unsigned int i) const
00734 {
00735   OStringStream sensitivity_name;
00736   sensitivity_name << "sensitivity_solution" << i;
00737 
00738   return this->get_vector(sensitivity_name.str());
00739 }
00740 
00741 
00742 
00743 NumericVector<Number> & System::add_weighted_sensitivity_solution ()
00744 {
00745   return this->add_vector("weighted_sensitivity_solution");
00746 }
00747 
00748 
00749 
00750 NumericVector<Number> & System::get_weighted_sensitivity_solution ()
00751 {
00752   return this->get_vector("weighted_sensitivity_solution");
00753 }
00754 
00755 
00756 
00757 const NumericVector<Number> & System::get_weighted_sensitivity_solution () const
00758 {
00759   return this->get_vector("weighted_sensitivity_solution");
00760 }
00761 
00762 
00763 
00764 NumericVector<Number> & System::add_adjoint_solution (unsigned int i)
00765 {
00766   OStringStream adjoint_name;
00767   adjoint_name << "adjoint_solution" << i;
00768 
00769   return this->add_vector(adjoint_name.str());
00770 }
00771 
00772 
00773 
00774 NumericVector<Number> & System::get_adjoint_solution (unsigned int i)
00775 {
00776   OStringStream adjoint_name;
00777   adjoint_name << "adjoint_solution" << i;
00778 
00779   return this->get_vector(adjoint_name.str());
00780 }
00781 
00782 
00783 
00784 const NumericVector<Number> & System::get_adjoint_solution (unsigned int i) const
00785 {
00786   OStringStream adjoint_name;
00787   adjoint_name << "adjoint_solution" << i;
00788 
00789   return this->get_vector(adjoint_name.str());
00790 }
00791 
00792 
00793 
00794 NumericVector<Number> & System::add_weighted_sensitivity_adjoint_solution (unsigned int i)
00795 {
00796   OStringStream adjoint_name;
00797   adjoint_name << "weighted_sensitivity_adjoint_solution" << i;
00798 
00799   return this->get_vector(adjoint_name.str());
00800 }
00801 
00802 
00803 
00804 NumericVector<Number> & System::get_weighted_sensitivity_adjoint_solution (unsigned int i)
00805 {
00806   OStringStream adjoint_name;
00807   adjoint_name << "weighted_sensitivity_adjoint_solution" << i;
00808 
00809   return this->get_vector(adjoint_name.str());
00810 }
00811 
00812 
00813 
00814 const NumericVector<Number> & System::get_weighted_sensitivity_adjoint_solution (unsigned int i) const
00815 {
00816   OStringStream adjoint_name;
00817   adjoint_name << "weighted_sensitivity_adjoint_solution" << i;
00818 
00819   return this->get_vector(adjoint_name.str());
00820 }
00821 
00822 
00823 
00824 NumericVector<Number> & System::add_adjoint_rhs (unsigned int i)
00825 {
00826   OStringStream adjoint_rhs_name;
00827   adjoint_rhs_name << "adjoint_rhs" << i;
00828 
00829   return this->add_vector(adjoint_rhs_name.str());
00830 }
00831 
00832 
00833 
00834 NumericVector<Number> & System::get_adjoint_rhs (unsigned int i)
00835 {
00836   OStringStream adjoint_rhs_name;
00837   adjoint_rhs_name << "adjoint_rhs" << i;
00838 
00839   return this->get_vector(adjoint_rhs_name.str());
00840 }
00841 
00842 
00843 
00844 const NumericVector<Number> & System::get_adjoint_rhs (unsigned int i) const
00845 {
00846   OStringStream adjoint_rhs_name;
00847   adjoint_rhs_name << "adjoint_rhs" << i;
00848 
00849   return this->get_vector(adjoint_rhs_name.str());
00850 }
00851 
00852 
00853 
00854 NumericVector<Number> & System::add_sensitivity_rhs (unsigned int i)
00855 {
00856   OStringStream sensitivity_rhs_name;
00857   sensitivity_rhs_name << "sensitivity_rhs" << i;
00858 
00859   return this->add_vector(sensitivity_rhs_name.str());
00860 }
00861 
00862 
00863 
00864 NumericVector<Number> & System::get_sensitivity_rhs (unsigned int i)
00865 {
00866   OStringStream sensitivity_rhs_name;
00867   sensitivity_rhs_name << "sensitivity_rhs" << i;
00868 
00869   return this->get_vector(sensitivity_rhs_name.str());
00870 }
00871 
00872 
00873 
00874 const NumericVector<Number> & System::get_sensitivity_rhs (unsigned int i) const
00875 {
00876   OStringStream sensitivity_rhs_name;
00877   sensitivity_rhs_name << "sensitivity_rhs" << i;
00878 
00879   return this->get_vector(sensitivity_rhs_name.str());
00880 }
00881 
00882 
00883 
00884 unsigned int System::add_variable (const std::string& var,
00885                                    const FEType& type,
00886                                    const std::set<subdomain_id_type> * const active_subdomains)
00887 {  
00888   // Make sure the variable isn't there already
00889   // or if it is, that it's the type we want
00890   for (unsigned int v=0; v<this->n_vars(); v++)
00891     if (this->variable_name(v) == var)
00892       {
00893         if (this->variable_type(v) == type)
00894           return _variables[v].number();
00895 
00896         std::cerr << "ERROR: incompatible variable "
00897                   << var
00898                   << " has already been added for this system!"
00899                   << std::endl;
00900         libmesh_error();
00901       }
00902 
00903   const unsigned int curr_n_vars = this->n_vars();                                              
00904 
00905   // Add the variable to the list
00906   _variables.push_back((active_subdomains == NULL) ?
00907                        Variable(var, curr_n_vars, type) :
00908                        Variable(var, curr_n_vars, type, *active_subdomains));
00909 
00910   libmesh_assert ((curr_n_vars+1) == this->n_vars());
00911 
00912   _variable_numbers[var] = curr_n_vars;
00913 
00914   // Add the variable to the _dof_map
00915   _dof_map->add_variable (_variables.back());
00916 
00917   // Return the number of the new variable
00918   return curr_n_vars;
00919 }
00920 
00921 
00922 
00923 unsigned int System::add_variable (const std::string& var,
00924                                    const Order order,
00925                                    const FEFamily family,
00926                                    const std::set<subdomain_id_type> * const active_subdomains)
00927 {
00928   return this->add_variable(var, 
00929                             FEType(order, family), 
00930                             active_subdomains);
00931 }
00932 
00933 
00934 
00935 bool System::has_variable (const std::string& var) const
00936 {
00937   return _variable_numbers.count(var);
00938 }
00939 
00940 
00941 
00942 unsigned short int System::variable_number (const std::string& var) const
00943 {
00944   // Make sure the variable exists
00945   std::map<std::string, unsigned short int>::const_iterator
00946     pos = _variable_numbers.find(var);
00947   
00948   if (pos == _variable_numbers.end())
00949     {
00950       std::cerr << "ERROR: variable "
00951                 << var
00952                 << " does not exist in this system!"
00953                 << std::endl;      
00954       libmesh_error();
00955     }
00956   libmesh_assert (_variables[pos->second].name() == var);
00957 
00958   return pos->second;
00959 }
00960 
00961 
00962 void System::local_dof_indices(const unsigned int var, std::set<unsigned int> & var_indices) const
00963 {
00964   // Make sure the set is clear
00965   var_indices.clear();
00966 
00967   std::vector<unsigned int> dof_indices;
00968   
00969   // Begin the loop over the elements
00970   MeshBase::const_element_iterator       el     =
00971     this->get_mesh().active_local_elements_begin();
00972   const MeshBase::const_element_iterator end_el =
00973     this->get_mesh().active_local_elements_end();
00974 
00975   const unsigned int 
00976     first_local = this->get_dof_map().first_dof(),
00977     end_local   = this->get_dof_map().end_dof();
00978 
00979   for ( ; el != end_el; ++el)
00980     {
00981       const Elem* elem = *el;      
00982       this->get_dof_map().dof_indices (elem, dof_indices, var);
00983 
00984       for(unsigned int i=0; i<dof_indices.size(); i++)
00985         {
00986           unsigned int dof = dof_indices[i];
00987 
00988           //If the dof is owned by the local processor
00989           if(first_local <= dof && dof < end_local)
00990             var_indices.insert(dof_indices[i]);
00991         }
00992     }
00993 }
00994 
00995 void System::zero_variable (NumericVector<Number>& v, unsigned int var_num) const
00996 {
00997   /* Make sure the call makes sense.  */
00998   libmesh_assert(var_num<this->n_vars());
00999 
01000   /* Get a reference to the mesh.  */
01001   const MeshBase& mesh = this->get_mesh();
01002 
01003   /* Check which system we are.  */
01004   const unsigned int sys_num = this->number();
01005 
01006   /* Loop over nodes.  */
01007   {
01008     MeshBase::const_node_iterator it = mesh.local_nodes_begin();
01009     const MeshBase::const_node_iterator end_it = mesh.local_nodes_end(); 
01010     for ( ; it != end_it; ++it)
01011       {    
01012         const Node* node = *it;
01013         unsigned int n_comp = node->n_comp(sys_num,var_num);
01014         for(unsigned int i=0; i<n_comp; i++)
01015           {
01016             const unsigned int index = node->dof_number(sys_num,var_num,i);
01017             v.set(index,0.0);
01018           }
01019       }
01020   }
01021 
01022   /* Loop over elements.  */
01023   {
01024     MeshBase::const_element_iterator it = mesh.active_local_elements_begin();
01025     const MeshBase::const_element_iterator end_it = mesh.active_local_elements_end(); 
01026     for ( ; it != end_it; ++it)
01027       {    
01028         const Elem* elem = *it;
01029         unsigned int n_comp = elem->n_comp(sys_num,var_num);
01030         for(unsigned int i=0; i<n_comp; i++)
01031           {
01032             const unsigned int index = elem->dof_number(sys_num,var_num,i);
01033             v.set(index,0.0);
01034           }
01035       }
01036   }
01037 }
01038 
01039 Real System::discrete_var_norm(NumericVector<Number>& v,
01040                                unsigned int var,
01041                                FEMNormType norm_type) const
01042 {
01043   std::set<unsigned int> var_indices;
01044   local_dof_indices(var, var_indices);
01045 
01046   if(norm_type == DISCRETE_L1)
01047     return v.subset_l1_norm(var_indices);
01048   if(norm_type == DISCRETE_L2)
01049     return v.subset_l2_norm(var_indices);
01050   if(norm_type == DISCRETE_L_INF)
01051     return v.subset_linfty_norm(var_indices);
01052   else
01053     libmesh_error();
01054 }
01055 
01056 Real System::calculate_norm(NumericVector<Number>& v,
01057                             unsigned int var,
01058                             FEMNormType norm_type) const
01059 {
01060   //short circuit to save time
01061   if(norm_type == DISCRETE_L1 ||
01062      norm_type == DISCRETE_L2 ||
01063      norm_type == DISCRETE_L_INF)
01064     return discrete_var_norm(v,var,norm_type);
01065 
01066   // Not a discrete norm
01067   std::vector<FEMNormType> norms(this->n_vars(), L2);
01068   std::vector<Real> weights(this->n_vars(), 0.0);
01069   norms[var] = norm_type;
01070   weights[var] = 1.0;
01071   Real val = this->calculate_norm(v, SystemNorm(norms, weights));
01072   return val;
01073 }
01074 
01075 
01076 
01077 Real System::calculate_norm(NumericVector<Number>& v,
01078                             const SystemNorm &norm) const
01079 {
01080   // This function must be run on all processors at once
01081   parallel_only();
01082 
01083   START_LOG ("calculate_norm()", "System");
01084 
01085   // Zero the norm before summation
01086   Real v_norm = 0.;
01087 
01088   if (norm.is_discrete())
01089     {
01090       STOP_LOG ("calculate_norm()", "System");
01091       //Check to see if all weights are 1.0
01092       unsigned int check_var = 0;
01093       for (; check_var != this->n_vars(); ++check_var)
01094         if(norm.weight(check_var) != 1.0)
01095           break;
01096 
01097       //All weights were 1.0 so just do the full vector discrete norm
01098       if(check_var == this->n_vars())
01099         {
01100           FEMNormType norm_type = norm.type(0);
01101           
01102           if(norm_type == DISCRETE_L1)
01103             return v.l1_norm();
01104           if(norm_type == DISCRETE_L2)
01105             return v.l2_norm();
01106           if(norm_type == DISCRETE_L_INF)
01107             return v.linfty_norm();
01108           else
01109             libmesh_error();
01110         }
01111 
01112       for (unsigned int var=0; var != this->n_vars(); ++var)
01113         {
01114           // Skip any variables we don't need to integrate
01115           if (norm.weight(var) == 0.0)
01116             continue;
01117 
01118           v_norm += norm.weight(var) * discrete_var_norm(v, var, norm.type(var));
01119         }
01120 
01121       return v_norm;
01122     }
01123 
01124   // Localize the potentially parallel vector
01125   AutoPtr<NumericVector<Number> > local_v = NumericVector<Number>::build();
01126   local_v->init(v.size(), true, SERIAL);
01127   v.localize (*local_v, _dof_map->get_send_list()); 
01128 
01129   unsigned int dim = this->get_mesh().mesh_dimension();
01130 
01131   // Loop over all variables
01132   for (unsigned int var=0; var != this->n_vars(); ++var)
01133     {
01134       // Skip any variables we don't need to integrate
01135       if (norm.weight(var) == 0.0)
01136         continue;
01137 
01138       const FEType& fe_type = this->get_dof_map().variable_type(var);
01139       AutoPtr<QBase> qrule =
01140         fe_type.default_quadrature_rule (dim);
01141       AutoPtr<FEBase> fe
01142         (FEBase::build(dim, fe_type));
01143       fe->attach_quadrature_rule (qrule.get());
01144 
01145       const std::vector<Real>&               JxW = fe->get_JxW();
01146       const std::vector<std::vector<Real> >* phi = NULL;
01147       if (norm.type(var) == H1 ||
01148           norm.type(var) == H2 ||
01149           norm.type(var) == L2)
01150         phi = &(fe->get_phi());
01151 
01152       const std::vector<std::vector<RealGradient> >* dphi = NULL;
01153       if (norm.type(var) == H1 ||
01154           norm.type(var) == H2 ||
01155           norm.type(var) == H1_SEMINORM)
01156         dphi = &(fe->get_dphi());
01157 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
01158       const std::vector<std::vector<RealTensor> >*   d2phi = NULL;
01159       if (norm.type(var) == H2 ||
01160           norm.type(var) == H2_SEMINORM)
01161         d2phi = &(fe->get_d2phi());
01162 #endif
01163 
01164       std::vector<unsigned int> dof_indices;
01165 
01166       // Begin the loop over the elements
01167       MeshBase::const_element_iterator       el     =
01168         this->get_mesh().active_local_elements_begin();
01169       const MeshBase::const_element_iterator end_el =
01170         this->get_mesh().active_local_elements_end();
01171 
01172       for ( ; el != end_el; ++el)
01173         {
01174           const Elem* elem = *el;
01175 
01176           fe->reinit (elem);
01177 
01178           this->get_dof_map().dof_indices (elem, dof_indices, var);
01179 
01180           const unsigned int n_qp = qrule->n_points();
01181 
01182           const unsigned int n_sf = dof_indices.size();
01183 
01184           // Begin the loop over the Quadrature points.
01185           for (unsigned int qp=0; qp<n_qp; qp++)
01186             {
01187               if (norm.type(var) == H1 ||
01188                   norm.type(var) == H2 ||
01189                   norm.type(var) == L2)
01190                 {
01191                   Number u_h = 0.;
01192                   for (unsigned int i=0; i != n_sf; ++i)
01193                     u_h += (*phi)[i][qp] * (*local_v)(dof_indices[i]);
01194                   v_norm += norm.weight_sq(var) *
01195                             JxW[qp] * libmesh_norm(u_h);
01196                 }
01197 
01198               if (norm.type(var) == H1 ||
01199                   norm.type(var) == H2 ||
01200                   norm.type(var) == H1_SEMINORM)
01201                 {
01202                   Gradient grad_u_h;
01203                   for (unsigned int i=0; i != n_sf; ++i)
01204                     grad_u_h.add_scaled((*dphi)[i][qp], (*local_v)(dof_indices[i]));
01205                   v_norm += norm.weight_sq(var) *
01206                             JxW[qp] * grad_u_h.size_sq();
01207                 }
01208 
01209 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
01210               if (norm.type(var) == H2 ||
01211                   norm.type(var) == H2_SEMINORM)
01212                 {
01213                   Tensor hess_u_h;
01214                   for (unsigned int i=0; i != n_sf; ++i)
01215                     hess_u_h.add_scaled((*d2phi)[i][qp], (*local_v)(dof_indices[i]));
01216                   v_norm += norm.weight_sq(var) *
01217                             JxW[qp] * hess_u_h.size_sq();
01218                 }
01219 #endif
01220             }
01221         }
01222     }
01223 
01224   Parallel::sum(v_norm);
01225 
01226   STOP_LOG ("calculate_norm()", "System");
01227 
01228   return std::sqrt(v_norm);
01229 }
01230 
01231 
01232 
01233 std::string System::get_info() const
01234 {
01235   std::ostringstream out;
01236 
01237   
01238   const std::string& sys_name = this->name();
01239       
01240   out << "   System \"" << sys_name << "\"\n"
01241       << "    Type \""  << this->system_type() << "\"\n"
01242       << "    Variables=";
01243   
01244   for (unsigned int vn=0; vn<this->n_vars(); vn++)
01245       out << "\"" << this->variable_name(vn) << "\" ";
01246      
01247   out << '\n';
01248 
01249   out << "    Finite Element Types=";
01250 #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
01251   for (unsigned int vn=0; vn<this->n_vars(); vn++)
01252     out << "\""
01253         << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).family)
01254         << "\" ";  
01255 #else
01256   for (unsigned int vn=0; vn<this->n_vars(); vn++)
01257     {
01258       out << "\""
01259           << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).family)
01260           << "\", \""
01261           << Utility::enum_to_string<FEFamily>(this->get_dof_map().variable_type(vn).radial_family)
01262           << "\" ";
01263     }
01264 
01265   out << '\n' << "    Infinite Element Mapping=";
01266   for (unsigned int vn=0; vn<this->n_vars(); vn++)
01267     out << "\""
01268         << Utility::enum_to_string<InfMapType>(this->get_dof_map().variable_type(vn).inf_map)
01269         << "\" ";
01270 #endif      
01271 
01272   out << '\n';
01273       
01274   out << "    Approximation Orders=";
01275   for (unsigned int vn=0; vn<this->n_vars(); vn++)
01276     {
01277 #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
01278       out << "\""
01279           << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).order)
01280           << "\" ";
01281 #else
01282       out << "\""
01283           << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).order)
01284           << "\", \""
01285           << Utility::enum_to_string<Order>(this->get_dof_map().variable_type(vn).radial_order)
01286           << "\" ";
01287 #endif
01288     }
01289 
01290   out << '\n';
01291       
01292   out << "    n_dofs()="             << this->n_dofs()             << '\n';
01293   out << "    n_local_dofs()="       << this->n_local_dofs()       << '\n';
01294 #ifdef LIBMESH_ENABLE_AMR
01295   out << "    n_constrained_dofs()=" << this->n_constrained_dofs() << '\n';
01296 #endif
01297 
01298   out << "    " << "n_vectors()="  << this->n_vectors()  << '\n';
01299 //   out << "    " << "n_additional_matrices()=" << this->n_additional_matrices() << '\n';
01300   
01301   return out.str();
01302 }
01303 
01304 
01305 
01306 void System::attach_init_function (void fptr(EquationSystems& es,
01307                                              const std::string& name))
01308 {
01309   libmesh_assert (fptr != NULL);
01310   
01311   _init_system = fptr;
01312 }
01313 
01314 
01315 
01316 void System::attach_assemble_function (void fptr(EquationSystems& es,
01317                                                  const std::string& name))
01318 {
01319   libmesh_assert (fptr != NULL);
01320   
01321   _assemble_system = fptr;  
01322 }
01323 
01324 
01325 
01326 void System::attach_constraint_function(void fptr(EquationSystems& es,
01327                                                   const std::string& name))
01328 {
01329   libmesh_assert (fptr != NULL);
01330   
01331   _constrain_system = fptr;  
01332 }
01333 
01334 
01335 
01336 void System::attach_QOI_function(void fptr(EquationSystems&,
01337                                            const std::string&,
01338                                            const QoISet&))
01339 {
01340   libmesh_assert (fptr != NULL);
01341   
01342   _qoi_evaluate = fptr;  
01343 }
01344 
01345 
01346 
01347 void System::attach_QOI_derivative(void fptr(EquationSystems&,
01348                                              const std::string&,
01349                                              const QoISet&))
01350 {
01351   libmesh_assert (fptr != NULL);
01352   
01353   _qoi_evaluate_derivative = fptr;  
01354 }
01355 
01356 
01357 
01358 void System::user_initialization ()
01359 {
01360   // Call the user-provided intialization function,
01361   // if it was provided
01362   if (_init_system != NULL)
01363     this->_init_system (_equation_systems, this->name());
01364 }
01365 
01366 
01367 void System::user_assembly ()
01368 {
01369   // Call the user-provided assembly function,
01370   // if it was provided
01371   if (_assemble_system != NULL)
01372     this->_assemble_system (_equation_systems, this->name());
01373 }
01374 
01375 
01376 
01377 void System::user_constrain ()
01378 {
01379   // Call the user-provided constraint function, 
01380   // if it was provided
01381   if(_constrain_system!= NULL)
01382     this->_constrain_system(_equation_systems, this->name());
01383 }
01384 
01385 
01386 
01387 void System::user_QOI (const QoISet& qoi_indices)
01388 {
01389   // Call the user-provided quantity of interest function, 
01390   // if it was provided
01391   if(_qoi_evaluate != NULL)
01392     this->_qoi_evaluate(_equation_systems, this->name(), qoi_indices);
01393 }
01394 
01395 
01396 
01397 void System::user_QOI_derivative (const QoISet& qoi_indices)
01398 {
01399   // Call the user-provided quantity of interest derivative, 
01400   // if it was provided
01401   if(_qoi_evaluate_derivative != NULL)
01402     this->_qoi_evaluate_derivative(_equation_systems, this->name(), qoi_indices);
01403 }

Site Created By: libMesh Developers
Last modified: November 25 2009 03:43:48.

Hosted By:
SourceForge.net Logo