equation_systems.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sstream>
00023
00024
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
00040
00041 #include "equation_systems.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050 EquationSystems::EquationSystems (MeshBase& m, MeshData* mesh_data) :
00051 _mesh (m),
00052 _mesh_data (mesh_data)
00053 {
00054
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
00071 parameters.clear ();
00072
00073
00074
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
00096 if (libMesh::n_processors() > 1)
00097 _mesh.delete_remote_elements();
00098
00099
00100
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
00127
00128 {
00129
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
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
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
00155
00156
00157 {
00158 for (unsigned int i=0; i != this->n_systems(); ++i)
00159 {
00160 System &sys = this->get_system(i);
00161
00162
00163 if(!sys.n_vars())
00164 continue;
00165
00166 sys.get_dof_map().distribute_dofs(_mesh);
00167
00168
00169 sys.get_dof_map().create_dof_constraints(_mesh);
00170
00171
00172 sys.user_constrain();
00173
00174
00175 sys.get_dof_map().process_constraints();
00176
00177
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
00187
00188
00189 MeshRefinement mesh_refine(_mesh);
00190
00191 mesh_refine.face_level_mismatch_limit() = false;
00192
00193
00194
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
00216
00217 if (mesh_changed)
00218 this->get_mesh().contract();
00219
00220
00221
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
00243
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
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
00265 _mesh.allgather();
00266
00267
00268
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
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
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
00308 if (sys_type == "Newmark")
00309 this->add_system<NewmarkSystem> (name);
00310
00311
00312 else if ((sys_type == "Explicit"))
00313 this->add_system<ExplicitSystem> (name);
00314
00315
00316 else if ((sys_type == "Implicit") ||
00317 (sys_type == "Steady" ))
00318 this->add_system<ImplicitSystem> (name);
00319
00320
00321 else if ((sys_type == "Transient") ||
00322 (sys_type == "TransientImplicit") ||
00323 (sys_type == "TransientLinearImplicit"))
00324 this->add_system<TransientLinearImplicitSystem> (name);
00325
00326
00327 else if (sys_type == "TransientNonlinearImplicit")
00328 this->add_system<TransientNonlinearImplicitSystem> (name);
00329
00330
00331 else if (sys_type == "TransientExplicit")
00332 this->add_system<TransientExplicitSystem> (name);
00333
00334
00335 else if (sys_type == "LinearImplicit")
00336 this->add_system<LinearImplicitSystem> (name);
00337
00338
00339 else if (sys_type == "NonlinearImplicit")
00340 this->add_system<NonlinearImplicitSystem> (name);
00341
00342 #if defined(LIBMESH_USE_COMPLEX_NUMBERS)
00343
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
00357
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
00438 libmesh_error();
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 }
00516
00517
00518
00519
00520 void EquationSystems::build_solution_vector (std::vector<Number>& soln) const
00521 {
00522
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
00533 libmesh_assert (nn == _mesh.max_node_id());
00534
00535
00536
00537 soln.resize(nn*nv);
00538
00539
00540 std::fill (soln.begin(), soln.end(), libMesh::zero);
00541
00542 std::vector<Number> sys_soln;
00543
00544
00545
00546
00547
00548 std::vector<unsigned short int> node_conn(nn), repeat_count(nn);
00549
00550
00551
00552
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
00561
00562 Parallel::sum(node_conn);
00563
00564 unsigned int var_num=0;
00565
00566
00567
00568
00569
00570
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;
00582 std::vector<Number> nodal_soln;
00583 std::vector<unsigned int> dof_indices;
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
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 }
00628
00629
00630
00631
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 }
00644
00645 var_num += nv_sys;
00646 }
00647
00648
00649
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
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
00675
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
00685
00686
00687
00688
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;
00702 std::vector<Number> nodal_soln;
00703 std::vector<unsigned int> dof_indices;
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
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
00758
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
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
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
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
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
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
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
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
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 }