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"
38using MetaPhysicL::DynamicSparseNumberArray;
44template <
typename T,
typename IndexType>
52template <
typename T,
typename IndexType,
typename T2>
56 MetaPhysicL::DynamicSparseNumberArray
62template <
typename T,
typename IndexType>
64 typedef std::vector<std::pair<IndexType,T>>
type;
67template <
typename T,
typename IndexType>
68const 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);
82template <
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"
131typedef DynamicSparseNumberArray<Real, dof_id_type>
DSNAN;
133template LIBMESH_EXPORT
void
136template LIBMESH_EXPORT
void
150#ifdef LIBMESH_ENABLE_AMR
174 system(other.system),
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;
314 Threads::parallel_reduce (active_local_range.value(),
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;
338 Threads::parallel_reduce (active_local_range.value(),
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, scalar_vars;
389 for (
auto var : vars)
391 if (this->variable(var).type().family ==
SCALAR)
392 scalar_vars.push_back(var);
393 else if (FEInterface::field_type(this->variable_type(var)) ==
TYPE_SCALAR)
394 regular_vars.push_back(var);
396 vector_vars.push_back(var);
401 if (!regular_vars.empty())
410 f(*
this, old_vector, ®ular_vars);
412 g(*
this, old_vector, ®ular_vars);
414 FEMProjector projector(*
this, f, &g, setter, regular_vars);
415 projector.project(active_local_range.value());
418 if (!vector_vars.empty())
428 FEMVectorProjector vector_projector(*
this, f_vector, &g_vector, setter, vector_vars);
429 vector_projector.project(active_local_range.value());
435 if (this->processor_id() == (this->n_processors()-1))
437 const DofMap & dof_map = this->get_dof_map();
438 for (
auto var : scalar_vars)
441 std::vector<dof_id_type> new_SCALAR_indices, old_SCALAR_indices;
445 new_vector.
set(new_SCALAR_indices[i], old_vector(old_SCALAR_indices[i]));
460 dist_v->init(this->n_dofs(), this->n_local_dofs(),
false,
PARALLEL);
464 if (new_vector(i) != 0.0)
465 dist_v->set(i, new_vector(i));
469 dist_v->localize (new_v, this->get_dof_map().get_send_list());
485 if(this->project_with_constraints)
487 if (is_adjoint == -1)
489 this->get_dof_map().enforce_constraints_exactly(*
this, &new_v);
491 else if (is_adjoint >= 0)
493 this->get_dof_map().enforce_adjoint_constraints_exactly(new_v,
508#ifdef LIBMESH_ENABLE_AMR
509#ifdef LIBMESH_HAVE_METAPHYSICL
511template <
typename Output>
515 typedef DynamicSparseNumberArray<Output, dof_id_type>
type;
518template <
typename InnerOutput>
534template <
typename Output,
547 const std::vector<unsigned int> * vars) :
550 this->old_context.set_algebraic_type(FEMContext::OLD_DOFS_ONLY);
554 OldSolutionBase<Output, point_output>(in.sys, in.old_context.active_vars())
556 this->old_context.set_algebraic_type(FEMContext::OLD_DOFS_ONLY);
561 unsigned int elem_dim,
563 bool extra_hanging_dofs,
570 bool skip_context_check);
576 std::vector<DSNA> & derivs)
578 LOG_SCOPE (
"eval_mixed_derivatives",
"OldSolutionCoefs");
581 libmesh_assert_less(c.get_elem().get_node_index(&n),
582 c.get_elem().n_vertices());
585 libmesh_assert_less(i, this->component_to_var.size());
586 unsigned int var = this->component_to_var[i];
589 const unsigned int n_mixed = (
dim-1) * (
dim-1);
590 derivs.resize(n_mixed);
595 if (old_dof_object &&
596 old_dof_object->
n_vars(this->sys.number()) &&
597 old_dof_object->
n_comp(this->sys.number(), var))
601 std::vector<dof_id_type> old_ids(n_mixed);
602 std::iota(old_ids.begin(), old_ids.end(), first_old_id);
606 derivs[d_i].resize(1);
607 derivs[d_i].raw_at(0) = 1;
608 derivs[d_i].raw_index(0) = old_ids[d_i];
613 std::fill(derivs.begin(), derivs.end(), 0);
619 unsigned int node_num,
620 unsigned int var_num,
621 std::vector<dof_id_type> & indices,
622 std::vector<DSNA> & values)
624 LOG_SCOPE (
"eval_old_dofs(node)",
"OldSolutionCoefs");
630 this->sys.get_dof_map().dof_indices(elem, node_num, indices, var_num);
632 std::vector<dof_id_type> old_indices;
634 this->sys.get_dof_map().old_dof_indices(elem, node_num, old_indices, var_num);
636 libmesh_assert_equal_to (old_indices.size(), indices.size());
638 values.resize(old_indices.size());
643 values[i].raw_at(0) = 1;
644 values[i].raw_index(0) = old_indices[i];
651 unsigned int sys_num,
652 unsigned int var_num,
653 std::vector<dof_id_type> & indices,
654 std::vector<DSNA> & values)
656 LOG_SCOPE (
"eval_old_dofs(elem)",
"OldSolutionCoefs");
660 const Elem & old_elem =
665 const unsigned int nc =
666 FEInterface::n_dofs_per_elem(fe_type, &elem);
668 std::vector<dof_id_type> old_dof_indices(nc);
678 const auto [vg, vig] =
681 const unsigned int n_comp = elem.
n_comp_group(sys_num,vg);
682 libmesh_assert_greater(elem.
n_systems(), sys_num);
683 libmesh_assert_greater_equal(n_comp, nc);
685 for (
unsigned int i=0; i<nc; i++)
688 old_dof_object.
dof_number(sys_num, vg, vig, i, n_comp);
691 libmesh_assert_not_equal_to (d_old, DofObject::invalid_id);
692 libmesh_assert_not_equal_to (d_new, DofObject::invalid_id);
694 old_dof_indices[i] = d_old;
699 values.resize(old_dof_indices.size());
704 values[i].raw_at(0) = 1;
705 values[i].raw_index(0) = old_dof_indices[i];
714DynamicSparseNumberArray<Real, dof_id_type>
720 bool skip_context_check)
722 LOG_SCOPE (
"eval_at_point()",
"OldSolutionCoefs");
724 if (!skip_context_check)
725 if (!this->check_old_context(c, p))
730 this->old_context.get_element_fe<
Real>
731 (i, fe, this->old_context.get_elem_dim());
735 this->old_context.build_new_fe(fe, p);
738 const std::vector<std::vector<Real> > & phi = fe_new->
get_phi();
739 const std::vector<dof_id_type> & dof_indices =
740 this->old_context.get_dof_indices(i);
742 const std::size_t n_dofs = phi.size();
743 libmesh_assert_equal_to(n_dofs, dof_indices.size());
745 DynamicSparseNumberArray<Real, dof_id_type> returnval;
746 returnval.resize(n_dofs);
750 returnval.raw_at(j) = phi[j][0];
751 returnval.raw_index(j) = dof_indices[j];
767 bool skip_context_check)
769 LOG_SCOPE (
"eval_at_point()",
"OldSolutionCoefs");
771 if (!skip_context_check)
772 if (!this->check_old_context(c, p))
777 this->old_context.get_element_fe<
Real>
778 (i, fe, this->old_context.get_elem_dim());
782 this->old_context.build_new_fe(fe, p);
785 const std::vector<std::vector<RealGradient> > & dphi = fe_new->
get_dphi();
786 const std::vector<dof_id_type> & dof_indices =
787 this->old_context.get_dof_indices(i);
789 const std::size_t n_dofs = dphi.size();
790 libmesh_assert_equal_to(n_dofs, dof_indices.size());
794 for (
unsigned int d = 0; d != LIBMESH_DIM; ++d)
795 returnval(d).resize(n_dofs);
798 for (
int d = 0; d != LIBMESH_DIM; ++d)
800 returnval(d).raw_at(j) = dphi[j][0](d);
801 returnval(d).raw_index(j) = dof_indices[j];
810DynamicSparseNumberArray<Real, dof_id_type>
816 bool extra_hanging_dofs,
819 LOG_SCOPE (
"Real eval_at_node()",
"OldSolutionCoefs");
834 if (old_dof_object &&
835 (!extra_hanging_dofs ||
836 flag == Elem::JUST_COARSENED ||
837 flag == Elem::DO_NOTHING) &&
838 old_dof_object->
n_vars(sys.number()) &&
839 old_dof_object->
n_comp(sys.number(), i))
841 DynamicSparseNumberArray<Real, dof_id_type> returnval;
843 old_dof_object->
dof_number(sys.number(), i, 0);
845 returnval.raw_at(0) = 1;
846 returnval.raw_index(0) = old_id;
850 return this->eval_at_point(c, i, n, 0,
false);
861 unsigned int elem_dim,
863 bool extra_hanging_dofs,
866 LOG_SCOPE (
"RealGradient eval_at_node()",
"OldSolutionCoefs");
881 if (old_dof_object &&
882 (!extra_hanging_dofs ||
883 flag == Elem::JUST_COARSENED ||
884 flag == Elem::DO_NOTHING) &&
885 old_dof_object->
n_vars(sys.number()) &&
886 old_dof_object->
n_comp(sys.number(), i))
889 for (
unsigned int d = 0; d != elem_dim; ++d)
892 old_dof_object->
dof_number(sys.number(), i, d+1);
895 g(d).raw_index(0) = old_id;
900 return this->eval_at_point(c, i, n, 0,
false);
913template <
typename ValIn,
typename ValOut>
923 target_matrix(target_mat) {}
926 const DynamicSparseNumberArray<ValIn, dof_id_type> & val)
930 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
932 const std::size_t dnsa_size = val.size();
933 for (
unsigned int j = 0; j != dnsa_size; ++j)
936 const ValIn dof_val = val.raw_at(j);
937 target_matrix.
set(
id, dof_j, dof_val);
943 void insert(
const std::vector<dof_id_type> & dof_indices,
944 const std::vector<DynamicSparseNumberArray<ValIn, dof_id_type> > & Ue)
950 unsigned int size = Ue.size();
952 libmesh_assert_equal_to(size, dof_indices.size());
956 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
958 for (
unsigned int i = 0; i != size; ++i)
961 if ((dof_i >= begin_dof) && (dof_i < end_dof))
963 const DynamicSparseNumberArray<ValIn,dof_id_type> & dnsa = Ue[i];
964 const std::size_t dnsa_size = dnsa.size();
965 for (
unsigned int j = 0; j != dnsa_size; ++j)
968 const ValIn dof_val = dnsa.raw_at(j);
969 target_matrix.
set(dof_i, dof_j, dof_val);
985 LOG_SCOPE (
"projection_matrix()",
"System");
987 const unsigned int n_variables = this->
n_vars();
992 (this->get_mesh().active_local_elements_begin(),
993 this->get_mesh().active_local_elements_end());
995 std::vector<unsigned int> vars(n_variables);
996 std::iota(vars.begin(), vars.end(), 0);
1004 OldSolutionGradientCoefs,
1005 DynamicSparseNumberArray<Real,dof_id_type>,
1008 OldSolutionValueCoefs f(*
this, &vars);
1009 OldSolutionGradientCoefs g(*
this, &vars);
1012 ProjMatFiller mat_filler(*
this, f, &g, setter, vars);
1013 mat_filler.project(active_local_elem_range);
1018 if (this->processor_id() == (this->n_processors()-1))
1020 const DofMap & dof_map = this->get_dof_map();
1022 if (this->variable(var).type().family ==
SCALAR)
1025 std::vector<dof_id_type> new_SCALAR_indices, old_SCALAR_indices;
1028 const unsigned int new_n_dofs =
1029 cast_int<unsigned int>(new_SCALAR_indices.size());
1031 for (
unsigned int i=0; i<new_n_dofs; i++)
1033 proj_mat.
set( new_SCALAR_indices[i],
1034 old_SCALAR_indices[i], 1);
1049void System::project_solution (ValueFunctionPointer
fptr,
1050 GradientFunctionPointer
gptr,
1052 std::optional<ConstElemRange> active_local_range,
1053 std::optional<std::vector<unsigned int>> variable_numbers)
const
1057 this->project_solution(&f, &g, active_local_range, variable_numbers);
1067 std::optional<ConstElemRange> active_local_range,
1068 std::optional<std::vector<unsigned int>> variable_numbers)
const
1070 this->project_vector(*solution, f, g, -1, active_local_range, variable_numbers);
1072 solution->localize(*current_local_solution, _dof_map->get_send_list());
1082 std::optional<ConstElemRange> active_local_range,
1083 std::optional<std::vector<unsigned int>> variable_numbers)
const
1085 this->project_vector(*solution, f, g, -1, active_local_range, variable_numbers);
1087 solution->localize(*current_local_solution, _dof_map->get_send_list());
1095void System::project_vector (ValueFunctionPointer
fptr,
1096 GradientFunctionPointer
gptr,
1100 std::optional<ConstElemRange> active_local_range,
1101 std::optional<std::vector<unsigned int>> variable_numbers)
const
1105 this->project_vector(new_vector, &f, &g, is_adjoint, active_local_range, variable_numbers);
1116 std::optional<ConstElemRange> active_local_range,
1117 std::optional<std::vector<unsigned int>> variable_numbers)
const
1119 LOG_SCOPE (
"project_vector(FunctionBase)",
"System");
1129 this->project_vector(new_vector, &f_fem, &g_fem, is_adjoint, active_local_range, variable_numbers);
1132 this->project_vector(new_vector, &f_fem,
nullptr, is_adjoint, active_local_range, variable_numbers);
1144 std::optional<ConstElemRange> active_local_range,
1145 std::optional<std::vector<unsigned int>> variable_numbers)
const
1147 LOG_SCOPE (
"project_fem_vector()",
"System");
1151 if (!active_local_range)
1153 active_local_range.emplace
1154 (this->get_mesh().active_local_elements_begin(),
1155 this->get_mesh().active_local_elements_end());
1160 const unsigned int n_variables = this->
n_vars();
1162 std::vector<unsigned int> vars;
1163 if (variable_numbers)
1165 vars = *variable_numbers;
1167 if (v >= n_variables)
1168 libmesh_error_msg(
"ERROR: variable number " << v <<
1169 " out of range for system with " <<
1170 n_variables <<
" variables.");
1174 vars.resize(n_variables);
1175 std::iota(vars.begin(), vars.end(), 0);
1190 FEMProjector projector(*
this, fw, &gw, setter, vars);
1191 projector.project(active_local_range.value());
1195 FEMProjector projector(*
this, fw,
nullptr, setter, vars);
1196 projector.project(active_local_range.value());
1202 if (this->processor_id() == (this->n_processors()-1))
1207 const DofMap & dof_map = this->get_dof_map();
1208 for (
auto var : vars)
1209 if (this->variable(var).type().family ==
SCALAR)
1214 context.
pre_fe_reinit(*
this, *(this->get_mesh().active_local_elements_begin()));
1216 std::vector<dof_id_type> SCALAR_indices;
1218 const unsigned int n_SCALAR_dofs =
1219 cast_int<unsigned int>(SCALAR_indices.size());
1221 for (
unsigned int i=0; i<n_SCALAR_dofs; i++)
1223 const dof_id_type global_index = SCALAR_indices[i];
1224 const unsigned int component_index =
1225 this->variable_scalar_number(var,i);
1227 new_vector.
set(global_index, f->
component(context, component_index,
Point(), this->time));
1236 std::vector<const Variable *> rational_vars;
1237 for (
auto varnum : vars)
1239 const Variable & var = this->get_dof_map().variable(varnum);
1241 rational_vars.push_back(&var);
1246 bool using_spline_bases =
false;
1247 if (!rational_vars.empty())
1251 for (
auto & elem : active_local_range.value())
1253 for (
auto rational_var : rational_vars)
1254 if (rational_var->active_on_subdomain(elem->subdomain_id()))
1256 using_spline_bases =
true;
1257 goto checked_on_splines;
1265 this->comm().max(using_spline_bases);
1267 if (using_spline_bases)
1268 this->solve_for_unconstrained_dofs(new_vector, is_adjoint);
1270#ifdef LIBMESH_ENABLE_CONSTRAINTS
1271 if (is_adjoint == -1)
1272 this->get_dof_map().enforce_constraints_exactly(*
this, &new_vector);
1273 else if (is_adjoint >= 0)
1274 this->get_dof_map().enforce_adjoint_constraints_exactly(new_vector,
1287void System::boundary_project_solution (
const std::set<boundary_id_type> &
b,
1288 const std::vector<unsigned int> & variables,
1289 ValueFunctionPointer
fptr,
1290 GradientFunctionPointer
gptr,
1292 std::optional<ConstElemRange> active_local_range)
1297 this->boundary_project_solution(
b, variables, &f, &g, active_local_range);
1306void System::boundary_project_solution (
const std::set<boundary_id_type> &
b,
1307 const std::vector<unsigned int> & variables,
1310 std::optional<ConstElemRange> active_local_range)
1312 this->boundary_project_vector(
b, variables, *solution, f, g, -1 , active_local_range);
1314 solution->localize(*current_local_solution);
1325void System::boundary_project_vector (
const std::set<boundary_id_type> &
b,
1326 const std::vector<unsigned int> & variables,
1327 ValueFunctionPointer
fptr,
1328 GradientFunctionPointer
gptr,
1332 std::optional<ConstElemRange> active_local_range)
const
1336 this->boundary_project_vector(
b, variables, new_vector, &f, &g,
1337 is_adjoint, active_local_range);
1344void System::boundary_project_vector (
const std::set<boundary_id_type> &
b,
1345 const std::vector<unsigned int> & variables,
1350 std::optional<ConstElemRange> active_local_range)
const
1352 LOG_SCOPE (
"boundary_project_vector()",
"System");
1354 if (!active_local_range)
1356 active_local_range.emplace
1357 (this->get_mesh().active_local_elements_begin(),
1358 this->get_mesh().active_local_elements_end());
1361 Threads::parallel_for
1362 (active_local_range.value(),
1364 this->get_equation_systems().parameters,
1373#ifdef LIBMESH_ENABLE_CONSTRAINTS
1374 if (is_adjoint == -1)
1375 this->get_dof_map().enforce_constraints_exactly(*
this, &new_vector);
1376 else if (is_adjoint >= 0)
1377 this->get_dof_map().enforce_adjoint_constraints_exactly(new_vector,
1386#ifdef LIBMESH_ENABLE_AMR
1387void BuildProjectionList::unique()
1391 std::sort(this->send_list.begin(),
1392 this->send_list.end());
1395 std::vector<dof_id_type>::iterator new_end =
1396 std::unique (this->send_list.begin(),
1397 this->send_list.end());
1401 std::vector<dof_id_type>
1402 (this->send_list.begin(), new_end).swap (this->send_list);
1410 const DofMap & dof_map = system.get_dof_map();
1417 std::vector<dof_id_type> di;
1420 for (
const auto & elem : range)
1436 if (!old_dof_object &&
1437 elem->refinement_flag() != Elem::JUST_REFINED &&
1438 elem->refinement_flag() != Elem::JUST_COARSENED)
1443 if (elem->refinement_flag() == Elem::JUST_REFINED)
1453 for (
auto & node : elem->node_ref_range())
1459 const unsigned int sysnum = system.number();
1460 const unsigned int nvg = old_dofs->
n_var_groups(sysnum);
1462 for (
unsigned int vg=0; vg != nvg; ++vg)
1464 const unsigned int nvig =
1465 old_dofs->
n_vars(sysnum, vg);
1466 for (
unsigned int vig=0; vig != nvig; ++vig)
1468 const unsigned int n_comp =
1470 for (
unsigned int c=0; c != n_comp; ++c)
1480 old_id == DofObject::invalid_id);
1481 di.push_back(old_id);
1488 std::sort(di.begin(), di.end());
1489 std::vector<dof_id_type>::iterator new_end =
1490 std::unique(di.begin(), di.end());
1491 std::vector<dof_id_type>(di.begin(), new_end).swap(di);
1493 else if (elem->refinement_flag() == Elem::JUST_COARSENED)
1495 std::vector<dof_id_type> di_child;
1497 for (
auto & child : elem->child_ref_range())
1500 di.insert(di.end(), di_child.begin(), di_child.end());
1506 for (
auto di_i : di)
1512 if (di_i == DofObject::invalid_id)
1515 libmesh_assert_less(di_i, dof_map.
n_old_dofs());
1516 if (di_i < first_old_dof || di_i >= end_old_dof)
1517 this->send_list.push_back(di_i);
1527 this->send_list.insert(this->send_list.end(),
1548 const unsigned int dim = system.get_mesh().mesh_dimension();
1551 const DofMap & dof_map = system.get_dof_map();
1555 system.get_mesh().get_boundary_info();
1570 const unsigned int var = variables[v];
1579 const unsigned int var_component =
1580 system.variable_scalar_number(var, 0);
1583 std::unique_ptr<FEBase> fe (FEBase::build(
dim, fe_type));
1591 const std::vector<std::vector<Real>> & phi = fe->get_phi();
1595 const std::vector<std::vector<RealGradient>> * dphi =
nullptr;
1604 const std::vector<std::vector<RealGradient>> &
1605 ref_dphi = fe->get_dphi();
1610 const std::vector<Real> & JxW =
1614 const std::vector<Point> & xyz_values =
1618 std::vector<dof_id_type> dof_indices;
1620 std::vector<unsigned int> side_dofs;
1623 std::vector<boundary_id_type> bc_ids;
1626 for (
const auto & elem : range)
1633 const unsigned short n_nodes = elem->n_nodes();
1634 const unsigned short n_edges = elem->n_edges();
1635 const unsigned short n_sides = elem->n_sides();
1639 std::vector<bool> is_boundary_node(
n_nodes,
false),
1640 is_boundary_edge(n_edges,
false),
1641 is_boundary_side(n_sides,
false);
1644 std::vector<bool> is_boundary_nodeset(
n_nodes,
false);
1646 for (
unsigned char s=0; s != n_sides; ++s)
1650 bool do_this_side =
false;
1651 for (
const auto & bc_id : bc_ids)
1654 do_this_side =
true;
1660 is_boundary_side[s] =
true;
1663 for (
unsigned int n=0; n !=
n_nodes; ++n)
1664 if (elem->is_node_on_side(n,s))
1665 is_boundary_node[n] =
true;
1666 for (
unsigned int e=0; e != n_edges; ++e)
1667 if (elem->is_edge_on_side(e,s))
1668 is_boundary_edge[e] =
true;
1673 for (
unsigned int n=0; n !=
n_nodes; ++n)
1675 boundary_info.
boundary_ids (elem->node_ptr(n), bc_ids);
1677 for (
const auto & bc_id : bc_ids)
1680 is_boundary_node[n] =
true;
1681 is_boundary_nodeset[n] =
true;
1687 for (
unsigned short e=0; e != n_edges; ++e)
1691 for (
const auto & bc_id : bc_ids)
1693 is_boundary_edge[e] =
true;
1701 const unsigned int n_dofs =
1702 cast_int<unsigned int>(dof_indices.size());
1705 std::vector<char> dof_is_fixed(n_dofs,
false);
1706 std::vector<int> free_dof(n_dofs, 0);
1718 unsigned int current_dof = 0;
1719 for (
unsigned short n = 0; n !=
n_nodes; ++n)
1725 const unsigned int nc =
1726 FEInterface::n_dofs_at_node (fe_type, elem, n);
1728 if ((!elem->is_vertex(n) || !is_boundary_node[n]) &&
1729 !is_boundary_nodeset[n])
1736 libmesh_assert_equal_to (nc, 0);
1742 libmesh_assert_equal_to (nc, 1);
1743 Ue(current_dof) = f->component(var_component,
1746 dof_is_fixed[current_dof] =
true;
1752 Ue(current_dof) = f->component(var_component,
1755 dof_is_fixed[current_dof] =
true;
1757 Gradient grad = g->component(var_component,
1761 Ue(current_dof) = grad(0);
1762 dof_is_fixed[current_dof] =
true;
1768 Point nxminus = elem->point(n),
1769 nxplus = elem->point(n);
1770 nxminus(0) -= TOLERANCE;
1771 nxplus(0) += TOLERANCE;
1772 Gradient gxminus = g->component(var_component,
1775 Gradient gxplus = g->component(var_component,
1779 Ue(current_dof) = grad(1);
1780 dof_is_fixed[current_dof] =
true;
1783 Ue(current_dof) = (gxplus(1) - gxminus(1))
1785 dof_is_fixed[current_dof] =
true;
1792 Ue(current_dof) = grad(2);
1793 dof_is_fixed[current_dof] =
true;
1796 Ue(current_dof) = (gxplus(2) - gxminus(2))
1798 dof_is_fixed[current_dof] =
true;
1801 Point nyminus = elem->point(n),
1802 nyplus = elem->point(n);
1803 nyminus(1) -= TOLERANCE;
1804 nyplus(1) += TOLERANCE;
1805 Gradient gyminus = g->component(var_component,
1808 Gradient gyplus = g->component(var_component,
1812 Ue(current_dof) = (gyplus(2) - gyminus(2))
1814 dof_is_fixed[current_dof] =
true;
1817 Point nxmym = elem->point(n),
1818 nxmyp = elem->point(n),
1819 nxpym = elem->point(n),
1820 nxpyp = elem->point(n);
1821 nxmym(0) -= TOLERANCE;
1822 nxmym(1) -= TOLERANCE;
1823 nxmyp(0) -= TOLERANCE;
1824 nxmyp(1) += TOLERANCE;
1825 nxpym(0) += TOLERANCE;
1826 nxpym(1) -= TOLERANCE;
1827 nxpyp(0) += TOLERANCE;
1828 nxpyp(1) += TOLERANCE;
1829 Gradient gxmym = g->component(var_component,
1832 Gradient gxmyp = g->component(var_component,
1835 Gradient gxpym = g->component(var_component,
1838 Gradient gxpyp = g->component(var_component,
1841 Number gxzplus = (gxpyp(2) - gxmyp(2))
1843 Number gxzminus = (gxpym(2) - gxmym(2))
1846 Ue(current_dof) = (gxzplus - gxzminus)
1848 dof_is_fixed[current_dof] =
true;
1858 else if (cont ==
C_ONE)
1860 libmesh_assert_equal_to (nc, 1 +
dim);
1861 Ue(current_dof) = f->component(var_component,
1864 dof_is_fixed[current_dof] =
true;
1866 Gradient grad = g->component(var_component,
1869 for (
unsigned int i=0; i!=
dim; ++i)
1871 Ue(current_dof) = grad(i);
1872 dof_is_fixed[current_dof] =
true;
1877 libmesh_error_msg(
"Unknown continuity " << cont);
1882 for (
unsigned short e = 0; e != n_edges; ++e)
1884 if (!is_boundary_edge[e])
1887 FEInterface::dofs_on_edge(elem,
dim, fe_type, e,
1890 const unsigned int n_side_dofs =
1891 cast_int<unsigned int>(side_dofs.size());
1895 unsigned int free_dofs = 0;
1897 if (!dof_is_fixed[side_dofs[i]])
1898 free_dof[free_dofs++] = i;
1910 fe->attach_quadrature_rule (qedgerule.get());
1911 fe->edge_reinit (elem, e);
1912 const unsigned int n_qp = qedgerule->n_points();
1915 for (
unsigned int qp=0; qp<n_qp; qp++)
1918 Number fineval = f->component(var_component,
1924 finegrad = g->component(var_component,
1929 for (
unsigned int sidei=0, freei=0;
1930 sidei != n_side_dofs; ++sidei)
1932 unsigned int i = side_dofs[sidei];
1934 if (dof_is_fixed[i])
1936 for (
unsigned int sidej=0, freej=0;
1937 sidej != n_side_dofs; ++sidej)
1939 unsigned int j = side_dofs[sidej];
1940 if (dof_is_fixed[j])
1941 Fe(freei) -= phi[i][qp] * phi[j][qp] *
1944 Ke(freei,freej) += phi[i][qp] *
1945 phi[j][qp] * JxW[qp];
1948 if (dof_is_fixed[j])
1949 Fe(freei) -= ((*dphi)[i][qp] *
1953 Ke(freei,freej) += ((*dphi)[i][qp] *
1957 if (!dof_is_fixed[j])
1960 Fe(freei) += phi[i][qp] * fineval * JxW[qp];
1962 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
1971 for (
unsigned int i=0; i != free_dofs; ++i)
1973 Number & ui = Ue(side_dofs[free_dof[i]]);
1975 std::abs(ui - Uedge(i)) < TOLERANCE);
1977 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
1983 for (
unsigned short s = 0; s != n_sides; ++s)
1985 if (!is_boundary_side[s])
1988 FEInterface::dofs_on_side(elem,
dim, fe_type, s,
1993 unsigned int free_dofs = 0;
1995 if (!dof_is_fixed[side_dofs[i]])
1996 free_dof[free_dofs++] = i;
2008 fe->attach_quadrature_rule (qsiderule.get());
2009 fe->reinit (elem, s);
2010 const unsigned int n_qp = qsiderule->n_points();
2012 const unsigned int n_side_dofs =
2013 cast_int<unsigned int>(side_dofs.size());
2016 for (
unsigned int qp=0; qp<n_qp; qp++)
2019 Number fineval = f->component(var_component,
2025 finegrad = g->component(var_component,
2030 for (
unsigned int sidei=0, freei=0;
2031 sidei != n_side_dofs; ++sidei)
2033 unsigned int i = side_dofs[sidei];
2035 if (dof_is_fixed[i])
2037 for (
unsigned int sidej=0, freej=0;
2038 sidej != n_side_dofs; ++sidej)
2040 unsigned int j = side_dofs[sidej];
2041 if (dof_is_fixed[j])
2042 Fe(freei) -= phi[i][qp] * phi[j][qp] *
2045 Ke(freei,freej) += phi[i][qp] *
2046 phi[j][qp] * JxW[qp];
2049 if (dof_is_fixed[j])
2050 Fe(freei) -= ((*dphi)[i][qp] *
2054 Ke(freei,freej) += ((*dphi)[i][qp] *
2058 if (!dof_is_fixed[j])
2061 Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
2063 Fe(freei) += (finegrad * (*dphi)[i][qp]) *
2072 for (
unsigned int i=0; i != free_dofs; ++i)
2074 Number & ui = Ue(side_dofs[free_dof[i]]);
2076 std::abs(ui - Uside(i)) < TOLERANCE);
2078 dof_is_fixed[side_dofs[free_dof[i]]] =
true;
2083 first = new_vector.first_local_index(),
2084 last = new_vector.last_local_index();
2088 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
2090 for (
unsigned int i = 0; i < n_dofs; i++)
2091 if (dof_is_fixed[i] &&
2092 (dof_indices[i] >= first) &&
2093 (dof_indices[i] < last))
2095 new_vector.set(dof_indices[i], Ue(i));
2104 int is_adjoint)
const
2106 const DofMap & dof_map = this->get_dof_map();
2108 std::unique_ptr<SparseMatrix<Number>> mat =
2111 std::unique_ptr<SparsityPattern::Build> sp;
2117 mat->attach_dof_map(dof_map);
2119 mat->attach_sparsity_pattern(*sp);
2124 libmesh_assert_equal_to(vec.
size(), dof_map.
n_dofs());
2127 std::unique_ptr<NumericVector<Number>> rhs =
2156 std::vector<dof_id_type> dof_indices(1, d);
2158 F(0) = (*this->solution)(d);
2160 (K, F, dof_indices,
false, is_adjoint);
2161 mat->add_matrix(K, dof_indices);
2162 rhs->add_vector(F, dof_indices);
2166 std::unique_ptr<LinearSolver<Number>> linear_solver =
2169 linear_solver->solve(*mat, vec, *rhs,
2170 double(this->get_equation_systems().parameters.get<
Real>(
"linear solver tolerance")),
2171 this->get_equation_systems().parameters.
get<
unsigned int>(
"linear solver maximum iterations"));
void ErrorVector unsigned int
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
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 implements projecting an arbitrary boundary function to the current mesh.
const std::vector< unsigned int > & variables
BoundaryProjectSolution(const BoundaryProjectSolution &in)
std::unique_ptr< FunctionBase< Gradient > > g
std::unique_ptr< FunctionBase< Number > > f
NumericVector< Number > & new_vector
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)
const std::set< boundary_id_type > & b
const Parameters & parameters
This class builds the send_list of old dof indices whose coefficients are needed to perform a project...
BuildProjectionList(const System &system_in)
BuildProjectionList(BuildProjectionList &other, Threads::split)
std::vector< dof_id_type > send_list
VectorValue< DynamicSparseNumberArray< InnerOutput, dof_id_type > > type
DynamicSparseNumberArray< Output, dof_id_type > type
Defines a dense matrix for use in Finite Element-type computations.
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
For symmetric positive definite (SPD) matrices.
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.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
Defines a dense vector for use in Finite Element-type computations.
void resize(const unsigned int n)
Resize the vector.
virtual void zero() override final
Set every element in the vector to 0.
dof_id_type end_old_dof(const processor_id_type proc) const
dof_id_type first_dof(const processor_id_type proc) const
dof_id_type n_old_dofs() const
dof_id_type first_old_dof(const processor_id_type proc) const
dof_id_type end_dof(const processor_id_type proc) const
This class handles the numbering of degrees of freedom on a mesh.
dof_id_type n_local_dofs(const unsigned int vn) const
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
void update_sparsity_pattern(SparseMatrix< Number > &matrix) const
Additional matrices may be be temporarily initialized by this DofMap.
bool computed_sparsity_already() const
Returns true iff a sparsity pattern has already been computed.
bool is_constrained_dof(const dof_id_type dof) const
const Variable & variable(const unsigned int c) const override
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...
dof_id_type n_dofs(const unsigned int vn) const
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),...
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
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.
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
unsigned int n_systems() const
unsigned int n_comp(const unsigned int s, const unsigned int var) const
unsigned int n_comp_group(const unsigned int s, const unsigned int vg) const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
std::pair< unsigned int, unsigned int > var_to_vg_and_offset(const unsigned int s, const unsigned int var) const
unsigned int n_var_groups(const unsigned int s) const
DofObject * get_old_dof_object()
Pointer accessor for previously public old_dof_object.
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...
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
This is the base class from which all geometric element types are derived.
RefinementState refinement_flag() const
const Elem * parent() const
RefinementState
Enumeration of possible element refinement states.
This class forms the foundation from which generic finite elements may be derived.
const std::vector< std::vector< OutputShape > > & get_phi() const
const std::vector< std::vector< OutputGradient > > & get_dphi() const
This class provides all data required for a physics package (e.g.
virtual void pre_fe_reinit(const System &, const Elem *e)
Reinitializes local data vectors/matrices on the current geometric element.
const Elem & get_elem() const
Accessor for current Elem object.
FEMFunctionBase is a base class from which users can derive in order to define "function-like" object...
virtual Output component(const FEMContext &, unsigned int i, const Point &p, Real time=0.)
The FEMFunctionWrapper input functor class can be used with a GenericProjector to read values from an...
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
FEFamily family
The type of finite element.
Base class for functors that can be evaluated at a point and (optionally) time.
The GenericProjector class implements the core of other projection operations, using two input functo...
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
This base class can be inherited from to provide interfaces to linear solvers from different packages...
The MatrixFillAction output functor class can be used with GenericProjector to write solution transfe...
DynamicSparseNumberArray< ValIn, dof_id_type > InsertInput
void insert(const std::vector< dof_id_type > &dof_indices, const std::vector< DynamicSparseNumberArray< ValIn, dof_id_type > > &Ue)
SparseMatrix< ValOut > & target_matrix
void insert(dof_id_type id, const DynamicSparseNumberArray< ValIn, dof_id_type > &val)
MatrixFillAction(SparseMatrix< ValOut > &target_mat)
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 void clear()
Restores the NumericVector<T> to a pristine state.
ParallelType type() const
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
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 localize(std::vector< T > &v_local) const =0
Creates a copy of the global vector in the local vector v_local.
virtual numeric_index_type size() const =0
virtual std::unique_ptr< NumericVector< T > > clone() const =0
virtual numeric_index_type local_size() const =0
The OldSolutionBase input functor abstract base class is the root of the OldSolutionValue and OldSolu...
The OldSolutionCoefs input functor class can be used with GenericProjector to read solution transfer ...
OldSolutionCoefs(const OldSolutionCoefs &in)
DSNAOutput< Output >::type DSNA
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)
DSNA eval_at_point(const FEMContext &c, unsigned int i, const Point &p, Real time, bool skip_context_check)
void eval_mixed_derivatives(const FEMContext &libmesh_dbg_var(c), unsigned int i, unsigned int dim, const Node &n, std::vector< DSNA > &derivs)
OldSolutionCoefs(const libMesh::System &sys_in, const std::vector< unsigned int > *vars)
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)
DSNA eval_at_node(const FEMContext &c, unsigned int i, unsigned int elem_dim, const Node &n, bool extra_hanging_dofs, Real=0.)
The OldSolutionValue input functor class can be used with GenericProjector to read values from a solu...
This class provides the ability to map between arbitrary, user-defined strings and several data types...
A Point defines a location in LIBMESH_DIM dimensional Real space.
virtual numeric_index_type row_stop() const =0
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value)=0
Set the element (i,j) to value.
virtual numeric_index_type row_start() const =0
The StoredRange class defines a contiguous, divisible set of objects.
Manages consistently variables, degrees of freedom, and coefficient vectors.
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
This class defines the notion of a variable in the system.
bool active_on_subdomain(subdomain_id_type sid) const
const FEType & type() const
The VectorSetAction output functor class can be used with a GenericProjector to set projection values...
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
Wrap a libMesh-style function pointer into a FunctionBase object.
This class provides a wrapper with which to evaluate a (libMesh-style) function pointer in a Function...
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...
void libmesh_ignore(const Args &...)
const TypeToSend< T >::type convert_to_send(const T &in)
void convert_from_receive(SendT &received, T &converted)
dof_id_type numeric_index_type
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
DynamicSparseNumberArray< Real, dof_id_type > DSNAN
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...
Gradient gptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
For ease of communication, we allow users to translate their own value types to a more easily computa...
const dof_id_type n_nodes