00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sstream>
00024
00025
00026
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
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
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
00076
00077
00078 _init_system = _assemble_system = NULL;
00079
00080
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
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
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
00161 this->init_data();
00162
00163
00164
00165 if(!this->n_vars())
00166 return;
00167
00168
00169 this->user_initialization();
00170 }
00171
00172
00173
00174 void System::init_data ()
00175 {
00176 MeshBase &mesh = this->get_mesh();
00177
00178
00179 _dof_map->distribute_dofs (mesh);
00180
00181 #ifdef LIBMESH_ENABLE_AMR
00182
00183
00184 _dof_map->create_dof_constraints(mesh);
00185
00186
00187 this->user_constrain();
00188
00189
00190 _dof_map->process_constraints();
00191
00192
00193 _dof_map->prepare_send_list();
00194
00195 #endif
00196
00197
00198 solution->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
00199
00200
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
00210 _can_add_vectors = false;
00211
00212
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
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
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
00259 this->restrict_vectors();
00260 #endif
00261 }
00262
00263
00264
00265 void System::reinit ()
00266 {
00267 #ifdef LIBMESH_ENABLE_AMR
00268
00269
00270 if(!this->n_vars())
00271 return;
00272
00273
00274
00275
00276
00277
00278 solution->init (this->n_dofs(), this->n_local_dofs(), true, PARALLEL);
00279
00280 libmesh_assert (solution->size() == current_local_solution->size());
00281
00282
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
00300 libmesh_assert (current_local_solution->size() == solution->size());
00301
00302
00303 libmesh_assert (send_list.size() <= solution->size());
00304
00305
00306
00307
00308
00309 solution->localize (*current_local_solution, send_list);
00310 }
00311
00312
00313
00314 void System::re_update ()
00315 {
00316
00317
00318
00319 if(!this->n_vars())
00320 return;
00321
00322
00323 std::vector<unsigned int> send_list(solution->size());
00324 Utility::iota (send_list.begin(), send_list.end(), 0);
00325
00326
00327 libmesh_assert (current_local_solution->size() == solution->size());
00328
00329
00330 libmesh_assert (!send_list.empty());
00331 libmesh_assert (send_list.size() <= solution->size());
00332
00333
00334
00335 solution->localize (*current_local_solution, send_list);
00336 }
00337
00338
00339
00340 void System::assemble ()
00341 {
00342
00343 START_LOG("assemble()", "System");
00344
00345
00346 this->user_assembly();
00347
00348
00349 STOP_LOG("assemble()", "System");
00350 }
00351
00352
00353
00354 void System::assemble_qoi (const QoISet& qoi_indices)
00355 {
00356
00357 START_LOG("assemble_qoi()", "System");
00358
00359
00360 this->user_QOI(qoi_indices);
00361
00362
00363 STOP_LOG("assemble_qoi()", "System");
00364 }
00365
00366
00367
00368 void System::assemble_qoi_derivative (const QoISet& qoi_indices)
00369 {
00370
00371 START_LOG("assemble_qoi_derivative()", "System");
00372
00373
00374 this->user_QOI_derivative(qoi_indices);
00375
00376
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
00388 if (qoi_indices.size(*this) > parameters.size())
00389 forward_qoi_parameter_sensitivity(qoi_indices, parameters, sensitivities);
00390
00391
00392
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
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
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
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
00441
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
00460 ov_result.clear ();
00461 }
00462 else
00463 {
00464
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
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 }
00491
00492
00493 bool overall_result;
00494
00495
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
00553 if (this->have_vector(vec_name))
00554 return *(_vectors[vec_name]);
00555
00556
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
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
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
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
00889
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
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
00915 _dof_map->add_variable (_variables.back());
00916
00917
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
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
00965 var_indices.clear();
00966
00967 std::vector<unsigned int> dof_indices;
00968
00969
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
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
00998 libmesh_assert(var_num<this->n_vars());
00999
01000
01001 const MeshBase& mesh = this->get_mesh();
01002
01003
01004 const unsigned int sys_num = this->number();
01005
01006
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
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
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
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
01081 parallel_only();
01082
01083 START_LOG ("calculate_norm()", "System");
01084
01085
01086 Real v_norm = 0.;
01087
01088 if (norm.is_discrete())
01089 {
01090 STOP_LOG ("calculate_norm()", "System");
01091
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
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
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
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
01132 for (unsigned int var=0; var != this->n_vars(); ++var)
01133 {
01134
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
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
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
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
01361
01362 if (_init_system != NULL)
01363 this->_init_system (_equation_systems, this->name());
01364 }
01365
01366
01367 void System::user_assembly ()
01368 {
01369
01370
01371 if (_assemble_system != NULL)
01372 this->_assemble_system (_equation_systems, this->name());
01373 }
01374
01375
01376
01377 void System::user_constrain ()
01378 {
01379
01380
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
01390
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
01400
01401 if(_qoi_evaluate_derivative != NULL)
01402 this->_qoi_evaluate_derivative(_equation_systems, this->name(), qoi_indices);
01403 }