25 #include "libmesh/libmesh_config.h" 27 #ifdef LIBMESH_HAVE_METAPHYSICL 31 #include "libmesh/libmesh_common.h" 32 #include "libmesh/compare_types.h" 36 #include "metaphysicl/dynamicsparsenumberarray_decl.h" 38 using MetaPhysicL::DynamicSparseNumberArray;
44 template <
typename T,
typename IndexType>
52 template <
typename T,
typename IndexType,
typename T2>
56 MetaPhysicL::DynamicSparseNumberArray
62 template <
typename T,
typename IndexType>
64 typedef std::vector<std::pair<IndexType,T>>
type;
67 template <
typename T,
typename IndexType>
68 const std::vector<std::pair<IndexType,T>>
71 const std::size_t in_size = in.size();
72 std::vector<std::pair<IndexType,T>> returnval(in_size);
74 for (std::size_t i=0; i != in_size; ++i)
76 returnval[i].first = in.raw_index(i);
77 returnval[i].second = in.raw_at(i);
82 template <
typename SendT,
typename T,
typename IndexType>
84 MetaPhysicL::DynamicSparseNumberArray<T,IndexType> & converted)
86 const std::size_t received_size = received.size();
87 converted.resize(received_size);
88 for (std::size_t i=0; i != received_size; ++i)
90 converted.raw_index(i) = received[i].first;
91 converted.raw_at(i) = received[i].second;
100 #include "libmesh/boundary_info.h" 101 #include "libmesh/dense_matrix.h" 102 #include "libmesh/dense_vector.h" 103 #include "libmesh/dof_map.h" 104 #include "libmesh/elem.h" 105 #include "libmesh/fe_base.h" 106 #include "libmesh/fe_interface.h" 107 #include "libmesh/generic_projector.h" 108 #include "libmesh/int_range.h" 109 #include "libmesh/libmesh_logging.h" 110 #include "libmesh/linear_solver.h" 111 #include "libmesh/mesh_base.h" 112 #include "libmesh/numeric_vector.h" 113 #include "libmesh/quadrature.h" 114 #include "libmesh/sparse_matrix.h" 115 #include "libmesh/system.h" 116 #include "libmesh/threads.h" 117 #include "libmesh/wrapped_function.h" 118 #include "libmesh/wrapped_functor.h" 119 #include "libmesh/fe_interface.h" 123 #ifdef LIBMESH_HAVE_METAPHYSICL 125 #include "metaphysicl/dynamicsparsenumberarray.h" 128 #include "libmesh/dense_matrix_impl.h" 131 typedef DynamicSparseNumberArray<Real, dof_id_type>
DSNAN;
133 template LIBMESH_EXPORT
void 136 template LIBMESH_EXPORT
void 150 #ifdef LIBMESH_ENABLE_AMR 174 system(other.system),
184 #endif // LIBMESH_ENABLE_AMR 195 const std::set<boundary_id_type> &
b;
198 std::unique_ptr<FunctionBase<Number>>
f;
199 std::unique_ptr<FunctionBase<Gradient>>
g;
205 const std::vector<unsigned int> & variables_in,
212 variables(variables_in),
216 parameters(parameters_in),
227 variables(in.variables),
231 parameters(in.parameters),
232 new_vector(in.new_vector)
249 std::optional<ConstElemRange> active_local_range,
250 std::optional<std::vector<unsigned int>> variable_numbers)
const 254 std::unique_ptr<NumericVector<Number>>
255 old_vector (vector.
clone());
258 this->project_vector (*old_vector, vector, is_adjoint, active_local_range, variable_numbers);
270 std::optional<ConstElemRange> active_local_range,
271 std::optional<std::vector<unsigned int>> variable_numbers)
const 273 LOG_SCOPE (
"project_vector(old,new)",
"System");
283 #ifdef LIBMESH_ENABLE_AMR 287 std::unique_ptr<NumericVector<Number>> new_vector_built;
289 std::unique_ptr<NumericVector<Number>> local_old_vector_built;
292 if (!active_local_range)
294 active_local_range.emplace
295 (this->get_mesh().active_local_elements_begin(),
296 this->get_mesh().active_local_elements_end());
304 new_vector_ptr = &new_v;
305 old_vector_ptr = &old_v;
320 new_v.
init (this->n_dofs(), this->n_local_dofs(),
false,
PARALLEL);
323 new_vector_ptr = new_vector_built.
get();
324 local_old_vector = local_old_vector_built.
get();
325 new_vector_ptr->
init(this->n_dofs(), this->n_local_dofs(),
326 this->get_dof_map().get_send_list(),
false,
331 local_old_vector->
close();
332 old_vector_ptr = local_old_vector;
344 new_v.
init (this->n_dofs(), this->n_local_dofs(),
345 this->get_dof_map().get_send_list(),
false,
GHOSTED);
348 new_vector_ptr = &new_v;
349 local_old_vector = local_old_vector_built.
get();
353 local_old_vector->
close();
354 old_vector_ptr = local_old_vector;
357 libmesh_error_msg(
"ERROR: Unknown old_v.type() == " << old_v.
type());
368 const unsigned int n_variables = this->
n_vars();
372 std::vector<unsigned int> vars;
373 if (variable_numbers)
375 vars = *variable_numbers;
377 if (v >= n_variables)
378 libmesh_error_msg(
"ERROR: variable number " << v <<
379 " out of range for system with " <<
380 n_variables <<
" variables.");
384 vars.resize(n_variables);
385 std::iota(vars.begin(), vars.end(), 0);
388 std::vector<unsigned int> regular_vars, vector_vars;
389 for (
auto var : vars)
391 if (FEInterface::field_type(this->variable_type(var)) ==
TYPE_SCALAR)
392 regular_vars.push_back(var);
394 vector_vars.push_back(var);
399 if (!regular_vars.empty())
408 f(*
this, old_vector, ®ular_vars);
410 g(*
this, old_vector, ®ular_vars);
412 FEMProjector projector(*
this, f, &g, setter, regular_vars);
413 projector.project(active_local_range.value());
416 if (!vector_vars.empty())
426 FEMVectorProjector vector_projector(*
this, f_vector, &g_vector, setter, vector_vars);
427 vector_projector.project(active_local_range.value());
433 if (this->processor_id() == (this->n_processors()-1))
435 const DofMap & dof_map = this->get_dof_map();
436 for (
auto var : vars)
437 if (this->variable(var).type().family ==
SCALAR)
440 std::vector<dof_id_type> new_SCALAR_indices, old_SCALAR_indices;
444 new_vector.
set(new_SCALAR_indices[i], old_vector(old_SCALAR_indices[i]));
459 dist_v->init(this->n_dofs(), this->n_local_dofs(),
false,
PARALLEL);
463 if (new_vector(i) != 0.0)
464 dist_v->set(i, new_vector(i));
468 dist_v->localize (new_v, this->get_dof_map().get_send_list());
484 if(this->project_with_constraints)
486 if (is_adjoint == -1)
488 this->get_dof_map().enforce_constraints_exactly(*
this, &new_v);
490 else if (is_adjoint >= 0)
492 this->get_dof_map().enforce_adjoint_constraints_exactly(new_v,
503 #endif // #ifdef LIBMESH_ENABLE_AMR 507 #ifdef LIBMESH_ENABLE_AMR 508 #ifdef LIBMESH_HAVE_METAPHYSICL 510 template <
typename Output>
514 typedef DynamicSparseNumberArray<Output, dof_id_type>
type;
517 template <
typename InnerOutput>
533 template <
typename Output,
546 const std::vector<unsigned int> * vars) :
549 this->old_context.set_algebraic_type(FEMContext::OLD_DOFS_ONLY);
553 OldSolutionBase<Output, point_output>(in.sys, in.old_context.active_vars())
555 this->old_context.set_algebraic_type(FEMContext::OLD_DOFS_ONLY);
560 unsigned int elem_dim,
562 bool extra_hanging_dofs,
569 bool skip_context_check);
575 std::vector<DSNA> & derivs)
577 LOG_SCOPE (
"eval_mixed_derivatives",
"OldSolutionCoefs");
580 libmesh_assert_less(c.get_elem().get_node_index(&n),
581 c.get_elem().n_vertices());
584 libmesh_assert_less(i, this->component_to_var.size());
585 unsigned int var = this->component_to_var[i];
588 const unsigned int n_mixed = (
dim-1) * (
dim-1);
589 derivs.resize(n_mixed);
594 if (old_dof_object &&
595 old_dof_object->
n_vars(this->sys.number()) &&
596 old_dof_object->
n_comp(this->sys.number(), var))
600 std::vector<dof_id_type> old_ids(n_mixed);
601 std::iota(old_ids.begin(), old_ids.end(), first_old_id);
605 derivs[d_i].resize(1);
606 derivs[d_i].raw_at(0) = 1;
607 derivs[d_i].raw_index(0) = old_ids[d_i];
612 std::fill(derivs.begin(), derivs.end(), 0);
618 unsigned int node_num,
619 unsigned int var_num,
620 std::vector<dof_id_type> & indices,
621 std::vector<DSNA> & values)
623 LOG_SCOPE (
"eval_old_dofs(node)",
"OldSolutionCoefs");
629 this->sys.get_dof_map().dof_indices(elem, node_num, indices, var_num);
631 std::vector<dof_id_type> old_indices;
633 this->sys.get_dof_map().old_dof_indices(elem, node_num, old_indices, var_num);
635 libmesh_assert_equal_to (old_indices.size(), indices.size());
637 values.resize(old_indices.size());
642 values[i].raw_at(0) = 1;
643 values[i].raw_index(0) = old_indices[i];
650 unsigned int sys_num,
651 unsigned int var_num,
652 std::vector<dof_id_type> & indices,
653 std::vector<DSNA> & values)
655 LOG_SCOPE (
"eval_old_dofs(elem)",
"OldSolutionCoefs");
659 const Elem & old_elem =
664 const unsigned int nc =
665 FEInterface::n_dofs_per_elem(fe_type, &elem);
667 std::vector<dof_id_type> old_dof_indices(nc);
677 const auto [vg, vig] =
680 const unsigned int n_comp = elem.
n_comp_group(sys_num,vg);
681 libmesh_assert_greater(elem.
n_systems(), sys_num);
682 libmesh_assert_greater_equal(n_comp, nc);
684 for (
unsigned int i=0; i<nc; i++)
687 old_dof_object.
dof_number(sys_num, vg, vig, i, n_comp);
690 libmesh_assert_not_equal_to (d_old, DofObject::invalid_id);
691 libmesh_assert_not_equal_to (d_new, DofObject::invalid_id);
693 old_dof_indices[i] = d_old;
698 values.resize(old_dof_indices.size());
703 values[i].raw_at(0) = 1;
704 values[i].raw_index(0) = old_dof_indices[i];
713 DynamicSparseNumberArray<Real, dof_id_type>
714 OldSolutionCoefs<Real, &FEMContext::point_value>::
719 bool skip_context_check)
721 LOG_SCOPE (
"eval_at_point()",
"OldSolutionCoefs");
723 if (!skip_context_check)
724 if (!this->check_old_context(c, p))
729 this->old_context.get_element_fe<
Real>
730 (i, fe, this->old_context.get_elem_dim());
734 this->old_context.build_new_fe(fe, p);
737 const std::vector<std::vector<Real> > & phi = fe_new->
get_phi();
738 const std::vector<dof_id_type> & dof_indices =
739 this->old_context.get_dof_indices(i);
741 const std::size_t n_dofs = phi.size();
742 libmesh_assert_equal_to(n_dofs, dof_indices.size());
744 DynamicSparseNumberArray<Real, dof_id_type> returnval;
745 returnval.resize(n_dofs);
749 returnval.raw_at(j) = phi[j][0];
750 returnval.raw_index(j) = dof_indices[j];
766 bool skip_context_check)
768 LOG_SCOPE (
"eval_at_point()",
"OldSolutionCoefs");
770 if (!skip_context_check)
771 if (!this->check_old_context(c, p))
776 this->old_context.get_element_fe<
Real>
777 (i, fe, this->old_context.get_elem_dim());
781 this->old_context.build_new_fe(fe, p);
784 const std::vector<std::vector<RealGradient> > & dphi = fe_new->
get_dphi();
785 const std::vector<dof_id_type> & dof_indices =
786 this->old_context.get_dof_indices(i);
788 const std::size_t n_dofs = dphi.size();
789 libmesh_assert_equal_to(n_dofs, dof_indices.size());
793 for (
unsigned int d = 0; d != LIBMESH_DIM; ++d)
794 returnval(d).resize(n_dofs);
797 for (
int d = 0; d != LIBMESH_DIM; ++d)
799 returnval(d).raw_at(j) = dphi[j][0](d);
800 returnval(d).raw_index(j) = dof_indices[j];
809 DynamicSparseNumberArray<Real, dof_id_type>
815 bool extra_hanging_dofs,
818 LOG_SCOPE (
"Real eval_at_node()",
"OldSolutionCoefs");
833 if (old_dof_object &&
834 (!extra_hanging_dofs ||
835 flag == Elem::JUST_COARSENED ||
836 flag == Elem::DO_NOTHING) &&
837 old_dof_object->
n_vars(sys.number()) &&
838 old_dof_object->
n_comp(sys.number(), i))
840 DynamicSparseNumberArray<Real, dof_id_type> returnval;
842 old_dof_object->
dof_number(sys.number(), i, 0);
844 returnval.raw_at(0) = 1;
845 returnval.raw_index(0) = old_id;
849 return this->eval_at_point(c, i, n, 0,
false);
860 unsigned int elem_dim,
862 bool extra_hanging_dofs,
865 LOG_SCOPE (
"RealGradient eval_at_node()",
"OldSolutionCoefs");
880 if (old_dof_object &&
881 (!extra_hanging_dofs ||
882 flag == Elem::JUST_COARSENED ||
883 flag == Elem::DO_NOTHING) &&
884 old_dof_object->
n_vars(sys.number()) &&
885 old_dof_object->
n_comp(sys.number(), i))
888 for (
unsigned int d = 0; d != elem_dim; ++d)
891 old_dof_object->
dof_number(sys.number(), i, d+1);
894 g(d).raw_index(0) = old_id;
899 return this->eval_at_point(c, i, n, 0,
false);
912 template <
typename ValIn,
typename ValOut>
922 target_matrix(target_mat) {}
925 const DynamicSparseNumberArray<ValIn, dof_id_type> & val)
931 const std::size_t dnsa_size = val.size();
932 for (
unsigned int j = 0; j != dnsa_size; ++j)
935 const ValIn dof_val = val.raw_at(j);
936 target_matrix.
set(
id, dof_j, dof_val);
942 void insert(
const std::vector<dof_id_type> & dof_indices,
943 const std::vector<DynamicSparseNumberArray<ValIn, dof_id_type> > & Ue)
949 unsigned int size = Ue.size();
951 libmesh_assert_equal_to(size, dof_indices.size());
957 for (
unsigned int i = 0; i != size; ++i)
960 if ((dof_i >= begin_dof) && (dof_i < end_dof))
962 const DynamicSparseNumberArray<ValIn,dof_id_type> & dnsa = Ue[i];
963 const std::size_t dnsa_size = dnsa.size();
964 for (
unsigned int j = 0; j != dnsa_size; ++j)
967 const ValIn dof_val = dnsa.raw_at(j);
968 target_matrix.
set(dof_i, dof_j, dof_val);
984 LOG_SCOPE (
"projection_matrix()",
"System");
986 const unsigned int n_variables = this->
n_vars();
991 (this->get_mesh().active_local_elements_begin(),
992 this->get_mesh().active_local_elements_end());
994 std::vector<unsigned int> vars(n_variables);
995 std::iota(vars.begin(), vars.end(), 0);
1003 OldSolutionGradientCoefs,
1004 DynamicSparseNumberArray<Real,dof_id_type>,
1007 OldSolutionValueCoefs f(*
this, &vars);
1008 OldSolutionGradientCoefs g(*
this, &vars);
1011 ProjMatFiller mat_filler(*
this, f, &g, setter, vars);
1012 mat_filler.project(active_local_elem_range);
1017 if (this->processor_id() == (this->n_processors()-1))
1019 const DofMap & dof_map = this->get_dof_map();
1021 if (this->variable(var).type().family ==
SCALAR)
1024 std::vector<dof_id_type> new_SCALAR_indices, old_SCALAR_indices;
1027 const unsigned int new_n_dofs =
1028 cast_int<unsigned int>(new_SCALAR_indices.size());
1030 for (
unsigned int i=0; i<new_n_dofs; i++)
1032 proj_mat.
set( new_SCALAR_indices[i],
1033 old_SCALAR_indices[i], 1);
1039 #endif // LIBMESH_HAVE_METAPHYSICL 1040 #endif // LIBMESH_ENABLE_AMR 1048 void System::project_solution (ValueFunctionPointer
fptr,
1049 GradientFunctionPointer
gptr,
1051 std::optional<ConstElemRange> active_local_range,
1052 std::optional<std::vector<unsigned int>> variable_numbers)
const 1056 this->project_solution(&f, &g, active_local_range, variable_numbers);
1066 std::optional<ConstElemRange> active_local_range,
1067 std::optional<std::vector<unsigned int>> variable_numbers)
const 1069 this->project_vector(*solution, f, g, -1, active_local_range, variable_numbers);
1071 solution->localize(*current_local_solution, _dof_map->get_send_list());
1081 std::optional<ConstElemRange> active_local_range,
1082 std::optional<std::vector<unsigned int>> variable_numbers)
const 1084 this->project_vector(*solution, f, g, -1, active_local_range, variable_numbers);
1086 solution->localize(*current_local_solution, _dof_map->get_send_list());
1094 void System::project_vector (ValueFunctionPointer
fptr,
1095 GradientFunctionPointer
gptr,
1099 std::optional<ConstElemRange> active_local_range,
1100 std::optional<std::vector<unsigned int>> variable_numbers)
const 1104 this->project_vector(new_vector, &f, &g, is_adjoint, active_local_range, variable_numbers);
1115 std::optional<ConstElemRange> active_local_range,
1116 std::optional<std::vector<unsigned int>> variable_numbers)
const 1118 LOG_SCOPE (
"project_vector(FunctionBase)",
"System");
1128 this->project_vector(new_vector, &f_fem, &g_fem, is_adjoint, active_local_range, variable_numbers);
1131 this->project_vector(new_vector, &f_fem,
nullptr, is_adjoint, active_local_range, variable_numbers);
1143 std::optional<ConstElemRange> active_local_range,
1144 std::optional<std::vector<unsigned int>> variable_numbers)
const 1146 LOG_SCOPE (
"project_fem_vector()",
"System");
1150 if (!active_local_range)
1152 active_local_range.emplace
1153 (this->get_mesh().active_local_elements_begin(),
1154 this->get_mesh().active_local_elements_end());
1159 const unsigned int n_variables = this->
n_vars();
1161 std::vector<unsigned int> vars;
1162 if (variable_numbers)
1164 vars = *variable_numbers;
1166 if (v >= n_variables)
1167 libmesh_error_msg(
"ERROR: variable number " << v <<
1168 " out of range for system with " <<
1169 n_variables <<
" variables.");
1173 vars.resize(n_variables);
1174 std::iota(vars.begin(), vars.end(), 0);
1189 FEMProjector projector(*
this, fw, &gw, setter, vars);
1190 projector.project(active_local_range.value());
1194 FEMProjector projector(*
this, fw,
nullptr, setter, vars);
1195 projector.project(active_local_range.value());
1201 if (this->processor_id() == (this->n_processors()-1))
1206 const DofMap & dof_map = this->get_dof_map();
1207 for (
auto var : vars)
1208 if (this->variable(var).type().family ==
SCALAR)
1213 context.
pre_fe_reinit(*
this, *(this->get_mesh().active_local_elements_begin()));
1215 std::vector<dof_id_type> SCALAR_indices;
1217 const unsigned int n_SCALAR_dofs =
1218 cast_int<unsigned int>(SCALAR_indices.size());
1220 for (
unsigned int i=0; i<n_SCALAR_dofs; i++)
1222 const dof_id_type global_index = SCALAR_indices[i];
1223 const unsigned int component_index =
1224 this->variable_scalar_number(var,i);
1226 new_vector.
set(global_index, f->
component(context, component_index,
Point(), this->time));
1235 std::vector<const Variable *> rational_vars;
1236 for (
auto varnum : vars)
1238 const Variable & var = this->get_dof_map().variable(varnum);
1240 rational_vars.push_back(&var);
1245 bool using_spline_bases =
false;
1246 if (!rational_vars.empty())
1250 for (
auto & elem : active_local_range.value())
1252 for (
auto rational_var : rational_vars)
1253 if (rational_var->active_on_subdomain(elem->subdomain_id()))
1255 using_spline_bases =
true;
1256 goto checked_on_splines;
1264 this->comm().max(using_spline_bases);
1266 if (using_spline_bases)
1267 this->solve_for_unconstrained_dofs(new_vector, is_adjoint);
1269 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1270 if (is_adjoint == -1)
1271 this->get_dof_map().enforce_constraints_exactly(*
this, &new_vector);
1272 else if (is_adjoint >= 0)
1273 this->get_dof_map().enforce_adjoint_constraints_exactly(new_vector,
1286 void System::boundary_project_solution (
const std::set<boundary_id_type> &
b,
1287 const std::vector<unsigned int> & variables,
1288 ValueFunctionPointer
fptr,
1289 GradientFunctionPointer
gptr,
1291 std::optional<ConstElemRange> active_local_range)
1296 this->boundary_project_solution(
b, variables, &f, &g, active_local_range);
1305 void System::boundary_project_solution (
const std::set<boundary_id_type> &
b,
1306 const std::vector<unsigned int> & variables,
1309 std::optional<ConstElemRange> active_local_range)
1311 this->boundary_project_vector(
b, variables, *solution, f, g, -1 , active_local_range);
1313 solution->localize(*current_local_solution);
1324 void System::boundary_project_vector (
const std::set<boundary_id_type> &
b,
1325 const std::vector<unsigned int> & variables,
1326 ValueFunctionPointer
fptr,
1327 GradientFunctionPointer
gptr,
1331 std::optional<ConstElemRange> active_local_range)
const 1335 this->boundary_project_vector(
b, variables, new_vector, &f, &g,
1336 is_adjoint, active_local_range);
1343 void System::boundary_project_vector (
const std::set<boundary_id_type> &
b,
1344 const std::vector<unsigned int> & variables,
1349 std::optional<ConstElemRange> active_local_range)
const 1351 LOG_SCOPE (
"boundary_project_vector()",
"System");
1353 if (!active_local_range)
1355 active_local_range.emplace
1356 (this->get_mesh().active_local_elements_begin(),
1357 this->get_mesh().active_local_elements_end());
1361 (active_local_range.value(),
1363 this->get_equation_systems().parameters,
1372 #ifdef LIBMESH_ENABLE_CONSTRAINTS 1373 if (is_adjoint == -1)
1374 this->get_dof_map().enforce_constraints_exactly(*
this, &new_vector);
1375 else if (is_adjoint >= 0)
1376 this->get_dof_map().enforce_adjoint_constraints_exactly(new_vector,
1385 #ifdef LIBMESH_ENABLE_AMR 1386 void BuildProjectionList::unique()
1390 std::sort(this->send_list.begin(),
1391 this->send_list.end());
1394 std::vector<dof_id_type>::iterator new_end =
1395 std::unique (this->send_list.begin(),
1396 this->send_list.end());
1400 std::vector<dof_id_type>
1401 (this->send_list.begin(), new_end).swap (this->send_list);
1409 const DofMap & dof_map = system.get_dof_map();
1416 std::vector<dof_id_type> di;
1419 for (
const auto & elem : range)
1435 if (!old_dof_object &&
1436 elem->refinement_flag() != Elem::JUST_REFINED &&
1437 elem->refinement_flag() != Elem::JUST_COARSENED)
1442 if (elem->refinement_flag() == Elem::JUST_REFINED)
1452 for (
auto & node : elem->node_ref_range())
1458 const unsigned int sysnum = system.number();
1459 const unsigned int nvg = old_dofs->
n_var_groups(sysnum);
1461 for (
unsigned int vg=0; vg != nvg; ++vg)
1463 const unsigned int nvig =
1464 old_dofs->
n_vars(sysnum, vg);
1465 for (
unsigned int vig=0; vig != nvig; ++vig)
1467 const unsigned int n_comp =
1469 for (
unsigned int c=0; c != n_comp; ++c)
1479 old_id == DofObject::invalid_id);
1480 di.push_back(old_id);
1487 std::sort(di.begin(), di.end());
1488 std::vector<dof_id_type>::iterator new_end =
1489 std::unique(di.begin(), di.end());
1490 std::vector<dof_id_type>(di.begin(), new_end).swap(di);
1492 else if (elem->refinement_flag() == Elem::JUST_COARSENED)
1494 std::vector<dof_id_type> di_child;
1496 for (
auto & child : elem->child_ref_range())
1499 di.insert(di.end(), di_child.begin(), di_child.end());
1505 for (
auto di_i : di)
1511 if (di_i == DofObject::invalid_id)
1514 libmesh_assert_less(di_i, dof_map.
n_old_dofs());
1515 if (di_i < first_old_dof || di_i >= end_old_dof)
1516 this->send_list.push_back(di_i);
1526 this->send_list.insert(this->send_list.end(),
1530 #endif // LIBMESH_ENABLE_AMR 1547 const unsigned int dim = system.get_mesh().mesh_dimension();
1550 const DofMap & dof_map = system.get_dof_map();
1554 system.get_mesh().get_boundary_info();
1569 const unsigned int var = variables[v];
1578 const unsigned int var_component =
1579 system.variable_scalar_number(var, 0);
1582 std::unique_ptr<FEBase> fe (FEBase::build(
dim, fe_type));
1590 const std::vector<std::vector<Real>> & phi = fe->get_phi();
1594 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1603 const std::vector<std::vector<RealGradient>> &
1604 ref_dphi = fe->get_dphi();
1609 const std::vector<Real> & JxW =
1613 const std::vector<Point> & xyz_values =
1617 std::vector<dof_id_type> dof_indices;
1619 std::vector<unsigned int> side_dofs;
1622 std::vector<boundary_id_type> bc_ids;
1625 for (
const auto & elem : range)
1632 const unsigned short n_nodes = elem->n_nodes();
1633 const unsigned short n_edges = elem->n_edges();
1634 const unsigned short n_sides = elem->n_sides();
1638 std::vector<bool> is_boundary_node(
n_nodes,
false),
1639 is_boundary_edge(n_edges,
false),
1640 is_boundary_side(n_sides,
false);
1643 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
1645 for (
unsigned char s=0; s != n_sides; ++s)
1649 bool do_this_side =
false;
1650 for (
const auto & bc_id : bc_ids)
1653 do_this_side =
true;
1659 is_boundary_side[s] =
true;
1662 for (
unsigned int n=0; n !=
n_nodes; ++n)
1663 if (elem->is_node_on_side(n,s))
1664 is_boundary_node[n] =
true;
1665 for (
unsigned int e=0; e != n_edges; ++e)
1666 if (elem->is_edge_on_side(e,s))
1667 is_boundary_edge[e] =
true;
1672 for (
unsigned int n=0; n !=
n_nodes; ++n)
1674 boundary_info.
boundary_ids (elem->node_ptr(n), bc_ids);
1676 for (
const auto & bc_id : bc_ids)
1679 is_boundary_node[n] =
true;
1680 is_boundary_nodeset[n] =
true;
1686 for (
unsigned short e=0; e != n_edges; ++e)
1690 for (
const auto & bc_id : bc_ids)
1692 is_boundary_edge[e] =
true;
1700 const unsigned int n_dofs =
1701 cast_int<unsigned int>(dof_indices.size());
1704 std::vector<char> dof_is_fixed(n_dofs,
false);
1705 std::vector<int> free_dof(n_dofs, 0);
1717 unsigned int current_dof = 0;
1718 for (
unsigned short n = 0; n !=
n_nodes; ++n)
1724 const unsigned int nc =
1725 FEInterface::n_dofs_at_node (fe_type, elem, n);
1727 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
1728 !is_boundary_nodeset[n])
1735 libmesh_assert_equal_to (nc, 0);
1741 libmesh_assert_equal_to (nc, 1);
1742 Ue(current_dof) = f->component(var_component,
1745 dof_is_fixed[current_dof] =
true;
1751 Ue(current_dof) = f->component(var_component,
1754 dof_is_fixed[current_dof] =
true;
1756 Gradient grad = g->component(var_component,
1760 Ue(current_dof) = grad(0);
1761 dof_is_fixed[current_dof] =
true;
1767 Point nxminus = elem->point(n),
1768 nxplus = elem->point(n);
1771 Gradient gxminus = g->component(var_component,
1774 Gradient gxplus = g->component(var_component,
1778 Ue(current_dof) = grad(1);
1779 dof_is_fixed[current_dof] =
true;
1782 Ue(current_dof) = (gxplus(1) - gxminus(1))
1784 dof_is_fixed[current_dof] =
true;
1791 Ue(current_dof) = grad(2);
1792 dof_is_fixed[current_dof] =
true;
1795 Ue(current_dof) = (gxplus(2) - gxminus(2))
1797 dof_is_fixed[current_dof] =
true;
1800 Point nyminus = elem->point(n),
1801 nyplus = elem->point(n);
1804 Gradient gyminus = g->component(var_component,
1807 Gradient gyplus = g->component(var_component,
1811 Ue(current_dof) = (gyplus(2) - gyminus(2))
1813 dof_is_fixed[current_dof] =
true;
1816 Point nxmym = elem->point(n),
1817 nxmyp = elem->point(n),
1818 nxpym = elem->point(n),
1819 nxpyp = elem->point(n);
1828 Gradient gxmym = g->component(var_component,
1831 Gradient gxmyp = g->component(var_component,
1834 Gradient gxpym = g->component(var_component,
1837 Gradient gxpyp = g->component(var_component,
1840 Number gxzplus = (gxpyp(2) - gxmyp(2))
1842 Number gxzminus = (gxpym(2) - gxmym(2))
1845 Ue(current_dof) = (gxzplus - gxzminus)
1847 dof_is_fixed[current_dof] =
true;
1850 #endif // LIBMESH_DIM > 2 1852 #endif // LIBMESH_DIM > 1 1857 else if (cont ==
C_ONE)
1859 libmesh_assert_equal_to (nc, 1 +
dim);
1860 Ue(current_dof) = f->component(var_component,
1863 dof_is_fixed[current_dof] =
true;
1865 Gradient grad = g->component(var_component,
1868 for (
unsigned int i=0; i!=
dim; ++i)
1870 Ue(current_dof) = grad(i);
1871 dof_is_fixed[current_dof] =
true;
1876 libmesh_error_msg(
"Unknown continuity " << cont);
1881 for (
unsigned short e = 0; e != n_edges; ++e)
1883 if (!is_boundary_edge[e])
1886 FEInterface::dofs_on_edge(elem,
dim, fe_type, e,
1889 const unsigned int n_side_dofs =
1890 cast_int<unsigned int>(side_dofs.size());
1894 unsigned int free_dofs = 0;
1896 if (!dof_is_fixed[side_dofs[i]])
1897 free_dof[free_dofs++] = i;
1909 fe->attach_quadrature_rule (qedgerule.get());
1910 fe->edge_reinit (elem, e);
1911 const unsigned int n_qp = qedgerule->n_points();
1914 for (
unsigned int qp=0; qp<n_qp; qp++)
1917 Number fineval = f->component(var_component,
1923 finegrad = g->component(var_component,
1928 for (
unsigned int sidei=0, freei=0;
1929 sidei != n_side_dofs; ++sidei)
1931 unsigned int i = side_dofs[sidei];
1933 if (dof_is_fixed[i])
1935 for (
unsigned int sidej=0, freej=0;
1936 sidej != n_side_dofs; ++sidej)
1938 unsigned int j = side_dofs[sidej];
1939 if (dof_is_fixed[j])
1940 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1943 Ke(freei,freej) += phi[i][qp] *
1944 phi[j][qp] * JxW[qp];
1947 if (dof_is_fixed[j])
1948 Fe(freei) -= ((*dphi)[i][qp] *
1952 Ke(freei,freej) += ((*dphi)[i][qp] *
1956 if (!dof_is_fixed[j])
1959 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1961 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1970 for (
unsigned int i=0; i != free_dofs; ++i)
1972 Number & ui = Ue(side_dofs[free_dof[i]]);
1976 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1982 for (
unsigned short s = 0; s != n_sides; ++s)
1984 if (!is_boundary_side[s])
1987 FEInterface::dofs_on_side(elem,
dim, fe_type, s,
1992 unsigned int free_dofs = 0;
1994 if (!dof_is_fixed[side_dofs[i]])
1995 free_dof[free_dofs++] = i;
2007 fe->attach_quadrature_rule (qsiderule.get());
2008 fe->reinit (elem, s);
2009 const unsigned int n_qp = qsiderule->n_points();
2011 const unsigned int n_side_dofs =
2012 cast_int<unsigned int>(side_dofs.size());
2015 for (
unsigned int qp=0; qp<n_qp; qp++)
2018 Number fineval = f->component(var_component,
2024 finegrad = g->component(var_component,
2029 for (
unsigned int sidei=0, freei=0;
2030 sidei != n_side_dofs; ++sidei)
2032 unsigned int i = side_dofs[sidei];
2034 if (dof_is_fixed[i])
2036 for (
unsigned int sidej=0, freej=0;
2037 sidej != n_side_dofs; ++sidej)
2039 unsigned int j = side_dofs[sidej];
2040 if (dof_is_fixed[j])
2041 Fe(freei) -= phi[i][qp] * phi[j][qp] *
2044 Ke(freei,freej) += phi[i][qp] *
2045 phi[j][qp] * JxW[qp];
2048 if (dof_is_fixed[j])
2049 Fe(freei) -= ((*dphi)[i][qp] *
2053 Ke(freei,freej) += ((*dphi)[i][qp] *
2057 if (!dof_is_fixed[j])
2060 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
2062 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
2071 for (
unsigned int i=0; i != free_dofs; ++i)
2073 Number & ui = Ue(side_dofs[free_dof[i]]);
2077 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
2082 first = new_vector.first_local_index(),
2083 last = new_vector.last_local_index();
2089 for (
unsigned int i = 0; i < n_dofs; i++)
2090 if (dof_is_fixed[i] &&
2091 (dof_indices[i] >= first) &&
2092 (dof_indices[i] < last))
2094 new_vector.set(dof_indices[i], Ue(i));
2103 int is_adjoint)
const 2105 const DofMap & dof_map = this->get_dof_map();
2107 std::unique_ptr<SparseMatrix<Number>> mat =
2110 std::unique_ptr<SparsityPattern::Build> sp;
2116 mat->attach_dof_map(dof_map);
2118 mat->attach_sparsity_pattern(*sp);
2123 libmesh_assert_equal_to(vec.
size(), dof_map.
n_dofs());
2126 std::unique_ptr<NumericVector<Number>> rhs =
2155 std::vector<dof_id_type> dof_indices(1, d);
2157 F(0) = (*this->solution)(d);
2159 (K, F, dof_indices,
false, is_adjoint);
2160 mat->add_matrix(K, dof_indices);
2161 rhs->add_vector(F, dof_indices);
2165 std::unique_ptr<LinearSolver<Number>> linear_solver =
2168 linear_solver->solve(*mat, vec, *rhs,
2169 double(this->get_equation_systems().parameters.get<
Real>(
"linear solver tolerance")),
2170 this->get_equation_systems().parameters.
get<
unsigned int>(
"linear solver maximum iterations"));
The GenericProjector class implements the core of other projection operations, using two input functo...
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
FEFamily family
The type of finite element.
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.
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
Solves the equation Ax=b for the unknown value x and rhs b based on the Cholesky factorization of A...
RefinementState refinement_flag() const
void eval_old_dofs(const Elem &elem, const FEType &fe_type, unsigned int sys_num, unsigned int var_num, std::vector< dof_id_type > &indices, std::vector< DSNA > &values)
Wrap a libMesh-style function pointer into a FunctionBase object.
dof_id_type end_dof(const processor_id_type proc) const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
const Elem * parent() const
OldSolutionCoefs(const libMesh::System &sys_in, const std::vector< unsigned int > *vars)
A Node is like a Point, but with more information.
virtual void zero() override final
Set every element in the vector to 0.
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
BuildProjectionList(const System &system_in)
SparseMatrix< ValOut > & target_matrix
This class provides the ability to map between arbitrary, user-defined strings and several data types...
unsigned int n_var_groups(const unsigned int s) const
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
Access multiple components at once.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
static constexpr Real TOLERANCE
const Elem & get_elem() const
Accessor for current Elem object.
std::unique_ptr< FunctionBase< Number > > f
dof_id_type end_old_dof(const processor_id_type proc) const
The OldSolutionBase input functor abstract base class is the root of the OldSolutionValue and OldSolu...
BoundaryProjectSolution(const std::set< boundary_id_type > &b_in, const std::vector< unsigned int > &variables_in, const System &system_in, FunctionBase< Number > *f_in, FunctionBase< Gradient > *g_in, const Parameters ¶meters_in, NumericVector< Number > &new_v_in)
virtual numeric_index_type size() const =0
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
void resize(const unsigned int n)
Resize the vector.
DynamicSparseNumberArray< Output, dof_id_type > type
std::unique_ptr< SparsityPattern::Build > build_sparsity(const MeshBase &mesh, bool calculate_constrained=false, bool use_condensed_system=false) const
Builds a sparsity pattern for matrices using the current degree-of-freedom numbering and coupling...
This is the base class from which all geometric element types are derived.
This class implements projecting an arbitrary boundary function to the current mesh.
RefinementState
Enumeration of possible element refinement states.
virtual std::unique_ptr< NumericVector< T > > clone() const =0
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
dof_id_type n_dofs(const unsigned int vn) const
The StoredRange class defines a contiguous, divisible set of objects.
void eval_mixed_derivatives(const FEMContext &libmesh_dbg_var(c), unsigned int i, unsigned int dim, const Node &n, std::vector< DSNA > &derivs)
The libMesh namespace provides an interface to certain functionality in the library.
The OldSolutionValue input functor class can be used with GenericProjector to read values from a solu...
const std::vector< unsigned int > & variables
dof_id_type n_local_dofs(const unsigned int vn) const
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.
void SCALAR_dof_indices(std::vector< dof_id_type > &di, const unsigned int vn, const bool old_dofs=false) const
Fills the vector di with the global degree of freedom indices corresponding to the SCALAR variable vn...
virtual numeric_index_type row_stop() const =0
const Variable & variable(const unsigned int c) const override
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value)=0
Set the element (i,j) to value.
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
This class provides a wrapper with which to evaluate a (libMesh-style) function pointer in a Function...
BuildProjectionList(BuildProjectionList &other, Threads::split)
const Parameters & parameters
This class handles the numbering of degrees of freedom on a mesh.
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
This base class can be inherited from to provide interfaces to linear solvers from different packages...
const std::vector< std::vector< OutputGradient > > & get_dphi() const
This class builds the send_list of old dof indices whose coefficients are needed to perform a project...
void libmesh_ignore(const Args &...)
const dof_id_type n_nodes
This class defines the notion of a variable in the system.
dof_id_type numeric_index_type
The MatrixFillAction output functor class can be used with GenericProjector to write solution transfe...
NumericVector< Number > & new_vector
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
VectorValue< DynamicSparseNumberArray< InnerOutput, dof_id_type > > type
Manages consistently variables, degrees of freedom, and coefficient vectors.
unsigned int n_systems() const
NumberVectorValue Gradient
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
bool is_constrained_dof(const dof_id_type dof) const
This class provides all data required for a physics package (e.g.
void insert(dof_id_type id, const DynamicSparseNumberArray< ValIn, dof_id_type > &val)
dof_id_type n_old_dofs() const
DofObject * get_old_dof_object()
Pointer accessor for previously public old_dof_object.
bool active_on_subdomain(subdomain_id_type sid) const
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
void update_sparsity_pattern(SparseMatrix< Number > &matrix) const
Additional matrices may be be temporarily initialized by this DofMap.
BoundaryProjectSolution(const BoundaryProjectSolution &in)
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
DofObject & get_old_dof_object_ref()
As above, but do not use in situations where the old_dof_object may be nullptr, since this function a...
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
Execute the provided reduction operation in parallel on the specified range.
OldSolutionCoefs(const OldSolutionCoefs &in)
ParallelType type() const
void heterogenously_constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void convert_from_receive(SendT &received, T &converted)
DynamicSparseNumberArray< Real, dof_id_type > DSNAN
std::vector< dof_id_type > send_list
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
void eval_old_dofs(const Elem &elem, unsigned int node_num, unsigned int var_num, std::vector< dof_id_type > &indices, std::vector< DSNA > &values)
virtual numeric_index_type row_start() const =0
For ease of communication, we allow users to translate their own value types to a more easily computa...
virtual numeric_index_type local_size() const =0
The OldSolutionCoefs input functor class can be used with GenericProjector to read solution transfer ...
virtual Output component(const FEMContext &, unsigned int i, const Point &p, Real time=0.)
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
Gradient gptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
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...
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
DynamicSparseNumberArray< ValIn, dof_id_type > InsertInput
MatrixFillAction(SparseMatrix< ValOut > &target_mat)
std::pair< unsigned int, unsigned int > var_to_vg_and_offset(const unsigned int s, const unsigned int var) const
virtual void clear()
Restores the NumericVector<T> to a pristine state.
virtual void set(const numeric_index_type i, const T value)=0
Sets v(i) = value.
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
Defines a dense vector for use in Finite Element-type computations.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
dof_id_type first_old_dof(const processor_id_type proc) const
dof_id_type first_dof(const processor_id_type proc) const
The VectorSetAction output functor class can be used with a GenericProjector to set projection values...
const std::set< boundary_id_type > & b
std::unique_ptr< FunctionBase< Gradient > > g
const TypeToSend< T >::type convert_to_send(const T &in)
unsigned int n_comp_group(const unsigned int s, const unsigned int vg) const
The FEMFunctionWrapper input functor class can be used with a GenericProjector to read values from an...
A Point defines a location in LIBMESH_DIM dimensional Real space.
DSNAOutput< Output >::type DSNA
void ErrorVector unsigned int
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
void insert(const std::vector< dof_id_type > &dof_indices, const std::vector< DynamicSparseNumberArray< ValIn, dof_id_type > > &Ue)
const Elem & get(const ElemType type_in)
This class forms the foundation from which generic finite elements may be derived.
void old_dof_indices(const Elem &elem, unsigned int n, std::vector< dof_id_type > &di, const unsigned int vn) const
Appends to the vector di the old global degree of freedom indices for elem.node_ref(n), for one variable vn.
const std::vector< std::vector< OutputShape > > & get_phi() const
const FEType & type() const
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.
virtual void localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.