equation_systems.C

Go to the documentation of this file.
00001 // $Id: equation_systems.C 3530 2009-10-30 23:03:08Z 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 // System includes
00022 #include <sstream>
00023 
00024 // Local Includes
00025 #include "explicit_system.h"
00026 #include "fe_interface.h"
00027 #include "frequency_system.h"
00028 #include "linear_implicit_system.h"
00029 #include "mesh_refinement.h"
00030 #include "newmark_system.h"
00031 #include "nonlinear_implicit_system.h"
00032 #include "parallel.h"
00033 #include "transient_system.h"
00034 #include "dof_map.h"
00035 #include "mesh_base.h"
00036 #include "elem.h"
00037 #include "libmesh_logging.h"
00038 
00039 // Include the systems before this one to avoid
00040 // overlapping forward declarations.
00041 #include "equation_systems.h"
00042 
00043 // Forward Declarations
00044 
00045 
00046 
00047 
00048 // ------------------------------------------------------------
00049 // EquationSystems class implementation
00050 EquationSystems::EquationSystems (MeshBase& m, MeshData* mesh_data) :
00051   _mesh      (m),
00052   _mesh_data (mesh_data)
00053 {
00054   // Set default parameters
00055   this->parameters.set<Real>        ("linear solver tolerance") = TOLERANCE * TOLERANCE;
00056   this->parameters.set<unsigned int>("linear solver maximum iterations") = 5000;  
00057 }
00058 
00059 
00060 
00061 EquationSystems::~EquationSystems ()
00062 {
00063   this->clear ();
00064 }
00065 
00066 
00067 
00068 void EquationSystems::clear ()
00069 {
00070   // Clear any additional parameters
00071   parameters.clear ();
00072 
00073   // clear the systems.  We must delete them
00074   // since we newed them!
00075   while (!_systems.empty())
00076     {
00077       system_iterator pos = _systems.begin();
00078       
00079       System *sys = pos->second;
00080       delete sys;
00081       sys = NULL;
00082       
00083       _systems.erase (pos);
00084     }
00085 }
00086 
00087 
00088 
00089 void EquationSystems::init ()
00090 {
00091   const unsigned int n_sys = this->n_systems();
00092 
00093   libmesh_assert (n_sys != 0);
00094 
00095   // Distribute the mesh if possible
00096   if (libMesh::n_processors() > 1)
00097     _mesh.delete_remote_elements();
00098   
00099   // Tell all the \p DofObject entities how many systems
00100   // there are.
00101   {
00102     MeshBase::node_iterator       node_it  = _mesh.nodes_begin();
00103     const MeshBase::node_iterator node_end = _mesh.nodes_end();
00104 
00105     for ( ; node_it != node_end; ++node_it)
00106       (*node_it)->set_n_systems(n_sys);
00107     
00108     MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00109     const MeshBase::element_iterator elem_end = _mesh.elements_end();
00110     
00111     for ( ; elem_it != elem_end; ++elem_it)
00112       (*elem_it)->set_n_systems(n_sys);
00113   }
00114 
00115   for (unsigned int i=0; i != this->n_systems(); ++i)
00116     this->get_system(i).init();
00117 }
00118 
00119 
00120 
00121 void EquationSystems::reinit ()
00122 {
00123   libmesh_assert (this->n_systems() != 0);
00124   
00125 #ifdef DEBUG
00126   // Make sure all the \p DofObject entities know how many systems
00127   // there are.
00128   {
00129     // All the nodes
00130     MeshBase::node_iterator       node_it  = _mesh.nodes_begin();
00131     const MeshBase::node_iterator node_end = _mesh.nodes_end();
00132 
00133     for ( ; node_it != node_end; ++node_it)
00134       libmesh_assert((*node_it)->n_systems() == this->n_systems());
00135     
00136     // All the elements
00137     MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00138     const MeshBase::element_iterator elem_end = _mesh.elements_end();
00139     
00140     for ( ; elem_it != elem_end; ++elem_it)
00141       libmesh_assert((*elem_it)->n_systems() == this->n_systems());
00142   }
00143 #endif
00144 
00145   // Localize each system's vectors
00146   for (unsigned int i=0; i != this->n_systems(); ++i)
00147     this->get_system(i).re_update();
00148 
00149 #ifdef LIBMESH_ENABLE_AMR
00150 
00151   bool dof_constraints_created = false;
00152   bool mesh_changed = false;
00153 
00154   // FIXME: For backwards compatibility, assume
00155   // refine_and_coarsen_elements or refine_uniformly have already
00156   // been called
00157   {
00158     for (unsigned int i=0; i != this->n_systems(); ++i)
00159       {
00160         System &sys = this->get_system(i);
00161 
00162         // Don't do anything if the system doesn't have any variables in it
00163         if(!sys.n_vars())
00164           continue;
00165         
00166         sys.get_dof_map().distribute_dofs(_mesh);
00167 
00168         // Recreate any hanging node constraints
00169         sys.get_dof_map().create_dof_constraints(_mesh);
00170 
00171         // Apply any user-defined constraints
00172         sys.user_constrain();
00173 
00174         // Expand any recursive constraints
00175         sys.get_dof_map().process_constraints();
00176 
00177         // And clean up the send_list before we use it again
00178         sys.get_dof_map().prepare_send_list();
00179 
00180         sys.prolong_vectors();
00181       }
00182     mesh_changed = true;
00183     dof_constraints_created = true;
00184   }
00185   
00186   // FIXME: Where should the user set maintain_level_one now??
00187   // Don't override previous settings, for now
00188 
00189   MeshRefinement mesh_refine(_mesh);
00190 
00191   mesh_refine.face_level_mismatch_limit() = false;
00192 
00193   // Try to coarsen the mesh, then restrict each system's vectors
00194   // if necessary
00195   if (mesh_refine.coarsen_elements())
00196     {
00197       for (unsigned int i=0; i != this->n_systems(); ++i)
00198         {
00199           System &sys = this->get_system(i);
00200           if (!dof_constraints_created)
00201             {
00202               sys.get_dof_map().distribute_dofs(_mesh);
00203               sys.get_dof_map().create_dof_constraints(_mesh);
00204               sys.user_constrain();
00205               sys.get_dof_map().process_constraints();
00206               sys.get_dof_map().prepare_send_list();
00207 
00208             }
00209           sys.restrict_vectors();
00210         }
00211       mesh_changed = true;
00212       dof_constraints_created = true;
00213     }
00214 
00215   // Once vectors are all restricted, we can delete
00216   // children of coarsened elements
00217   if (mesh_changed)
00218     this->get_mesh().contract();
00219   
00220   // Try to refine the mesh, then prolong each system's vectors
00221   // if necessary
00222   if (mesh_refine.refine_elements())
00223     {
00224       for (unsigned int i=0; i != this->n_systems(); ++i)
00225         {
00226           System &sys = this->get_system(i);
00227           if (!dof_constraints_created)
00228             {
00229               sys.get_dof_map().distribute_dofs(_mesh);
00230               sys.get_dof_map().create_dof_constraints(_mesh);
00231               sys.user_constrain();
00232               sys.get_dof_map().process_constraints();
00233               sys.get_dof_map().prepare_send_list();
00234 
00235             }
00236           sys.prolong_vectors();
00237         }
00238       mesh_changed = true;
00239       dof_constraints_created = true;
00240     }
00241 
00242   // If the mesh has changed, systems will need to create new dof
00243   // constraints and update their global solution vectors
00244   if (mesh_changed)
00245     {
00246       for (unsigned int i=0; i != this->n_systems(); ++i)
00247         this->get_system(i).reinit();
00248     }
00249 #endif // #ifdef LIBMESH_ENABLE_AMR
00250 }
00251 
00252 
00253 
00254 void EquationSystems::allgather ()
00255 {
00256   // A serial mesh means nothing needs to be done
00257   if (_mesh.is_serial())
00258     return;
00259 
00260   const unsigned int n_sys = this->n_systems();
00261 
00262   libmesh_assert (n_sys != 0);
00263 
00264   // Gather the mesh
00265   _mesh.allgather();
00266   
00267   // Tell all the \p DofObject entities how many systems
00268   // there are.
00269   {
00270     MeshBase::node_iterator       node_it  = _mesh.nodes_begin();
00271     const MeshBase::node_iterator node_end = _mesh.nodes_end();
00272 
00273     for ( ; node_it != node_end; ++node_it)
00274       (*node_it)->set_n_systems(n_sys);
00275     
00276     MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00277     const MeshBase::element_iterator elem_end = _mesh.elements_end();
00278     
00279     for ( ; elem_it != elem_end; ++elem_it)
00280       (*elem_it)->set_n_systems(n_sys);
00281   }
00282 
00283   // And distribute each system's dofs
00284   for (unsigned int i=0; i != this->n_systems(); ++i)
00285     this->get_system(i).get_dof_map().distribute_dofs(_mesh);
00286 }
00287 
00288 
00289 
00290 
00291 void EquationSystems::update ()
00292 {
00293   START_LOG("update()","EquationSystems");
00294   
00295   // Localize each system's vectors
00296   for (unsigned int i=0; i != this->n_systems(); ++i)
00297     this->get_system(i).update();
00298   
00299   STOP_LOG("update()","EquationSystems");
00300 }
00301 
00302 
00303 
00304 System & EquationSystems::add_system (const std::string& sys_type,
00305                                       const std::string& name)
00306 {
00307   // Build a Newmark system
00308   if      (sys_type == "Newmark")
00309     this->add_system<NewmarkSystem> (name);
00310 
00311   // Build an Explicit system
00312   else if ((sys_type == "Explicit"))
00313     this->add_system<ExplicitSystem> (name);
00314 
00315   // Build an Implicit system
00316   else if ((sys_type == "Implicit") ||
00317            (sys_type == "Steady"  ))
00318     this->add_system<ImplicitSystem> (name);
00319 
00320   // build a transient implicit linear system
00321   else if ((sys_type == "Transient") ||
00322            (sys_type == "TransientImplicit") ||
00323            (sys_type == "TransientLinearImplicit"))
00324     this->add_system<TransientLinearImplicitSystem> (name);
00325 
00326   // build a transient implicit nonlinear system
00327   else if (sys_type == "TransientNonlinearImplicit")
00328     this->add_system<TransientNonlinearImplicitSystem> (name);
00329 
00330   // build a transient explicit system
00331   else if (sys_type == "TransientExplicit")
00332     this->add_system<TransientExplicitSystem> (name);
00333 
00334   // build a linear implicit system
00335   else if (sys_type == "LinearImplicit")
00336     this->add_system<LinearImplicitSystem> (name);
00337 
00338   // build a nonlinear implicit system
00339   else if (sys_type == "NonlinearImplicit")
00340     this->add_system<NonlinearImplicitSystem> (name);
00341 
00342 #if defined(LIBMESH_USE_COMPLEX_NUMBERS)
00343   // build a frequency system
00344   else if (sys_type == "Frequency")
00345     this->add_system<FrequencySystem> (name);
00346 #endif
00347 
00348   else
00349     {
00350       std::cerr << "ERROR: Unknown system type: "
00351                 << sys_type
00352                 << std::endl;
00353       libmesh_error();
00354     }
00355 
00356   // Return a reference to the new system
00357   //return (*this)(name);
00358   return this->get_system(name);
00359 }
00360 
00361 
00362 
00363 
00364 
00365 
00366 void EquationSystems::delete_system (const std::string& name)
00367 {
00368   libmesh_deprecated();
00369 
00370   if (!_systems.count(name))
00371     {
00372       std::cerr << "ERROR: no system named "
00373                 << name  << std::endl;
00374 
00375       libmesh_error();
00376     }
00377   
00378   delete _systems[name];
00379   
00380   _systems.erase (name);
00381 }
00382 
00383 
00384 
00385 void EquationSystems::solve ()
00386 {
00387   libmesh_assert (this->n_systems());
00388 
00389   for (unsigned int i=0; i != this->n_systems(); ++i)
00390     this->get_system(i).solve();
00391 }
00392 
00393 
00394  
00395 void EquationSystems::sensitivity_solve (const ParameterVector& parameters)
00396 {
00397   libmesh_assert (this->n_systems());
00398 
00399   for (unsigned int i=0; i != this->n_systems(); ++i)
00400     this->get_system(i).sensitivity_solve(parameters);
00401 }
00402  
00403 
00404  
00405 void EquationSystems::adjoint_solve (const QoISet& qoi_indices)
00406 {
00407   libmesh_assert (this->n_systems());
00408 
00409   for (unsigned int i=this->n_systems(); i != 0; --i)
00410     this->get_system(i-1).adjoint_solve(qoi_indices);
00411 }
00412  
00413 
00414  
00415 void EquationSystems::build_variable_names (std::vector<std::string>& var_names) const
00416 {
00417   libmesh_assert (this->n_systems());
00418   
00419   var_names.resize (this->n_vars());
00420 
00421   unsigned int var_num=0;
00422   
00423   const_system_iterator       pos = _systems.begin();
00424   const const_system_iterator end = _systems.end();
00425 
00426   for (; pos != end; ++pos)
00427     for (unsigned int vn=0; vn<pos->second->n_vars(); vn++)
00428       var_names[var_num++] = pos->second->variable_name(vn);       
00429 }
00430 
00431 
00432 
00433 void EquationSystems::build_solution_vector (std::vector<Number>&,
00434                                              const std::string&,
00435                                              const std::string&) const
00436 {
00437   //TODO:[BSK] re-implement this from the method below
00438   libmesh_error();
00439 
00440 //   // Get a reference to the named system
00441 //   const System& system = this->get_system(system_name);
00442 
00443 //   // Get the number associated with the variable_name we are passed
00444 //   const unsigned short int variable_num = system.variable_number(variable_name);
00445 
00446 //   // Get the dimension of the current mesh
00447 //   const unsigned int dim = _mesh.mesh_dimension();
00448 
00449 //   // If we're on processor 0, allocate enough memory to hold the solution.
00450 //   // Since we're only looking at one variable, there will be one solution value
00451 //   // for each node in the mesh.
00452 //   if (_mesh.processor_id() == 0)
00453 //     soln.resize(_mesh.n_nodes());
00454 
00455 //   // Vector to hold the global solution from all processors
00456 //   std::vector<Number> sys_soln;
00457   
00458 //   // Update the global solution from all processors
00459 //   system.update_global_solution (sys_soln, 0);
00460   
00461 //   // Temporary vector to store the solution on an individual element.
00462 //   std::vector<Number>       elem_soln;   
00463 
00464 //   // The FE solution interpolated to the nodes
00465 //   std::vector<Number>       nodal_soln;  
00466 
00467 //   // The DOF indices for the element
00468 //   std::vector<unsigned int> dof_indices; 
00469 
00470 //   // Determine the finite/infinite element type used in this system 
00471 //   const FEType& fe_type    = system.variable_type(variable_num);
00472 
00473 //   // Define iterators to iterate over all the elements of the mesh
00474 //   const_active_elem_iterator       it (_mesh.elements_begin());
00475 //   const const_active_elem_iterator end(_mesh.elements_end());
00476 
00477 //   // Loop over elements
00478 //   for ( ; it != end; ++it)
00479 //     {
00480 //       // Convenient shortcut to the element pointer
00481 //       const Elem* elem = *it;
00482 
00483 //       // Fill the dof_indices vector for this variable
00484 //       system.get_dof_map().dof_indices(elem,
00485 //                                     dof_indices,
00486 //                                     variable_num);
00487 
00488 //       // Resize the element solution vector to fit the
00489 //       // dof_indices for this element.
00490 //       elem_soln.resize(dof_indices.size());
00491 
00492 //       // Transfer the system solution to the element
00493 //       // solution by mapping it through the dof_indices vector.
00494 //       for (unsigned int i=0; i<dof_indices.size(); i++)
00495 //      elem_soln[i] = sys_soln[dof_indices[i]];
00496 
00497 //       // Using the FE interface, compute the nodal_soln
00498 //       // for the current elemnt type given the elem_soln
00499 //       FEInterface::nodal_soln (dim,
00500 //                             fe_type,
00501 //                             elem,
00502 //                             elem_soln,
00503 //                             nodal_soln);
00504 
00505 //       // Sanity check -- make sure that there are the same number
00506 //       // of entries in the nodal_soln as there are nodes in the
00507 //       // element!
00508 //       libmesh_assert (nodal_soln.size() == elem->n_nodes());
00509 
00510 //       // Copy the nodal solution over into the correct place in
00511 //       // the global soln vector which will be returned to the user.
00512 //       for (unsigned int n=0; n<elem->n_nodes(); n++)
00513 //      soln[elem->node(n)] = nodal_soln[n];
00514 //     }
00515 }
00516 
00517 
00518 
00519 
00520 void EquationSystems::build_solution_vector (std::vector<Number>& soln) const
00521 {
00522   // This function must be run on all processors at once
00523   parallel_only();
00524 
00525   libmesh_assert (this->n_systems());
00526 
00527   const unsigned int dim = _mesh.mesh_dimension();
00528   const unsigned int nn  = _mesh.n_nodes();
00529   const unsigned int nv  = this->n_vars();
00530   const unsigned short int one = 1;
00531 
00532   // We'd better have a contiguous node numbering
00533   libmesh_assert (nn == _mesh.max_node_id());
00534 
00535   // allocate storage to hold
00536   // (number_of_nodes)*(number_of_variables) entries.
00537   soln.resize(nn*nv);
00538   
00539   // Zero out the soln vector
00540   std::fill (soln.begin(), soln.end(), libMesh::zero);
00541 
00542   std::vector<Number>  sys_soln;
00543 
00544   // (Note that we use an unsigned short int here even though an
00545   // unsigned char would be more that sufficient.  The MPI 1.1
00546   // standard does not require that MPI_SUM, MPI_PROD etc... be
00547   // implemented for char data types. 12/23/2003 - BSK)  
00548   std::vector<unsigned short int> node_conn(nn), repeat_count(nn);
00549 
00550   // Get the number of elements that share each node.  We will
00551   // compute the average value at each node.  This is particularly
00552   // useful for plotting discontinuous data.
00553   MeshBase::element_iterator       e_it  = _mesh.active_local_elements_begin();
00554   const MeshBase::element_iterator e_end = _mesh.active_local_elements_end(); 
00555 
00556   for ( ; e_it != e_end; ++e_it)
00557     for (unsigned int n=0; n<(*e_it)->n_nodes(); n++)
00558       node_conn[(*e_it)->node(n)]++;
00559 
00560   // Gather the distributed node_conn arrays in the case of
00561   // multiple processors.
00562   Parallel::sum(node_conn);
00563 
00564   unsigned int var_num=0;
00565 
00566   // For each system in this EquationSystems object,
00567   // update the global solution and if we are on processor 0,
00568   // loop over the elements and build the nodal solution
00569   // from the element solution.  Then insert this nodal solution
00570   // into the vector passed to build_solution_vector.
00571   const_system_iterator       pos = _systems.begin();
00572   const const_system_iterator end = _systems.end();
00573   
00574   for (; pos != end; ++pos)
00575     {  
00576       const System& system  = *(pos->second);
00577       const unsigned int nv_sys = system.n_vars();
00578       
00579       system.update_global_solution (sys_soln);
00580       
00581       std::vector<Number>       elem_soln;   // The finite element solution
00582       std::vector<Number>       nodal_soln;  // The FE solution interpolated to the nodes
00583       std::vector<unsigned int> dof_indices; // The DOF indices for the finite element 
00584       
00585       for (unsigned int var=0; var<nv_sys; var++)
00586         {
00587           const FEType& fe_type                   = system.variable_type(var);
00588           const System::Variable &var_description = system.variable(var);
00589           const DofMap &dof_map                   = system.get_dof_map();
00590 
00591           std::fill (repeat_count.begin(), repeat_count.end(), 0);
00592 
00593           MeshBase::element_iterator       it  = _mesh.active_local_elements_begin();
00594           const MeshBase::element_iterator end = _mesh.active_local_elements_end(); 
00595 
00596           for ( ; it != end; ++it)
00597             if (var_description.active_on_subdomain((*it)->subdomain_id()))
00598               {
00599                 const Elem* elem = *it;      
00600 
00601                 dof_map.dof_indices (elem, dof_indices, var);
00602               
00603                 elem_soln.resize(dof_indices.size());
00604               
00605                 for (unsigned int i=0; i<dof_indices.size(); i++)
00606                   elem_soln[i] = sys_soln[dof_indices[i]];
00607                   
00608                 FEInterface::nodal_soln (dim,
00609                                          fe_type,
00610                                          elem,
00611                                          elem_soln,
00612                                          nodal_soln);
00613 
00614 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00615                 // infinite elements should be skipped...
00616                 if (!elem->infinite())
00617 #endif
00618                   { 
00619                     libmesh_assert (nodal_soln.size() == elem->n_nodes());
00620                   
00621                     for (unsigned int n=0; n<elem->n_nodes(); n++)
00622                       {
00623                         repeat_count[elem->node(n)]++;
00624                         soln[nv*(elem->node(n)) + (var + var_num)] += nodal_soln[n];
00625                       }
00626                   }
00627               } // end loop over elements        
00628 
00629           // when a variable is active everywhere the repeat_count
00630           // and node_conn arrays should be identical, so let's
00631           // use that information to avoid unnecessary communication
00632           if (var_description.implicitly_active())
00633             repeat_count = node_conn;
00634             
00635           else
00636             Parallel::sum (repeat_count);
00637 
00638           for (unsigned int n=0; n<nn; n++)
00639             soln[nv*n + (var + var_num)] /= 
00640               static_cast<Real>(std::max (repeat_count[n], one));
00641           
00642       
00643         } // end loop on variables in this system
00644   
00645       var_num += nv_sys;
00646     } // end loop over systems
00647 
00648   // Now each processor has computed contriburions to the
00649   // soln vector.  Gather them all up.
00650   Parallel::sum(soln);
00651 }
00652 
00653 
00654 
00655 
00656 void EquationSystems::build_discontinuous_solution_vector (std::vector<Number>& soln) const
00657 {
00658   libmesh_assert (this->n_systems());
00659 
00660   const unsigned int dim = _mesh.mesh_dimension();
00661   const unsigned int nv  = this->n_vars();
00662   unsigned int tw=0;
00663 
00664   // get the total weight
00665   {
00666     MeshBase::element_iterator       it  = _mesh.active_elements_begin();
00667     const MeshBase::element_iterator end = _mesh.active_elements_end(); 
00668 
00669     for ( ; it != end; ++it)
00670       tw += (*it)->n_nodes();
00671   }
00672   
00673 
00674   // Only if we are on processor zero, allocate the storage
00675   // to hold (number_of_nodes)*(number_of_variables) entries.
00676   if (_mesh.processor_id() == 0)
00677     soln.resize(tw*nv);
00678 
00679   std::vector<Number> sys_soln; 
00680 
00681   
00682   unsigned int var_num=0;
00683 
00684   // For each system in this EquationSystems object,
00685   // update the global solution and if we are on processor 0,
00686   // loop over the elements and build the nodal solution
00687   // from the element solution.  Then insert this nodal solution
00688   // into the vector passed to build_solution_vector.
00689   const_system_iterator       pos = _systems.begin();
00690   const const_system_iterator end = _systems.end();
00691 
00692   for (; pos != end; ++pos)
00693     {  
00694       const System& system  = *(pos->second);
00695       const unsigned int nv_sys = system.n_vars();
00696       
00697       system.update_global_solution (sys_soln, 0);
00698       
00699       if (_mesh.processor_id() == 0)
00700         {
00701           std::vector<Number>       elem_soln;   // The finite element solution
00702           std::vector<Number>       nodal_soln;  // The FE solution interpolated to the nodes
00703           std::vector<unsigned int> dof_indices; // The DOF indices for the finite element 
00704               
00705           for (unsigned int var=0; var<nv_sys; var++)
00706             {
00707               const FEType& fe_type    = system.variable_type(var);
00708 
00709               MeshBase::element_iterator       it  = _mesh.active_elements_begin();
00710               const MeshBase::element_iterator end = _mesh.active_elements_end(); 
00711 
00712               unsigned int nn=0;
00713               
00714               for ( ; it != end; ++it)
00715                 {
00716                   const Elem* elem = *it;
00717                   system.get_dof_map().dof_indices (elem, dof_indices, var);
00718                   
00719                   elem_soln.resize(dof_indices.size());
00720                   
00721                   for (unsigned int i=0; i<dof_indices.size(); i++)
00722                     elem_soln[i] = sys_soln[dof_indices[i]];
00723                   
00724                   FEInterface::nodal_soln (dim,
00725                                            fe_type,
00726                                            elem,
00727                                            elem_soln,
00728                                            nodal_soln);
00729 
00730 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00731                   // infinite elements should be skipped...
00732                   if (!elem->infinite())
00733 #endif
00734                     { 
00735                       libmesh_assert (nodal_soln.size() == elem->n_nodes());
00736                   
00737                       for (unsigned int n=0; n<elem->n_nodes(); n++)
00738                         {
00739                           soln[nv*(nn++) + (var + var_num)] +=
00740                             nodal_soln[n];
00741                         }
00742                     }
00743                 }
00744             }    
00745         }
00746 
00747       var_num += nv_sys;
00748     }
00749 }
00750 
00751 
00752 
00753 bool EquationSystems::compare (const EquationSystems& other_es, 
00754                                const Real threshold,
00755                                const bool verbose) const
00756 {
00757   // safety check, whether we handle at least the same number
00758   // of systems
00759   std::vector<bool> os_result;
00760 
00761   if (this->n_systems() != other_es.n_systems())
00762     {
00763       if (verbose)
00764         {
00765           std::cout << "  Fatal difference. This system handles " 
00766                     << this->n_systems() << " systems," << std::endl
00767                     << "  while the other system handles "
00768                     << other_es.n_systems() 
00769                     << " systems." << std::endl
00770                     << "  Aborting comparison." << std::endl;
00771         }
00772       return false;
00773     }
00774   else
00775     {
00776       // start comparing each system      
00777       const_system_iterator       pos = _systems.begin();
00778       const const_system_iterator end = _systems.end();
00779 
00780       for (; pos != end; ++pos)
00781         {
00782           const std::string& sys_name = pos->first;
00783           const System&  system        = *(pos->second);
00784       
00785           // get the other system
00786           const System& other_system   = other_es.get_system (sys_name);
00787 
00788           os_result.push_back (system.compare (other_system, threshold, verbose));
00789 
00790         }
00791 
00792     }
00793   
00794 
00795   // sum up the results
00796   if (os_result.size()==0)
00797     return true;
00798   else
00799     {
00800       bool os_identical;
00801       unsigned int n = 0;
00802           do
00803             {
00804               os_identical = os_result[n];
00805               n++;
00806             }
00807           while (os_identical && n<os_result.size());
00808           return os_identical;
00809         }
00810 }
00811 
00812 
00813 
00814 std::string EquationSystems::get_info () const
00815 {
00816   std::ostringstream out;
00817   
00818   out << " EquationSystems\n"
00819       << "  n_systems()=" << this->n_systems() << '\n';
00820 
00821   // Print the info for the individual systems
00822   const_system_iterator       pos = _systems.begin();
00823   const const_system_iterator end = _systems.end();
00824 
00825   for (; pos != end; ++pos)
00826     out << pos->second->get_info();
00827 
00828   
00829 //   // Possibly print the parameters  
00830 //   if (!this->parameters.empty())
00831 //     {  
00832 //       out << "  n_parameters()=" << this->n_parameters() << '\n';
00833 //       out << "   Parameters:\n";
00834       
00835 //       for (std::map<std::string, Real>::const_iterator
00836 //           param = _parameters.begin(); param != _parameters.end();
00837 //         ++param)
00838 //      out << "    "
00839 //          << "\""
00840 //          << param->first
00841 //          << "\""
00842 //          << "="
00843 //          << param->second
00844 //          << '\n';
00845 //     }
00846   
00847   return out.str();
00848 }
00849 
00850 
00851 
00852 void EquationSystems::print_info (std::ostream& os) const
00853 {
00854   os << this->get_info()
00855      << std::endl;
00856 }
00857 
00858 
00859 
00860 std::ostream& operator << (std::ostream& os, const EquationSystems& es)
00861 {
00862   es.print_info(os);
00863   return os;
00864 }
00865 
00866 
00867 
00868 unsigned int EquationSystems::n_vars () const
00869 {
00870   unsigned int tot=0;
00871   
00872   const_system_iterator       pos = _systems.begin();
00873   const const_system_iterator end = _systems.end();
00874 
00875   for (; pos != end; ++pos)
00876     tot += pos->second->n_vars();
00877 
00878   return tot;
00879 }
00880 
00881 
00882 
00883 unsigned int EquationSystems::n_dofs () const
00884 {
00885   unsigned int tot=0;
00886 
00887   const_system_iterator       pos = _systems.begin();
00888   const const_system_iterator end = _systems.end();
00889 
00890   for (; pos != end; ++pos)
00891     tot += pos->second->n_dofs();
00892 
00893   return tot;      
00894 }
00895 
00896 
00897 
00898 
00899 unsigned int EquationSystems::n_active_dofs () const
00900 {
00901   unsigned int tot=0;
00902 
00903   const_system_iterator       pos = _systems.begin();
00904   const const_system_iterator end = _systems.end();
00905 
00906   for (; pos != end; ++pos)
00907     tot += pos->second->n_active_dofs();
00908 
00909   return tot;      
00910 }
00911 
00912 
00913 void EquationSystems::_add_system_to_nodes_and_elems()
00914 {
00915   // All the nodes
00916   MeshBase::node_iterator       node_it  = _mesh.nodes_begin();
00917   const MeshBase::node_iterator node_end = _mesh.nodes_end();
00918  
00919   for ( ; node_it != node_end; ++node_it)
00920     (*node_it)->add_system();
00921  
00922   // All the elements
00923   MeshBase::element_iterator       elem_it  = _mesh.elements_begin();
00924   const MeshBase::element_iterator elem_end = _mesh.elements_end();
00925  
00926   for ( ; elem_it != elem_end; ++elem_it)
00927     (*elem_it)->add_system();
00928 }

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

Hosted By:
SourceForge.net Logo