47 femsystem_mutex assembly_mutex;
49 void assemble_unconstrained_element_system(
const FEMSystem & _sys,
50 const bool _get_jacobian,
51 const bool _constrain_heterogeneously,
76 const bool need_jacobian =
77 (_get_jacobian || _constrain_heterogeneously);
79 bool jacobian_computed =
80 _sys.
time_solver->element_residual(need_jacobian, _femcontext);
83 if (need_jacobian && !jacobian_computed)
93 if (need_jacobian && jacobian_computed &&
102 Real analytic_norm = analytic_jacobian.l1_norm();
110 Real error_norm = analytic_jacobian.l1_norm();
112 Real relative_error = error_norm /
113 std::max(analytic_norm, numerical_norm);
118 <<
" detected in analytic jacobian on element " 119 << _femcontext.
get_elem().
id() <<
'!' << std::endl;
127 << analytic_jacobian << std::endl;
131 libmesh_error_msg(
"Relative error too large, exiting!");
136 for (_femcontext.
side = 0; _femcontext.
side != n_sides;
158 #endif // ifndef DEBUG 165 _sys.
time_solver->side_residual(need_jacobian, _femcontext);
168 if (need_jacobian && !jacobian_computed)
176 if (old_jacobian.
m())
193 else if (need_jacobian && jacobian_computed &&
202 Real analytic_norm = analytic_jacobian.l1_norm();
210 Real error_norm = analytic_jacobian.l1_norm();
212 Real relative_error = error_norm /
213 std::max(analytic_norm, numerical_norm);
218 <<
" detected in analytic jacobian on element " 221 <<
static_cast<unsigned int>(_femcontext.
side) <<
'!' << std::endl;
229 << analytic_jacobian << std::endl;
232 libmesh_error_msg(
"Relative error too large, exiting!");
246 #endif // ifdef DEBUG 250 void add_element_system(
const FEMSystem & _sys,
251 const bool _get_residual,
252 const bool _get_jacobian,
253 const bool _constrain_heterogeneously,
254 const bool _no_constraints,
257 #ifdef LIBMESH_ENABLE_CONSTRAINTS 272 if (_get_residual && _get_jacobian)
274 if (_constrain_heterogeneously)
279 else if (!_no_constraints)
286 else if (_get_residual)
288 if (_constrain_heterogeneously)
293 else if (!_no_constraints)
298 else if (_get_jacobian)
303 if (!_no_constraints)
308 #endif // #ifdef LIBMESH_ENABLE_CONSTRAINTS 335 femsystem_mutex::scoped_lock lock(assembly_mutex);
348 class AssemblyContributions
357 bool constrain_heterogeneously,
358 bool no_constraints) :
360 _get_residual(get_residual),
361 _get_jacobian(get_jacobian),
362 _constrain_heterogeneously(constrain_heterogeneously),
363 _no_constraints(no_constraints) {}
371 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
374 for (
const auto & elem : range)
376 Elem * el =
const_cast<Elem *
>(elem);
381 assemble_unconstrained_element_system
382 (_sys, _get_jacobian, _constrain_heterogeneously, _femcontext);
385 (_sys, _get_residual, _get_jacobian,
386 _constrain_heterogeneously, _no_constraints, _femcontext);
394 const bool _get_residual, _get_jacobian, _constrain_heterogeneously, _no_constraints;
397 class PostprocessContributions
404 PostprocessContributions(
FEMSystem & sys) : _sys(sys) {}
412 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
415 for (
const auto & elem : range)
417 Elem * el =
const_cast<Elem *
>(elem);
427 for (_femcontext.
side = 0; _femcontext.
side != n_sides;
450 class QoIContributions
459 const QoISet & qoi_indices) :
460 qoi(sys.n_qois(), 0.), _sys(sys), _diff_qoi(diff_qoi),_qoi_indices(qoi_indices) {}
465 QoIContributions(
const QoIContributions & other,
467 qoi(other._sys.n_qois(), 0.), _sys(other._sys), _diff_qoi(other._diff_qoi) {}
475 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
476 _diff_qoi.init_context(_femcontext);
478 bool have_some_heterogenous_qoi_bc =
false;
479 #ifdef LIBMESH_ENABLE_CONSTRAINTS 480 std::vector<bool> have_heterogenous_qoi_bc(_sys.
n_qois(),
false);
481 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
482 if (_qoi_indices.has_index(q) &&
485 have_heterogenous_qoi_bc[q] =
true;
486 have_some_heterogenous_qoi_bc =
true;
490 if (have_some_heterogenous_qoi_bc)
493 for (
const auto & elem : range)
495 Elem * el =
const_cast<Elem *
>(elem);
499 const unsigned int n_dofs =
504 #ifdef LIBMESH_ENABLE_CONSTRAINTS 505 bool elem_has_some_heterogenous_qoi_bc =
false;
506 std::vector<bool> elem_has_heterogenous_qoi_bc(_sys.
n_qois(),
false);
507 if (have_some_heterogenous_qoi_bc)
509 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
511 if (have_heterogenous_qoi_bc[q])
517 elem_has_some_heterogenous_qoi_bc =
true;
518 elem_has_heterogenous_qoi_bc[q] =
true;
526 if (_diff_qoi.assemble_qoi_elements ||
527 elem_has_some_heterogenous_qoi_bc)
530 if (_diff_qoi.assemble_qoi_elements)
531 _diff_qoi.element_qoi(_femcontext, _qoi_indices);
536 #ifdef LIBMESH_ENABLE_CONSTRAINTS 537 if (elem_has_some_heterogenous_qoi_bc)
539 _sys.
time_solver->element_residual(
false, _femcontext);
541 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
543 if (elem_has_heterogenous_qoi_bc[q])
555 for (_femcontext.
side = 0; _femcontext.
side != n_sides;
559 if (!_diff_qoi.assemble_qoi_sides ||
560 (!_diff_qoi.assemble_qoi_internal_sides &&
566 _diff_qoi.side_qoi(_femcontext, _qoi_indices);
570 this->_diff_qoi.thread_join( this->qoi, _femcontext.
get_qois(), _qoi_indices );
573 void join (
const QoIContributions & other)
575 libmesh_assert_equal_to (this->qoi.size(), other.qoi.size());
576 this->_diff_qoi.thread_join( this->qoi, other.qoi, _qoi_indices );
579 std::vector<Number> qoi;
586 const QoISet _qoi_indices;
589 class QoIDerivativeContributions
595 QoIDerivativeContributions(
FEMSystem & sys,
596 const QoISet & qoi_indices,
598 bool include_liftfunc,
599 bool apply_constraints) :
601 _qoi_indices(qoi_indices),
603 _include_liftfunc(include_liftfunc),
604 _apply_constraints(apply_constraints) {}
612 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
613 _qoi.init_context(_femcontext);
615 bool have_some_heterogenous_qoi_bc =
false;
616 #ifdef LIBMESH_ENABLE_CONSTRAINTS 617 std::vector<bool> have_heterogenous_qoi_bc(_sys.
n_qois(),
false);
618 if (_include_liftfunc || _apply_constraints)
619 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
620 if (_qoi_indices.has_index(q) &&
623 have_heterogenous_qoi_bc[q] =
true;
624 have_some_heterogenous_qoi_bc =
true;
628 if (have_some_heterogenous_qoi_bc)
631 for (
const auto & elem : range)
633 Elem * el =
const_cast<Elem *
>(elem);
637 const unsigned int n_dofs =
642 #ifdef LIBMESH_ENABLE_CONSTRAINTS 643 bool elem_has_some_heterogenous_qoi_bc =
false;
644 std::vector<bool> elem_has_heterogenous_qoi_bc(_sys.
n_qois(),
false);
645 if (have_some_heterogenous_qoi_bc)
647 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
649 if (have_heterogenous_qoi_bc[q])
655 elem_has_some_heterogenous_qoi_bc =
true;
656 elem_has_heterogenous_qoi_bc[q] =
true;
669 if (_qoi.assemble_qoi_elements ||
670 ((_include_liftfunc || _apply_constraints) &&
671 elem_has_some_heterogenous_qoi_bc))
674 if (_qoi.assemble_qoi_elements)
675 _qoi.element_qoi_derivative(_femcontext, _qoi_indices);
677 #ifdef LIBMESH_ENABLE_CONSTRAINTS 681 if ((_include_liftfunc || _apply_constraints) &&
682 elem_has_some_heterogenous_qoi_bc)
684 bool jacobian_computed = _sys.
time_solver->element_residual(
true, _femcontext);
687 if (!jacobian_computed)
699 if (_include_liftfunc && elem_has_some_heterogenous_qoi_bc)
701 for (
unsigned int q=0; q != _sys.
n_qois(); ++q)
703 if (elem_has_heterogenous_qoi_bc[q])
710 if (liftfunc_val !=
Number(0))
725 for (_femcontext.
side = 0; _femcontext.
side != n_sides;
729 if (!_qoi.assemble_qoi_sides ||
730 (!_qoi.assemble_qoi_internal_sides &&
736 _qoi.side_qoi_derivative(_femcontext, _qoi_indices);
743 #ifdef LIBMESH_ENABLE_CONSTRAINTS 744 std::vector<dof_id_type> original_dofs = _femcontext.
get_dof_indices();
748 femsystem_mutex::scoped_lock lock(assembly_mutex);
750 #ifdef LIBMESH_ENABLE_CONSTRAINTS 754 if (_apply_constraints)
758 for (
unsigned int i=0; i != _sys.
n_qois(); ++i)
759 if (_qoi_indices.has_index(i))
761 #ifdef LIBMESH_ENABLE_CONSTRAINTS 762 if (_apply_constraints)
765 bool has_heterogenous_constraint =
false;
770 has_heterogenous_constraint =
true;
771 libmesh_assert(elem_has_heterogenous_qoi_bc[i]);
772 libmesh_assert(elem_has_some_heterogenous_qoi_bc);
776 bool has_heterogenous_constraint =
777 elem_has_heterogenous_qoi_bc[i];
782 if (has_heterogenous_constraint)
788 (elem_jacobian_transpose);
791 (elem_jacobian_transpose,
814 const QoISet & _qoi_indices;
816 bool _include_liftfunc, _apply_constraints;
831 const std::string & name_in,
832 const unsigned int number_in)
833 :
Parent(es, name_in, number_in),
834 fe_reinit_during_postprocess(true),
836 verify_analytic_jacobians(0.0)
855 bool apply_heterogeneous_constraints,
856 bool apply_no_constraints)
858 libmesh_assert(get_residual || get_jacobian);
861 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING 862 const char * log_name;
863 if (get_residual && get_jacobian)
864 log_name =
"assembly()";
865 else if (get_residual)
866 log_name =
"assembly(get_residual)";
868 log_name =
"assembly(get_jacobian)";
870 LOG_SCOPE(log_name,
"FEMSystem");
891 <<
"];" << std::endl;
905 libMesh::err <<
"WARNING! verify_analytic_jacobians was set " 906 <<
"to absurdly large value of " 922 AssemblyContributions(*
this, get_residual, get_jacobian,
923 apply_heterogeneous_constraints,
924 apply_no_constraints));
927 bool have_scalar =
false;
942 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
946 bool jacobian_computed =
947 this->
time_solver->nonlocal_residual(get_jacobian, _femcontext);
955 if (get_jacobian && !jacobian_computed)
965 if (get_jacobian && jacobian_computed &&
974 Real analytic_norm = analytic_jacobian.l1_norm();
982 Real error_norm = analytic_jacobian.l1_norm();
984 Real relative_error = error_norm /
985 std::max(analytic_norm, numerical_norm);
990 <<
" detected in analytic jacobian on nonlocal dofs!" 999 << analytic_jacobian << std::endl;
1003 libmesh_error_msg(
"Relative error too large, exiting!");
1008 (*
this, get_residual, get_jacobian,
1009 apply_heterogeneous_constraints, apply_no_constraints, _femcontext);
1070 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
1103 LOG_SCOPE(
"postprocess()",
"FEMSystem");
1116 PostprocessContributions(*
this));
1123 LOG_SCOPE(
"assemble_qoi()",
"FEMSystem");
1129 const unsigned int Nq = this->
n_qois();
1133 for (
unsigned int i=0; i != Nq; ++i)
1139 QoIContributions qoi_contributions(*
this, *(this->
diff_qoi), qoi_indices);
1152 bool include_liftfunc,
1153 bool apply_constraints)
1155 LOG_SCOPE(
"assemble_qoi_derivative()",
"FEMSystem");
1163 for (
unsigned int i=0; i != this->
n_qois(); ++i)
1170 QoIDerivativeContributions(*
this, qoi_indices,
1173 apply_constraints));
1175 for (
unsigned int i=0; i != this->
n_qois(); ++i)
1195 Real numerical_point_h = 0.;
1199 const unsigned int n_dofs =
1202 for (
unsigned int v = 0; v != context.
n_vars(); ++v)
1220 const unsigned int total_j = j + j_offset;
1227 Real * coord =
nullptr;
1246 ((*time_solver).*(res))(
false, context);
1260 ((*time_solver).*(res))(
false, context);
1271 numeric_jacobian(i,total_j) =
1273 2. / numerical_point_h;
1280 numeric_jacobian(i,total_j) =
1296 LOG_SCOPE(
"numerical_elem_jacobian()",
"FEMSystem");
1304 LOG_SCOPE(
"numerical_side_jacobian()",
"FEMSystem");
1312 LOG_SCOPE(
"numerical_nonlocal_jacobian()",
"FEMSystem");
1324 libmesh_assert (phys);
1337 return std::unique_ptr<DiffContext>(fc);
1356 FEMContext & context = cast_ref<FEMContext &>(c);
1359 for (
unsigned int var = 0; var != this->
n_vars(); ++var)
1367 FEBase * elem_fe =
nullptr;
1382 libmesh_error_msg(
"Unrecognized field type!");
1394 libmesh_error_msg(
"_mesh_sys was nullptr!");
1398 libmesh_not_implemented();
1404 FEMContext & _femcontext = cast_ref<FEMContext &>(*con);
virtual unsigned int size() const override
virtual bool side_residual(bool request_jacobian, DiffContext &)=0
void numerical_elem_jacobian(FEMContext &context) const
unsigned int get_mesh_x_var() const
Manages multiples systems of equations.
const std::vector< Number > & get_qois() const
const DenseMatrix< Number > & get_elem_jacobian() const
void set_mesh_z_var(unsigned int z_var)
Real verify_analytic_jacobians
void elem_position_set(Real theta)
virtual void pre_fe_reinit(const System &, const Elem *e)
const unsigned int invalid_uint
void set_mesh_x_var(unsigned int x_var)
std::streamsize precision() const
virtual void finalize_derivative(NumericVector< Number > &derivatives, std::size_t qoi_index)
void constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
const DenseVector< Number > & get_elem_fixed_solution() const
void parallel_for(const Range &range, const Body &body)
Used to specify quantities of interest in a simulation.
bool print_jacobian_norms
const Elem & get_elem() const
unsigned int n_qois() const
virtual void assemble_qoi(const QoISet &indices=QoISet()) override
Real numerical_jacobian_h
Number has_heterogenous_adjoint_constraint(const unsigned int qoi_num, const dof_id_type dof) const
void numerical_jacobian(TimeSolverResPtr res, FEMContext &context) const
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
unsigned int n_variable_groups() const
The base class for all geometric element types.
std::unique_ptr< TimeSolver > time_solver
const System * get_mesh_system() const
static FEFieldType field_type(const FEType &fe_type)
NumericVector< Number > * rhs
const Parallel::Communicator & comm() const
void numerical_side_jacobian(FEMContext &context) const
static const Real TOLERANCE
Utility class for defining generic ranges for threading.
virtual void postprocess() override
long double max(long double a, double b)
const MeshBase & get_mesh() const
virtual bool nonlocal_residual(bool request_jacobian, DiffContext &)=0
dof_id_type n_dofs() const
virtual void elem_fe_reinit(const std::vector< Point > *const pts=nullptr)
bool print_element_residuals
DifferentiableQoI * diff_qoi
void heterogenously_constrain_element_vector(const DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true, int qoi_index=-1) const
virtual void set_mesh_system(System *sys)
bool print_element_solutions
virtual node_iterator nodes_begin()=0
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
bool has_index(std::size_t) const
virtual bool element_residual(bool request_jacobian, DiffContext &)=0
bool print_solution_norms
unsigned int get_mesh_y_var() const
processor_id_type n_processors() const
void set_is_adjoint(bool _is_adjoint_value)
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
virtual void parallel_op(const Parallel::Communicator &communicator, std::vector< Number > &sys_qoi, std::vector< Number > &local_qoi, const QoISet &qoi_indices)
const DenseVector< Number > & get_elem_solution() const
virtual void init_data() override
bool print_residual_norms
virtual void side_fe_reinit()
virtual void side_postprocess(DiffContext &)
virtual Real hmin() const
std::vector< Number > qoi
virtual element_iterator active_local_elements_begin()=0
bool fe_reinit_during_postprocess
const std::vector< Real > & get_JxW() const
void get_transpose(DenseMatrix< T > &dest) const
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseMatrix< T3 > &mat)
std::unique_ptr< NumericVector< Number > > solution
const std::vector< dof_id_type > & get_dof_indices() const
void numerical_nonlocal_jacobian(FEMContext &context) const
OStreamProxy err(std::cerr)
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
virtual void element_postprocess(DiffContext &)
NumericVector< Number > & add_adjoint_rhs(unsigned int i=0)
virtual Real l1_norm() const =0
virtual void solve() override
const DifferentiablePhysics * get_physics() const
virtual unsigned int n_sides() const =0
const Elem * neighbor_ptr(unsigned int i) 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
bool compute_internal_sides
const DenseVector< Number > & get_elem_residual() const
virtual void init_data() override
bool has_heterogenous_adjoint_constraints(const unsigned int qoi_num) const
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual node_iterator nodes_end()=0
StoredRange< iterator_type, object_type > & reset(const iterator_type &first, const iterator_type &last)
void constrain_element_vector(DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
virtual void zero() override
SparseMatrix< Number > * matrix
void set_mesh_y_var(unsigned int y_var)
bool print_element_jacobians
void parallel_reduce(const Range &range, Body &body)
unsigned int get_mesh_z_var() const
void set_deltat_pointer(Real *dt)
void get_element_fe(unsigned int var, FEGenericBase< OutputShape > *&fe) const
virtual void init_context(DiffContext &) override
virtual void assemble_qoi_derivative(const QoISet &qoi_indices=QoISet(), bool include_liftfunc=true, bool apply_constraints=true) override
virtual std::unique_ptr< DiffContext > build_context() override
virtual void solve() override
bool is_time_evolving(unsigned int var) const
virtual Real l1_norm() const =0
unsigned int n_vars() const
unsigned int n_vars() const
processor_id_type processor_id() const
const std::vector< DenseVector< Number > > & get_qoi_derivatives() const
FEMSystem(EquationSystems &es, const std::string &name, const unsigned int number)
OStreamProxy out(std::cout)
const DofMap & get_dof_map() const
virtual element_iterator active_local_elements_end()=0
const Point & point(const unsigned int i) const
bool has_children() const
const VariableGroup & variable_group(unsigned int vg) const
void constrain_nothing(std::vector< dof_id_type > &dofs) const
virtual void assembly(bool get_residual, bool get_jacobian, bool apply_heterogeneous_constraints=false, bool apply_no_constraints=false) override
Real numerical_jacobian_h_for_var(unsigned int var_num) const
virtual void zero() override
const std::vector< std::vector< OutputShape > > & get_phi() const
TimeSolver & get_time_solver()
const FEType & type() const
NumericVector< Number > & get_adjoint_rhs(unsigned int i=0)
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Manages consistently variables, degrees of freedom, coefficient vectors, and matrices for implicit sy...