20#include "libmesh/default_coupling.h"
21#include "libmesh/dof_map.h"
22#include "libmesh/eigen_system.h"
23#include "libmesh/elem.h"
24#include "libmesh/explicit_system.h"
25#include "libmesh/fe_interface.h"
26#include "libmesh/frequency_system.h"
27#include "libmesh/int_range.h"
28#include "libmesh/libmesh_logging.h"
29#include "libmesh/linear_implicit_system.h"
30#include "libmesh/mesh_base.h"
31#include "libmesh/mesh_refinement.h"
32#include "libmesh/newmark_system.h"
33#include "libmesh/nonlinear_implicit_system.h"
34#include "libmesh/parallel.h"
35#include "libmesh/rb_construction.h"
36#include "libmesh/remote_elem.h"
37#include "libmesh/transient_rb_construction.h"
38#include "libmesh/transient_system.h"
47#include "libmesh/equation_systems.h"
55 _refine_in_reinit(true),
56 _enable_default_ghosting(true)
60 this->
parameters.
set<
unsigned int>(
"linear solver maximum iterations") = 5000;
104 const unsigned int n_sys = this->
n_systems();
106 libmesh_assert_not_equal_to (n_sys, 0);
110 for (
auto & node :
_mesh.node_ptr_range())
111 node->set_n_systems(n_sys);
117 for (Elem * elem : range)
118 elem->set_n_systems(n_sys);
124#ifdef LIBMESH_ENABLE_AMR
138 parallel_object_only();
140 const unsigned int n_sys = this->
n_systems();
141 libmesh_assert_not_equal_to (n_sys, 0);
144 for (
unsigned int i=0; i != n_sys; ++i)
157 for (
auto & node :
_mesh.node_ptr_range())
158 node->set_n_systems(n_sys);
165 for (Elem * elem : range)
166 elem->set_n_systems(n_sys);
171 for (
unsigned int i=0; i != n_sys; ++i)
174#ifdef LIBMESH_ENABLE_AMR
176 bool mesh_changed =
false;
182 for (
unsigned int i=0; i != n_sys; ++i)
281 const unsigned int n_sys = this->
n_systems();
283 libmesh_assert_not_equal_to (n_sys, 0);
290 for (
auto & node :
_mesh.node_ptr_range())
291 node->set_n_systems(n_sys);
297 for (Elem * elem : range)
298 elem->set_n_systems(n_sys);
326 mesh.add_ghosting_functor(
mesh.default_ghosting());
328 mesh.remove_ghosting_functor(
mesh.default_ghosting());
344 LOG_SCOPE(
"update()",
"EquationSystems");
354 std::string_view name)
365 else if (sys_type ==
"Basic")
366 this->add_system<System> (name);
369 else if (sys_type ==
"Newmark")
370 this->add_system<NewmarkSystem> (name);
373 else if ((sys_type ==
"Explicit"))
374 this->add_system<ExplicitSystem> (name);
377 else if ((sys_type ==
"Implicit") ||
378 (sys_type ==
"Steady" ))
379 this->add_system<ImplicitSystem> (name);
382 else if ((sys_type ==
"Transient") ||
383 (sys_type ==
"TransientImplicit") ||
384 (sys_type ==
"TransientLinearImplicit"))
385 this->add_system<TransientLinearImplicitSystem> (name);
388 else if (sys_type ==
"TransientNonlinearImplicit")
389 this->add_system<TransientNonlinearImplicitSystem> (name);
392 else if (sys_type ==
"TransientExplicit")
393 this->add_system<TransientExplicitSystem> (name);
396 else if (sys_type ==
"LinearImplicit")
397 this->add_system<LinearImplicitSystem> (name);
400 else if (sys_type ==
"NonlinearImplicit")
401 this->add_system<NonlinearImplicitSystem> (name);
404 else if (sys_type ==
"RBConstruction")
405 this->add_system<RBConstruction> (name);
408 else if (sys_type ==
"TransientRBConstruction")
409 this->add_system<TransientRBConstruction> (name);
411#ifdef LIBMESH_HAVE_SLEPC
413 else if (sys_type ==
"Eigen")
414 this->add_system<EigenSystem> (name);
415 else if (sys_type ==
"TransientEigenSystem")
416 this->add_system<TransientEigenSystem> (name);
419#if defined(LIBMESH_USE_COMPLEX_NUMBERS)
421 else if (sys_type ==
"Frequency")
422 this->add_system<FrequencySystem> (name);
426 libmesh_error_msg(
"ERROR: Unknown system type: " << sys_type);
450 this->
get_system(i).sensitivity_solve(parameters_in);
459 for (
unsigned int i=this->
n_systems(); i != 0; --i)
460 this->
get_system(i-1).adjoint_solve(qoi_indices);
467 const std::set<std::string> * system_names)
const
470 unsigned int var_num = var_names.size();
474 std::unordered_multiset<std::string> seen_names;
480 unsigned int n_scalar_vars = 0;
481 unsigned int n_vector_vars = 0;
483 for (
const auto & [sys_name, sys_ptr] :
_systems)
486 bool use_current_system = (system_names ==
nullptr);
487 if (!use_current_system)
488 use_current_system = system_names->count(sys_name);
489 if (!use_current_system || sys_ptr->hide_output())
492 seen_names.insert(sys_ptr->variable_name(vn));
498 seen_names.insert(sys_ptr->variable_name(vn));
509 unsigned int nv = n_scalar_vars +
dim*n_vector_vars;
513 libmesh_assert_less_equal ( nv, (
dim > 0 ?
dim : 1)*this->
n_vars() );
518 var_names.resize( nv );
521 for (
const auto & [sys_name, sys_ptr] :
_systems)
524 bool use_current_system = (system_names ==
nullptr);
525 if (!use_current_system)
526 use_current_system = system_names->count(sys_name);
527 if (!use_current_system || sys_ptr->hide_output())
532 const std::string & var_name = sys_ptr->variable_name(vn);
533 const FEType & fe_type = sys_ptr->variable_type(vn);
538 if (type ==
nullptr || (type && *type == fe_type))
546 var_names[var_num++] = var_name;
547 libmesh_error_msg_if(seen_names.count(var_name) > 1,
548 "Duplicate variable name "+var_name);
551 var_names[var_num++] = var_name+
"_x";
552 var_names[var_num++] = var_name+
"_y";
553 libmesh_error_msg_if(seen_names.count(var_name+
"_x"),
554 "Duplicate variable name "+var_name+
"_x");
555 libmesh_error_msg_if(seen_names.count(var_name+
"_y"),
556 "Duplicate variable name "+var_name+
"_y");
559 var_names[var_num++] = var_name+
"_x";
560 var_names[var_num++] = var_name+
"_y";
561 var_names[var_num++] = var_name+
"_z";
562 libmesh_error_msg_if(seen_names.count(var_name+
"_x"),
563 "Duplicate variable name "+var_name+
"_x");
564 libmesh_error_msg_if(seen_names.count(var_name+
"_y"),
565 "Duplicate variable name "+var_name+
"_y");
566 libmesh_error_msg_if(seen_names.count(var_name+
"_z"),
567 "Duplicate variable name "+var_name+
"_z");
570 libmesh_error_msg(
"Invalid dim in build_variable_names");
574 var_names[var_num++] = var_name;
579 var_names.resize(var_num);
593 (std::vector<std::string> & var_names,
594 const std::set<std::string> * system_names)
const
596 const std::vector<std::string> name_filter = var_names;
597 const bool is_names_empty = name_filter.empty();
600 const std::vector<std::string> component_suffix = {
"_x",
"_y",
"_z"};
602 libmesh_error_msg_if(
dim > 3,
"Invalid dim in build_elemental_data_variable_names");
604 for (
const auto & [sys_name, sys_ptr] :
_systems)
606 const bool use_current_system = (system_names ==
nullptr) || system_names->count(sys_name);
607 if (!use_current_system || sys_ptr->hide_output())
610 for (
auto var :
make_range(sys_ptr->n_vars()))
612 const FEType & var_type = sys_ptr->variable_type(var);
620 const std::string name =
621 sys_ptr->variable_name(var) + component_suffix[comp];
623 if (is_names_empty ||
624 std::find(name_filter.begin(), name_filter.end(), name) != name_filter.end())
625 var_names.push_back(name);
630 const std::string & name = sys_ptr->variable_name(var);
632 if (is_names_empty ||
633 std::find(name_filter.begin(), name_filter.end(), name) != name_filter.end())
634 var_names.push_back(name);
639 std::sort(var_names.begin(), var_names.end());
646 std::string_view)
const
649 libmesh_not_implemented();
655std::unique_ptr<NumericVector<Number>>
657 bool add_sides)
const
659 LOG_SCOPE(
"build_parallel_solution_vector()",
"EquationSystems");
662 parallel_object_only();
682 unsigned int n_scalar_vars = 0;
683 unsigned int n_vector_vars = 0;
684 for (
const auto & [sys_name, sys_ptr] :
_systems)
687 bool use_current_system = (system_names ==
nullptr);
688 if (!use_current_system)
689 use_current_system = system_names->count(sys_name);
690 if (!use_current_system || sys_ptr->hide_output())
703 nv = n_scalar_vars +
dim*n_vector_vars;
708 (std::distance(
_mesh.local_nodes_begin(),
709 _mesh.local_nodes_end()));
720 const dof_id_type gaps_per_processor = n_gaps / n_proc;
721 const dof_id_type remainder_gaps = n_gaps % n_proc;
723 n_local_nodes = n_local_nodes +
725 (my_pid < remainder_gaps);
730 added_side_nodes = 0;
733 std::vector<dof_id_type> others_added_side_nodes;
737 std::map<std::tuple<dof_id_type, unsigned short, unsigned short>,
745 std::vector<dof_id_type> true_node_offsets;
747 std::vector<dof_id_type> added_node_offsets;
749 auto node_id_to_vec_id =
750 [&true_node_offsets, &added_node_offsets]
753 if (true_node_offsets.empty())
757 const auto lb = std::upper_bound(true_node_offsets.begin(),
758 true_node_offsets.end(), node_id);
762 return node_id + added_node_offsets[p];
767 true_node_offsets.resize(n_proc);
768 added_node_offsets.resize(n_proc);
771 for (
const auto & elem :
_mesh.active_element_ptr_range())
773 for (
auto s : elem->side_index_range())
778 const std::vector<unsigned int> side_nodes =
779 elem->nodes_on_side(s);
782 local_added_side_nodes += side_nodes.size();
786 others_added_side_nodes.resize(n_proc);
788 others_added_side_nodes);
790 added_side_nodes = std::accumulate(others_added_side_nodes.begin(),
791 others_added_side_nodes.end(), 0,
796 true_node_offsets[p+1] += true_node_offsets[p];
801 added_node_offsets[0] = 0;
803 added_node_offsets[p+1] =
804 added_node_offsets[p] + others_added_side_nodes[p];
809 dof_id_type node_counter = true_node_offsets[my_pid];
811 node_counter += others_added_side_nodes[p];
814 for (
const auto & elem :
_mesh.active_local_element_ptr_range())
816 for (
auto s : elem->side_index_range())
821 const std::vector<unsigned int> side_nodes =
822 elem->nodes_on_side(s);
825 discontinuous_node_indices
826 [std::make_tuple(elem->id(),s,n)] = node_counter++;
832 n_global_vals = (max_nn + added_side_nodes) * nv,
833 n_local_vals = (n_local_nodes + local_added_side_nodes) * nv;
838 parallel_soln.
init(n_global_vals, n_local_vals,
false,
PARALLEL);
844 repeat_count.
init(n_global_vals, n_local_vals,
false,
PARALLEL);
846 repeat_count.
close();
848 unsigned int var_num=0;
855 for (
const auto & [sys_name, sys_ptr] :
_systems)
858 bool use_current_system = (system_names ==
nullptr);
859 if (!use_current_system)
860 use_current_system = system_names->count(sys_name);
861 if (!use_current_system || sys_ptr->hide_output())
864 const System & system = *sys_ptr;
865 const unsigned int nv_sys = system.
n_vars();
866 const unsigned int sys_num = system.
number();
869 unsigned int n_scalar_vars = 0;
870 unsigned int n_vector_vars = 0;
881 unsigned int nv_sys_split = n_scalar_vars +
dim*n_vector_vars;
892 if (!non_const_sys.
solution->closed())
901 std::vector<Number> elem_soln;
902 std::vector<Number> nodal_soln;
903 std::vector<dof_id_type> dof_indices;
905 unsigned var_inc = 0;
906 for (
unsigned int var=0; var<nv_sys; var++)
913 for (
const auto & elem :
_mesh.active_local_element_ptr_range())
918 sys_soln.
get(dof_indices, elem_soln);
929 if (!elem->infinite())
931 libmesh_assert_equal_to (nodal_soln.size(), n_vec_dim*elem->n_nodes());
933 for (
auto n : elem->node_index_range())
935 const Node & node = elem->node_ref(n);
938 nv * node_id_to_vec_id(node.
id());
940 for (
unsigned int d=0; d < n_vec_dim; d++)
944 parallel_soln.
add(node_idx + (var_inc+d + var_num), nodal_soln[n_vec_dim*n+d]);
947 repeat_count.
add(node_idx + (var_inc+d + var_num), 1);
953 for (
auto s : elem->side_index_range())
961 (fe_type, elem, s, elem_soln,
962 nodal_soln, add_p_level, n_vec_dim);
965 const std::vector<unsigned int> side_nodes =
966 elem->nodes_on_side(s);
968 libmesh_assert_equal_to
976 std::size_t node_index =
977 nv * libmesh_map_find(discontinuous_node_indices,
978 std::make_tuple(elem->id(), s, n));
980 for (
unsigned int d=0; d < n_vec_dim; d++)
982 parallel_soln.
add(node_index + (var_inc+d + var_num), nodal_soln[n_vec_dim*n+d]);
983 repeat_count.
add(node_index + (var_inc+d + var_num), 1);
991 for (
auto n : elem->node_index_range())
993 const Node & node = elem->node_ref(n);
997 if (!node.
n_dofs(sys_num, var))
1000 nv * node_id_to_vec_id(node.
id());
1002 for (
unsigned int d=0; d < n_vec_dim; d++)
1003 repeat_count.
add(node_idx + (var_inc+d + var_num), 1);
1008 var_inc += n_vec_dim;
1011 var_num += nv_sys_split;
1015 parallel_soln.
close();
1016 repeat_count.
close();
1030 if (std::abs(repeat_count(i)) <
TOLERANCE)
1031 repeat_count.
set(i, 1.);
1036 repeat_count.
close();
1040 parallel_soln /= repeat_count;
1042 return parallel_soln_ptr;
1048 const std::set<std::string> * system_names,
1049 bool add_sides)
const
1051 LOG_SCOPE(
"build_solution_vector()",
"EquationSystems");
1054 std::unique_ptr<NumericVector<Number>> parallel_soln =
1058 parallel_soln->localize_to_one(soln);
1064 std::vector<std::set<subdomain_id_type>> & vars_active_subdomains)
const
1066 vars_active_subdomains.clear();
1067 vars_active_subdomains.resize(names.size());
1071 const auto & sys_ptr = pr.second;
1072 for (
auto vn :
make_range(sys_ptr->n_vars()))
1074 const std::string & var_name = sys_ptr->variable_name(vn);
1076 auto names_it = std::find(names.begin(), names.end(), var_name);
1077 if(names_it != names.end())
1079 const Variable & variable = sys_ptr->variable(vn);
1080 const std::set<subdomain_id_type> & active_subdomains = variable.
active_subdomains();
1081 vars_active_subdomains[std::distance(names.begin(), names_it)] = active_subdomains;
1091 std::vector<std::string> & names)
const
1094 std::unique_ptr<NumericVector<Number>> parallel_soln =
1103 parallel_soln->localize_to_one(soln);
1106std::vector<std::pair<unsigned int, unsigned int>>
1108 (std::vector<std::string> & names,
const FEType * type,
const std::vector<FEType> * types)
const
1111 libmesh_assert_msg(!type || !types,
1112 "Input 'type', 'types', or neither in find_variable_numbers, but not both.");
1114 std::vector<FEType> type_filter;
1116 type_filter.push_back(*type);
1118 type_filter = *types;
1122 [&type_filter](
const FEType & var_type)
1124 return type_filter.empty() ||
1125 std::find(type_filter.begin(), type_filter.end(), var_type) != type_filter.end();
1131std::vector<std::pair<unsigned int, unsigned int>>
1140std::vector<std::pair<unsigned int, unsigned int>>
1142 (std::vector<std::string> & names,
1143 const std::function<
bool(
const FEType &)> & type_filter)
const
1146 parallel_object_only();
1154 std::vector<std::string> name_filter = names;
1155 bool is_names_empty = name_filter.empty();
1162 const std::vector<std::string> component_suffix = {
"_x",
"_y",
"_z"};
1164 libmesh_error_msg_if(
dim > 3,
"Invalid dim in find_variable_numbers");
1168 std::vector<std::pair<unsigned int, unsigned int>> var_nums;
1172 const System & system = *(pr.second);
1178 if (!type_filter(var_type))
1184 std::vector<std::string> component_names;
1185 for (
unsigned int comp = 0; comp <
dim; ++comp)
1188 if (is_names_empty ||
1189 (std::find(name_filter.begin(), name_filter.end(), name) != name_filter.end()))
1190 component_names.push_back(name);
1193 if (! component_names.empty())
1194 names.insert(names.end(), component_names.begin(), component_names.end());
1201 if (is_names_empty ||
1202 (std::find(name_filter.begin(), name_filter.end(), name) != name_filter.end()))
1203 names.push_back(name);
1209 var_nums.emplace_back(system.
number(), var);
1214 std::vector<unsigned int> sort_index(var_nums.size());
1215 std::iota(sort_index.begin(), sort_index.end(), 0);
1216 std::sort(sort_index.begin(), sort_index.end(),
1217 [&](
const unsigned int & lhs,
const unsigned int & rhs)
1218 {return this->get_system(var_nums[lhs].first).variable_name(var_nums[lhs].second) <
1219 this->get_system(var_nums[rhs].first).variable_name(var_nums[rhs].second);});
1221 std::vector<std::pair<unsigned int, unsigned int>> var_nums_sorted(var_nums.size());
1224 var_nums_sorted[i].first = var_nums[sort_index[i]].first;
1225 var_nums_sorted[i].second = var_nums[sort_index[i]].second;
1229 std::sort(names.begin(), names.end());
1232 return var_nums_sorted;
1236std::unique_ptr<NumericVector<Number>>
1242 std::vector<std::pair<unsigned int, unsigned int>> var_nums =
1245 const std::size_t nv = names.size();
1251 return std::unique_ptr<NumericVector<Number>>(
nullptr);
1265 parallel_soln_local_size = div+1;
1270 parallel_soln.
init(parallel_soln_global_size,
1271 parallel_soln_local_size,
1275 unsigned int sys_ctr = 0;
1276 unsigned int var_ctr = 0;
1279 std::pair<unsigned int, unsigned int> var_num = var_nums[i];
1283 if (sys_ctr != var_num.first)
1292 if (!non_const_sys.
solution->closed())
1295 sys_ctr = var_num.first;
1300 const unsigned int var = var_num.second;
1310 const unsigned int n_comps =
1317 [&dof_map, &variable, ne, var, var_ctr, n_comps,
1321 std::vector<dof_id_type> dof_indices;
1323 for (const Elem * elem : range)
1325 if (variable.active_on_subdomain(elem->subdomain_id()))
1327 dof_map.dof_indices(elem, dof_indices, var);
1331 libmesh_assert_equal_to(dof_indices.size(), n_comps);
1333 for (unsigned int comp = 0; comp < n_comps; comp++)
1334 parallel_soln.set(ne * (var_ctr + comp) + elem->id(), sys_soln(dof_indices[comp]));
1347 libmesh_assert_equal_to(names.size(), var_ctr);
1349 parallel_soln.close();
1350 return parallel_soln_ptr;
1356EquationSystems::build_discontinuous_solution_vector
1357(std::vector<Number> & soln,
1358 const std::set<std::string> * system_names,
1359 const std::vector<std::string> * var_names,
1361 bool add_sides)
const
1363 LOG_SCOPE(
"build_discontinuous_solution_vector()",
"EquationSystems");
1367 const std::vector<std::string> component_suffix = {
"_x",
"_y",
"_z"};
1368 const auto requested_components =
1369 [
this, var_names, &component_suffix](
const System & system,
1370 const unsigned int var)
1372 std::vector<unsigned int> components;
1374 const std::string & var_name = system.variable_name(var);
1375 const FEType & fe_type = system.variable_type(var);
1376 const unsigned int n_vec_dim = FEInterface::n_vec_dim(_mesh, fe_type);
1378 if (FEInterface::field_type(fe_type) ==
TYPE_VECTOR)
1380 libmesh_error_msg_if(n_vec_dim > component_suffix.size(),
1381 "Invalid dim in build_discontinuous_solution_vector");
1383 const bool use_all_components =
1384 (var_names ==
nullptr) ||
1385 std::count(var_names->begin(), var_names->end(), var_name);
1389 if (use_all_components)
1390 components.push_back(0);
1395 const std::string component_name = var_name + component_suffix[comp];
1396 if (use_all_components ||
1397 std::count(var_names->begin(), var_names->end(), component_name))
1398 components.push_back(comp);
1401 else if (var_names ==
nullptr ||
1402 std::count(var_names->begin(), var_names->end(), var_name))
1403 components.push_back(0);
1410 unsigned int nv = 0;
1412 for (
const auto & [sys_name, sys_ptr] : _systems)
1415 bool use_current_system = (system_names ==
nullptr);
1416 if (!use_current_system)
1417 use_current_system = system_names->count(sys_name);
1418 if (!use_current_system || sys_ptr->hide_output())
1423 for (
auto var_id :
make_range(sys_ptr->n_vars()))
1424 nv += cast_int<unsigned int>(requested_components(*sys_ptr, var_id).size());
1430 for (
const auto & elem : _mesh.active_element_ptr_range())
1432 tw += vertices_only ? elem->n_vertices() : elem->n_nodes();
1436 for (
auto s : elem->side_index_range())
1438 if (redundant_added_side(*elem,s))
1441 const std::vector<unsigned int> side_nodes =
1442 elem->nodes_on_side(s);
1445 tw += side_nodes.size();
1448 if (elem->is_vertex(side_nodes[n]))
1456 if (_mesh.processor_id() == 0)
1459 std::vector<Number> sys_soln;
1463 unsigned int var_offset = 0;
1470 for (
const auto & [sys_name, system] : _systems)
1473 bool use_current_system = (system_names ==
nullptr);
1474 if (!use_current_system)
1475 use_current_system = system_names->count(sys_name);
1476 if (!use_current_system || system->hide_output())
1479 const unsigned int nv_sys = system->n_vars();
1480 const auto & dof_map = system->get_dof_map();
1482 system->update_global_solution (sys_soln, 0);
1485 unsigned int n_vars_written_current_system = 0;
1487 if (_mesh.processor_id() == 0)
1489 std::vector<Number> soln_coeffs;
1490 std::vector<Number> nodal_soln;
1491 std::vector<dof_id_type> dof_indices;
1500 const std::vector<unsigned int> components_to_write =
1501 requested_components(*system, var);
1505 if (components_to_write.empty())
1508 const FEType & fe_type = system->variable_type(var);
1509 const Variable & var_description = system->variable(var);
1511 const unsigned int n_vec_dim = FEInterface::n_vec_dim(_mesh, fe_type);
1515 for (
auto & elem : _mesh.active_element_ptr_range())
1519 dof_map.dof_indices (elem, dof_indices, var);
1521 soln_coeffs.resize(dof_indices.size());
1524 soln_coeffs[i] = sys_soln[dof_indices[i]];
1529 FEInterface::nodal_soln (elem->dim(),
1538 if (!elem->infinite())
1540 libmesh_assert_equal_to (nodal_soln.size(), elem->n_nodes()*n_vec_dim);
1542 const unsigned int n_vals =
1543 vertices_only ? elem->n_vertices() : elem->n_nodes();
1549 nv * (nn++) + (n_vars_written_current_system + var_offset);
1551 for (
auto component_index :
index_range(components_to_write))
1552 soln[index + component_index] +=
1553 nodal_soln[n_vec_dim*n + components_to_write[component_index]];
1558 nn += vertices_only ? elem->n_vertices() : elem->n_nodes();
1569 std::vector<std::vector<const Elem *>>
1570 elems_by_pid(_mesh.n_processors());
1572 for (
const auto & elem : _mesh.active_element_ptr_range())
1573 elems_by_pid[elem->processor_id()].push_back(elem);
1576 for (
const Elem * elem : elems_by_pid[p])
1580 dof_map.dof_indices (elem, dof_indices, var);
1582 soln_coeffs.resize(dof_indices.size());
1585 soln_coeffs[i] = sys_soln[dof_indices[i]];
1587 for (
auto s : elem->side_index_range())
1589 if (redundant_added_side(*elem,s))
1592 const std::vector<unsigned int> side_nodes =
1593 elem->nodes_on_side(s);
1599 FEInterface::side_nodal_soln
1600 (fe_type, elem, s, soln_coeffs,
1601 nodal_soln, add_p_level,
1604 libmesh_assert_equal_to
1606 side_nodes.size()*n_vec_dim);
1615 FEInterface::get_continuity(fe_type);
1620 neigh->
level() == elem->level() &&
1623 std::vector<dof_id_type> neigh_indices;
1624 dof_map.dof_indices (neigh, neigh_indices, var);
1625 std::vector<Number> neigh_coeffs(neigh_indices.size());
1628 neigh_coeffs[i] = sys_soln[neigh_indices[i]];
1630 const unsigned int s_neigh =
1632 std::vector<Number> neigh_soln;
1633 FEInterface::side_nodal_soln
1634 (fe_type, neigh, s_neigh,
1635 neigh_coeffs, neigh_soln, add_p_level,
1638 const std::vector<unsigned int> neigh_nodes =
1642 if (neigh->
node_ptr(neigh_nodes[neigh_n])
1643 == elem->node_ptr(side_nodes[n]))
1646 const auto nodal_index = n_vec_dim*n + comp;
1647 nodal_soln[nodal_index] +=
1648 neigh_soln[n_vec_dim*neigh_n + comp];
1649 nodal_soln[nodal_index] /= 2;
1655 if (vertices_only &&
1656 !elem->is_vertex(n))
1661 nv * (nn++) + (n_vars_written_current_system + var_offset);
1663 for (
auto component_index :
index_range(components_to_write))
1664 soln[index + component_index] +=
1665 nodal_soln[n_vec_dim*n + components_to_write[component_index]];
1671 nn += vertices_only ? elem->n_vertices() : elem->n_nodes();
1673 for (
auto s : elem->side_index_range())
1675 if (redundant_added_side(*elem,s))
1678 const std::vector<unsigned int> side_nodes =
1679 elem->nodes_on_side(s);
1683 if (vertices_only &&
1684 !elem->is_vertex(n))
1694 n_vars_written_current_system += cast_int<unsigned int>(components_to_write.size());
1700 var_offset += n_vars_written_current_system;
1706bool EquationSystems::redundant_added_side(
const Elem & elem,
unsigned int side)
1726 return (neigh->
id() < elem.
id());
1732 const Real threshold,
1733 const bool verbose)
const
1737 std::vector<bool> os_result;
1739 if (this->n_systems() != other_es.
n_systems())
1743 libMesh::out <<
" Fatal difference. This system handles "
1744 << this->n_systems() <<
" systems," << std::endl
1745 <<
" while the other system handles "
1747 <<
" systems." << std::endl
1748 <<
" Aborting comparison." << std::endl;
1755 for (
const auto & [sys_name, sys_ptr] : _systems)
1760 os_result.push_back (sys_ptr->compare (other_system, threshold, verbose));
1768 if (os_result.size()==0)
1776 os_identical = os_result[n];
1779 while (os_identical && n<os_result.size());
1780 return os_identical;
1786std::string EquationSystems::get_info ()
const
1788 std::ostringstream oss;
1790 unsigned int n_hidden_sys = 0;
1791 for (
auto & pr : _systems)
1792 n_hidden_sys += pr.second->hide_output();
1794 oss <<
" EquationSystems\n"
1795 <<
" n_systems()=" << this->n_systems()
1796 << (n_hidden_sys ?
" (hidden: " + std::to_string(n_hidden_sys) +
")" :
"")
1800 for (
const auto & pr : _systems)
1801 if (!pr.second->hide_output())
1802 oss << pr.second->get_info();
1826void EquationSystems::print_info (std::ostream & os)
const
1828 os << this->get_info()
1834std::ostream & operator << (std::ostream & os,
1843unsigned int EquationSystems::n_vars ()
const
1847 for (
const auto & pr : _systems)
1848 tot += pr.second->n_vars();
1855std::size_t EquationSystems::n_dofs ()
const
1859 for (
const auto & pr : _systems)
1860 tot += pr.second->n_dofs();
1868std::size_t EquationSystems::n_active_dofs ()
const
1872 for (
const auto & pr : _systems)
1873 tot += pr.second->n_active_dofs();
1879void EquationSystems::_add_system_to_nodes_and_elems()
1882 for (
auto & node : _mesh.node_ptr_range())
1886 Threads::parallel_for
1887 (_mesh.element_stored_range(),
1890 for (Elem * elem : range)
1895void EquationSystems::_remove_default_ghosting(
unsigned int sys_num)
1897 this->get_system(sys_num).get_dof_map().remove_default_ghosting();
processor_id_type size() const
processor_id_type rank() const
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
This class handles the numbering of degrees of freedom on a mesh.
void remove_default_ghosting()
Remove any default ghosting functor(s).
std::size_t distribute_dofs(MeshBase &)
Distribute dofs on the current mesh.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void add_default_ghosting()
Add the default functor(s) for coupling and algebraic ghosting.
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
This is the base class from which all geometric element types are derived.
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
subdomain_id_type subdomain_id() const
unsigned int level() const
const Node * node_ptr(const unsigned int i) const
const Elem * neighbor_ptr(unsigned int i) const
This is the EquationSystems class.
std::vector< std::pair< unsigned int, unsigned int > > find_elemental_data_variable_numbers(std::vector< std::string > &names) const
Finds system and variable numbers for variables that can be represented as elemental data.
virtual void reinit()
Handle any mesh changes and reinitialize all the systems on the updated mesh.
static bool is_elemental_data_fe_type(const FEType &type)
std::vector< std::pair< unsigned int, unsigned int > > find_variable_numbers_by_predicate(std::vector< std::string > &names, const std::function< bool(const FEType &)> &type_filter) const
Implementation detail for find_variable_numbers() variants.
std::unique_ptr< NumericVector< Number > > build_parallel_elemental_solution_vector(std::vector< std::string > &names) const
Builds a parallel vector of elemental data solution values corresponding to the entries in the input ...
EquationSystems(MeshBase &mesh)
Constructor.
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
std::unique_ptr< NumericVector< Number > > build_parallel_solution_vector(const std::set< std::string > *system_names=nullptr, bool add_sides=false) const
A version of build_solution_vector which is appropriate for "parallel" output formats like Nemesis.
virtual ~EquationSystems()
Destructor.
virtual void sensitivity_solve(const ParameterVector ¶meters)
Call sensitivity_solve on all the individual equation systems.
void update()
Updates local values for all the systems.
std::vector< std::pair< unsigned int, unsigned int > > find_variable_numbers(std::vector< std::string > &names, const FEType *type=nullptr, const std::vector< FEType > *types=nullptr) const
Finds system and variable numbers for any variables of 'type' or of 'types' corresponding to the entr...
void build_variable_names(std::vector< std::string > &var_names, const FEType *type=nullptr, const std::set< std::string > *system_names=nullptr) const
Fill the input vector var_names with the names of the variables for each system.
void build_elemental_solution_vector(std::vector< Number > &soln, std::vector< std::string > &names) const
Retrieve the solution data for elemental data variables.
unsigned int n_systems() const
static bool redundant_added_side(const Elem &elem, unsigned int side)
unsigned int n_vars() const
void get_vars_active_subdomains(const std::vector< std::string > &names, std::vector< std::set< subdomain_id_type > > &vars_active_subdomains) const
Retrieve vars_active_subdomains, which indicates the active subdomains for each variable in names.
const MeshBase & get_mesh() const
Parameters parameters
Data structure holding arbitrary parameters.
void build_elemental_data_variable_names(std::vector< std::string > &var_names, const std::set< std::string > *system_names=nullptr) const
Filter var_names to names of variables that can be represented as elemental data.
void build_solution_vector(std::vector< Number > &soln, std::string_view system_name, std::string_view variable_name="all_vars") const
Fill the input vector soln with the solution values for the system named name.
bool _refine_in_reinit
Flag for whether to call coarsen/refine in reinit().
MeshBase & _mesh
The mesh data structure.
bool reinit_solutions()
Handle any mesh changes and project any solutions onto the updated mesh.
virtual void init()
Initialize all the systems.
virtual System & add_system(std::string_view system_type, std::string_view name)
Add the system of type system_type named name to the systems array.
virtual void reinit_mesh()
Handle the association of a completely new mesh with the EquationSystem and all the Systems assigned ...
virtual void adjoint_solve(const QoISet &qoi_indices=QoISet())
Call adjoint_solve on all the individual equation systems.
virtual void reinit_systems()
Reinitialize all systems on the current mesh.
virtual void clear()
Restores the data structure to a pristine state.
const T_sys & get_system(std::string_view name) const
virtual void enable_default_ghosting(bool enable)
Enable or disable default ghosting functors on the Mesh and on all Systems.
virtual void solve()
Call solve on all the individual equation systems.
bool _enable_default_ghosting
Flag for whether to enable default ghosting on newly added Systems.
std::map< std::string, std::unique_ptr< System >, std::less<> > _systems
Data structure holding the systems.
void allgather()
Serializes a distributed mesh and its associated degree of freedom numbering for all systems.
static unsigned int n_vec_dim(const MeshBase &mesh, const FEType &fe_type)
static FEFieldType field_type(const FEType &fe_type)
static void nodal_soln(const unsigned int dim, const FEType &fe_t, const Elem *elem, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln, const bool add_p_level=true, const unsigned int vdim=1)
Build the nodal soln from the element soln.
static void side_nodal_soln(const FEType &fe_t, const Elem *elem, const unsigned int side, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln, const bool add_p_level=true, const unsigned int vdim=1)
Build the nodal soln on one side from the (full) element soln.
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
bool p_refinement
Whether or not the finite elements for this type increase their p refinement level on geometric eleme...
FEFamily family
The type of finite element.
This is the MeshBase class.
virtual bool is_serial() const
virtual bool contract()=0
Delete subactive (i.e.
virtual dof_id_type n_elem() const =0
unsigned int spatial_dimension() const
const ConstElemRange & active_local_element_stored_range() const
const ElemRange & element_stored_range()
virtual dof_id_type max_node_id() const =0
virtual dof_id_type max_elem_id() const =0
virtual void allgather()
Gathers all elements and nodes of the mesh onto every processor.
Implements (adaptive) mesh refinement algorithms for a MeshBase.
bool coarsen_elements()
Only coarsens the user-requested elements.
void clean_refinement_flags()
Sets the refinement flag to Elem::DO_NOTHING for each element in the mesh.
unsigned char & face_level_mismatch_limit()
If face_level_mismatch_limit is set to a nonzero value, then refinement and coarsening will produce m...
signed char & underrefined_boundary_limit()
If underrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will pro...
bool refine_elements()
Only refines the user-requested elements.
signed char & overrefined_boundary_limit()
If overrefined_boundary_limit is set to a nonnegative value, then refinement and coarsening will prod...
A Node is like a Point, but with more information.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void set(const numeric_index_type i, const T value)=0
Sets v(i) = value.
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
virtual numeric_index_type last_local_index() const =0
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
virtual void init(const numeric_index_type n, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC)=0
Change the dimension of the vector to n.
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.
virtual numeric_index_type first_local_index() const =0
An object whose state is distributed along a set of processors.
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
processor_id_type n_processors() const
Data structure for specifying which Parameters should be independent variables in a parameter sensiti...
virtual void clear()
Clears internal data structures & frees any allocated memory.
T & set(const std::string &)
Data structure for specifying which Quantities of Interest should be calculated in an adjoint or a pa...
The StoredRange class defines a contiguous, divisible set of objects.
Manages consistently variables, degrees of freedom, and coefficient vectors.
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
const Variable & variable(unsigned int var) const
Return a constant reference to Variable var.
const FEType & variable_type(const unsigned int i) const
virtual void prolong_vectors()
Prolong vectors after the mesh has refined.
virtual void restrict_vectors()
Restrict vectors after the mesh has coarsened.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
const std::string & variable_name(const unsigned int i) const
virtual void update()
Update the local values to reflect the solution on neighboring processors.
virtual void reinit_constraints()
Reinitializes the constraints for this system.
unsigned int n_vars() const
const DofMap & get_dof_map() const
unsigned int number() const
This class defines the notion of a variable in the system.
const std::set< subdomain_id_type > & active_subdomains() const
bool active_on_subdomain(subdomain_id_type sid) const
void parallel_for(const Range &range, const Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided function object in parallel on the specified range.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
dof_id_type numeric_index_type
const RemoteElem * remote_elem
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...