29 namespace heat_transfer {
36 .relative_tol = 1.0e-6,
37 .absolute_tol = 1.0e-12,
38 .max_iterations = 200};
41 #ifdef MFEM_USE_STRUMPACK
51 .relative_tol = 1.0e-4,
52 .absolute_tol = 1.0e-8,
53 .max_iterations = 500,
81 template <
int order,
int dim,
typename parameters = Parameters<>,
82 typename parameter_indices = std::make_
integer_sequence<
int, parameters::n>>
86 template <
int order,
int dim,
typename... parameter_space,
int... parameter_indices>
91 static constexpr
int VALUE = 0, DERIVATIVE = 1;
92 static constexpr
int SHAPE = 0;
93 static constexpr
auto I = Identity<dim>();
98 static constexpr
auto NUM_STATE_VARS = 2;
119 std::string mesh_tag, std::vector<std::string> parameter_names = {},
int cycle = 0,
double time = 0.0,
120 bool checkpoint_to_disk =
false)
122 timestepping_opts, physics_name, mesh_tag, parameter_names, cycle, time, checkpoint_to_disk)
143 const std::string& physics_name, std::string mesh_tag, std::vector<std::string> parameter_names = {},
144 int cycle = 0,
double time = 0.0,
bool checkpoint_to_disk =
false)
145 :
BasePhysics(physics_name, mesh_tag, cycle, time, checkpoint_to_disk),
149 adjoint_temperature_(
151 implicit_sensitivity_temperature_start_of_step_(adjoint_temperature_.space(),
152 detail::addPrefix(physics_name,
"total_deriv_wrt_temperature")),
153 temperature_adjoint_load_(temperature_.space(), detail::addPrefix(physics_name,
"temperature_adjoint_load")),
154 temperature_rate_adjoint_load_(temperature_.space(),
155 detail::addPrefix(physics_name,
"temperature_rate_adjoint_load")),
156 residual_with_bcs_(temperature_.space().TrueVSize()),
157 nonlin_solver_(std::move(solver)),
158 ode_(temperature_.space().TrueVSize(),
159 {.time = ode_time_point_, .u = u_, .dt = dt_, .du_dt = temperature_rate_, .previous_dt = previous_dt_},
160 *nonlin_solver_, bcs_)
163 mesh_.Dimension() != dim,
164 axom::fmt::format(
"Compile time class dimension template parameter and runtime mesh dimension do not match"));
168 "EquationSolver argument is nullptr in HeatTransfer constructor. It is possible that it was previously moved.");
172 ode_.SetTimestepper(timestepping_opts.
timestepper);
174 is_quasistatic_ =
false;
176 is_quasistatic_ =
true;
179 states_.push_back(&temperature_);
180 if (!is_quasistatic_) {
181 states_.push_back(&temperature_rate_);
184 adjoints_.push_back(&adjoint_temperature_);
187 mfem::ParFiniteElementSpace* test_space = &temperature_.space();
188 mfem::ParFiniteElementSpace* shape_space = &shape_displacement_.space();
190 std::array<
const mfem::ParFiniteElementSpace*,
sizeof...(parameter_space) + NUM_STATE_VARS> trial_spaces;
191 trial_spaces[0] = &temperature_.space();
192 trial_spaces[1] = &temperature_.space();
195 sizeof...(parameter_space) != parameter_names.size(),
196 axom::fmt::format(
"{} parameter spaces given in the template argument but {} parameter names were supplied.",
197 sizeof...(parameter_space), parameter_names.size()));
199 if constexpr (
sizeof...(parameter_space) > 0) {
200 tuple<parameter_space...> types{};
202 parameters_.emplace_back(mesh_, get<i>(types), detail::addPrefix(name_, parameter_names[i]));
204 trial_spaces[i + NUM_STATE_VARS] = &(parameters_[i].state->space());
209 std::make_unique<ShapeAwareFunctional<shape_trial, test(scalar_trial, scalar_trial, parameter_space...)>>(
210 shape_space, test_space, trial_spaces);
212 nonlin_solver_->setOperator(residual_with_bcs_);
214 int true_size = temperature_.space().TrueVSize();
215 u_.SetSize(true_size);
216 u_predicted_.SetSize(true_size);
218 shape_displacement_ = 0.0;
219 initializeThermalStates();
232 const std::string& mesh_tag,
int cycle = 0,
double time = 0.0)
233 :
HeatTransfer(input_options.nonlin_solver_options, input_options.lin_solver_options,
234 input_options.timestepping_options, physics_name, mesh_tag, {}, cycle, time)
236 for (
const auto& mat : input_options.materials) {
237 if (std::holds_alternative<serac::heat_transfer::LinearIsotropicConductor>(mat)) {
238 setMaterial(std::get<serac::heat_transfer::LinearIsotropicConductor>(mat));
244 if (input_options.initial_temperature) {
245 auto temp = input_options.initial_temperature->constructScalar();
246 temperature_.project(*temp);
249 if (input_options.source_coef) {
252 SLIC_ERROR(
"'source' is not implemented yet in input files.");
256 std::map<std::string, input::BoundaryConditionInputOptions> sorted_bcs(input_options.boundary_conditions.begin(),
257 input_options.boundary_conditions.end());
258 for (
const auto& [bc_name, bc] : sorted_bcs) {
260 if (bc_name.find(
"temperature") != std::string::npos) {
261 std::shared_ptr<mfem::Coefficient> temp_coef(bc.coef_opts.constructScalar());
262 bcs_.addEssential(bc.attrs, temp_coef, temperature_.space(), *bc.coef_opts.component);
263 }
else if (bc_name.find(
"flux") != std::string::npos) {
266 SLIC_ERROR(
"'flux' is not implemented yet in input files.");
268 SLIC_WARNING_ROOT(
"Ignoring boundary condition with unknown name: " << physics_name);
286 temperature_rate_ = 0.0;
287 adjoint_temperature_ = 0.0;
288 implicit_sensitivity_temperature_start_of_step_ = 0.0;
289 temperature_adjoint_load_ = 0.0;
290 temperature_rate_adjoint_load_ = 0.0;
292 if (!checkpoint_to_disk_) {
293 checkpoint_states_.clear();
295 checkpoint_states_[
"temperature"].push_back(temperature_);
296 checkpoint_states_[
"temperature_rate"].push_back(temperature_rate_);
309 initializeThermalStates();
320 void setTemperatureBCs(
const std::set<int>& temp_bdr, std::function<
double(
const mfem::Vector& x,
double t)> temp)
323 temp_bdr_coef_ = std::make_shared<mfem::FunctionCoefficient>(temp);
325 bcs_.addEssential(temp_bdr, temp_bdr_coef_, temperature_.space());
337 if (is_quasistatic_) {
341 ode_time_point_ = time_;
344 for (
auto& bc : bcs_.essentials()) {
345 bc.setDofs(temperature_, time_);
347 nonlin_solver_->solve(temperature_);
354 ode_.Step(temperature_, time_, dt);
358 if (checkpoint_to_disk_) {
361 checkpoint_states_[
"temperature"].push_back(temperature_);
362 checkpoint_states_[
"temperature_rate"].push_back(temperature_rate_);
366 if (cycle_ > max_cycle_) {
367 timesteps_.push_back(dt);
377 template <
typename MaterialType>
378 struct ThermalMaterialIntegrand {
390 class DummyArgumentType {};
391 static_assert(!std::is_invocable<MaterialType, DummyArgumentType&>::value);
392 static_assert(!std::is_invocable<MaterialType, DummyArgumentType*>::value);
393 static_assert(!std::is_invocable<MaterialType, DummyArgumentType>::value);
399 template <
typename X,
typename T,
typename dT_dt,
typename... Params>
400 auto operator()(
double , X x, T temperature, dT_dt dtemp_dt, Params... params)
const
403 auto [u, du_dX] = temperature;
404 auto du_dt = get<VALUE>(dtemp_dt);
406 auto [heat_capacity, heat_flux] = material_(x, u, du_dX, params...);
408 return serac::tuple{heat_capacity * du_dt, -1.0 * heat_flux};
412 MaterialType material_;
438 template <
int... active_parameters,
typename MaterialType>
441 ThermalMaterialIntegrand<MaterialType> integrand(material);
443 residual_->AddDomainIntegral(
Dimension<dim>{},
DependsOn<0, 1, NUM_STATE_VARS + active_parameters...>{}, integrand,
448 template <
typename MaterialType>
464 mfem::FunctionCoefficient temp_coef(temp);
466 temp_coef.SetTime(time_);
467 temperature_.project(temp_coef);
496 template <
int... active_parameters,
typename SourceType>
498 const std::optional<Domain>& optional_domain = std::nullopt)
502 residual_->AddDomainIntegral(
504 [source_function](
double t,
auto x,
auto temperature,
auto ,
auto... params) {
506 auto [u, du_dX] = temperature;
508 auto source = source_function(x, t, u, du_dX, params...);
517 template <
typename SourceType>
518 void setSource(SourceType source_function,
const std::optional<Domain>& optional_domain = std::nullopt)
520 setSource(
DependsOn<>{}, source_function, optional_domain);
546 template <
int... active_parameters,
typename FluxType>
548 const std::optional<Domain>& optional_domain = std::nullopt)
552 residual_->AddBoundaryIntegral(
554 [flux_function](
double t,
auto X,
auto u,
auto ,
auto... params) {
555 auto temp = get<VALUE>(u);
556 auto n =
cross(get<DERIVATIVE>(X));
558 return flux_function(X,
normalize(n), t, temp, params...);
564 template <
typename FluxType>
565 void setFluxBCs(FluxType flux_function,
const std::optional<Domain>& optional_domain = std::nullopt)
567 setFluxBCs(
DependsOn<>{}, flux_function, optional_domain);
580 mfem::VectorFunctionCoefficient shape_disp_coef(dim, shape_disp);
581 shape_displacement_.project(shape_disp_coef);
609 if (state_name ==
"temperature") {
611 }
else if (state_name ==
"temperature_rate") {
612 return temperature_rate_;
615 SLIC_ERROR_ROOT(axom::fmt::format(
"State '{}' requested from solid mechanics module '{}', but it doesn't exist",
631 if (state_name ==
"temperature") {
632 temperature_ = state;
633 if (!checkpoint_to_disk_) {
634 checkpoint_states_[
"temperature"][
static_cast<size_t>(cycle_)] = temperature_;
639 SLIC_ERROR_ROOT(axom::fmt::format(
640 "setState for state named '{}' requested from heat transfer module '{}', but it doesn't exist", state_name,
651 if (is_quasistatic_) {
652 return std::vector<std::string>{
"temperature"};
654 return std::vector<std::string>{
"temperature",
"temperature_rate"};
679 template <
int... active_parameters,
typename callable>
681 const std::optional<Domain>& optional_domain = std::nullopt)
697 if (state_name ==
"temperature") {
698 return adjoint_temperature_;
701 SLIC_ERROR_ROOT(axom::fmt::format(
"Adjoint '{}' requested from solid mechanics module '{}', but it doesn't exist",
703 return adjoint_temperature_;
714 temperature_.space().BuildDofToArrays();
716 if (is_quasistatic_) {
718 temperature_.space().TrueVSize(),
720 [
this](
const mfem::Vector& u, mfem::Vector& r) {
721 const mfem::Vector res = (*residual_)(ode_time_point_, shape_displacement_, u, temperature_rate_,
722 *parameters_[parameter_indices].state...);
728 r.SetSubVector(bcs_.allEssentialTrueDofs(), 0.0);
731 [
this](
const mfem::Vector& u) -> mfem::Operator& {
732 auto [r, drdu] = (*residual_)(ode_time_point_, shape_displacement_, differentiate_wrt(u), temperature_rate_,
733 *parameters_[parameter_indices].state...);
735 J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_);
740 temperature_.space().TrueVSize(),
742 [
this](
const mfem::Vector& du_dt, mfem::Vector& r) {
743 add(1.0, u_, dt_, du_dt, u_predicted_);
744 const mfem::Vector res = (*residual_)(ode_time_point_, shape_displacement_, u_predicted_, du_dt,
745 *parameters_[parameter_indices].state...);
751 r.SetSubVector(bcs_.allEssentialTrueDofs(), 0.0);
754 [
this](
const mfem::Vector& du_dt) -> mfem::Operator& {
755 add(1.0, u_, dt_, du_dt, u_predicted_);
758 auto K = serac::get<DERIVATIVE>((*residual_)(ode_time_point_, shape_displacement_,
759 differentiate_wrt(u_predicted_), du_dt,
760 *parameters_[parameter_indices].state...));
761 std::unique_ptr<mfem::HypreParMatrix> k_mat(assemble(K));
764 auto M = serac::get<DERIVATIVE>((*residual_)(ode_time_point_, shape_displacement_, u_predicted_,
765 differentiate_wrt(du_dt),
766 *parameters_[parameter_indices].state...));
767 std::unique_ptr<mfem::HypreParMatrix> m_mat(assemble(M));
770 J_.reset(mfem::Add(1.0, *m_mat, dt_, *k_mat));
771 J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_);
777 if (checkpoint_to_disk_) {
780 checkpoint_states_.clear();
782 checkpoint_states_[
"temperature"].push_back(temperature_);
783 checkpoint_states_[
"temperature_rate"].push_back(temperature_rate_);
801 virtual void setAdjointLoad(std::unordered_map<std::string, const serac::FiniteElementDual&> loads)
override
803 SLIC_ERROR_ROOT_IF(loads.size() == 0,
804 "Adjoint load container size must be greater than 0 in the heat transfer module.");
806 auto temp_adjoint_load = loads.find(
"temperature");
807 auto temp_rate_adjoint_load = loads.find(
"temperature_rate");
809 SLIC_ERROR_ROOT_IF(temp_adjoint_load == loads.end(),
"Adjoint load for \"temperature\" not found.");
811 temperature_adjoint_load_ = temp_adjoint_load->second;
813 temperature_adjoint_load_ *= -1.0;
815 if (temp_rate_adjoint_load != loads.end()) {
816 temperature_rate_adjoint_load_ = temp_rate_adjoint_load->second;
817 temperature_rate_adjoint_load_ *= -1.0;
853 auto& lin_solver = nonlin_solver_->linearSolver();
855 mfem::HypreParVector adjoint_essential(temperature_adjoint_load_);
856 adjoint_essential = 0.0;
858 if (is_quasistatic_) {
862 auto [_, drdu] = (*residual_)(ode_time_point_, shape_displacement_,
differentiate_wrt(temperature_),
863 temperature_rate_, *parameters_[parameter_indices].state...);
864 auto jacobian = assemble(drdu);
865 auto J_T = std::unique_ptr<mfem::HypreParMatrix>(jacobian->Transpose());
867 for (
const auto& bc : bcs_.essentials()) {
868 bc.apply(*J_T, temperature_adjoint_load_, adjoint_essential);
871 lin_solver.SetOperator(*J_T);
872 lin_solver.Mult(temperature_adjoint_load_, adjoint_temperature_);
878 "Only backward Euler implemented for transient adjoint heat conduction.");
880 SLIC_ERROR_ROOT_IF(cycle_ <= min_cycle_,
881 "Maximum number of adjoint timesteps exceeded! The number of adjoint timesteps must equal the "
882 "number of forward timesteps");
888 auto previous_states_n = getCheckpointedStates(cycle_);
889 auto previous_states_n_minus_1 = getCheckpointedStates(cycle_ - 1);
891 temperature_ = previous_states_n.at(
"temperature");
892 temperature_rate_ = previous_states_n.at(
"temperature_rate");
893 temperature_n_minus_1 = previous_states_n_minus_1.at(
"temperature");
896 double dt = getCheckpointedTimestep(cycle_ - 1);
899 auto K = serac::get<DERIVATIVE>((*residual_)(ode_time_point_, shape_displacement_,
differentiate_wrt(temperature_),
900 temperature_rate_, *parameters_[parameter_indices].state...));
901 std::unique_ptr<mfem::HypreParMatrix> k_mat(assemble(K));
904 auto M = serac::get<DERIVATIVE>((*residual_)(ode_time_point_, shape_displacement_, temperature_,
906 *parameters_[parameter_indices].state...));
907 std::unique_ptr<mfem::HypreParMatrix> m_mat(assemble(M));
909 J_.reset(mfem::Add(1.0, *m_mat, dt, *k_mat));
910 auto J_T = std::unique_ptr<mfem::HypreParMatrix>(J_->Transpose());
914 mfem::HypreParVector modified_RHS(temperature_adjoint_load_);
916 modified_RHS.Add(1.0, temperature_rate_adjoint_load_);
917 modified_RHS.Add(-dt, implicit_sensitivity_temperature_start_of_step_);
919 for (
const auto& bc : bcs_.essentials()) {
920 bc.apply(*J_T, modified_RHS, adjoint_essential);
923 lin_solver.SetOperator(*J_T);
924 lin_solver.Mult(modified_RHS, adjoint_temperature_);
930 m_mat->Mult(adjoint_temperature_, implicit_sensitivity_temperature_start_of_step_);
931 implicit_sensitivity_temperature_start_of_step_ *= -1.0 / dt;
932 implicit_sensitivity_temperature_start_of_step_.Add(1.0 / dt,
933 temperature_rate_adjoint_load_);
948 std::unordered_map<std::string, FiniteElementState> previous_states;
950 if (checkpoint_to_disk_) {
951 previous_states.emplace(
"temperature", temperature_);
952 previous_states.emplace(
"temperature_rate", temperature_rate_);
954 {previous_states.at(
"temperature"), previous_states.at(
"temperature_rate")});
955 return previous_states;
957 previous_states.emplace(
"temperature", checkpoint_states_.at(
"temperature")[
static_cast<size_t>(cycle_to_load)]);
958 previous_states.emplace(
"temperature_rate",
959 checkpoint_states_.at(
"temperature_rate")[
static_cast<size_t>(cycle_to_load)]);
962 return previous_states;
978 auto drdparam = serac::get<DERIVATIVE>(d_residual_d_[parameter_field](ode_time_point_));
979 auto drdparam_mat = assemble(drdparam);
981 drdparam_mat->MultTranspose(adjoint_temperature_, *parameters_[parameter_field].sensitivity);
983 return *parameters_[parameter_field].sensitivity;
997 serac::get<DERIVATIVE>((*residual_)(ode_time_point_,
differentiate_wrt(shape_displacement_), temperature_,
998 temperature_rate_, *parameters_[parameter_indices].state...));
1000 auto drdshape_mat = assemble(drdshape);
1002 drdshape_mat->MultTranspose(adjoint_temperature_, *shape_displacement_sensitivity_);
1004 return *shape_displacement_sensitivity_;
1016 return {{
"temperature", implicit_sensitivity_temperature_start_of_step_}};
1054 std::unique_ptr<mfem::HypreParMatrix>
M_;
1076 std::unique_ptr<mfem::HypreParMatrix>
J_;
1080 std::unique_ptr<mfem::HypreParMatrix>
J_e_;
1097 std::array<std::function<decltype((*residual_)(
DifferentiateWRT<1>{}, 0.0, shape_displacement_, temperature_,
1098 temperature_rate_, *parameters_[parameter_indices].state...))(double)>,
1099 sizeof...(parameter_indices)>
1100 d_residual_d_ = {[&](
double TIME) {
1102 temperature_, temperature_rate_, *parameters_[parameter_indices].state...);
The base interface class for a generic PDE solver.
This is the abstract base class for a generic forward solver.
void initializeBasePhysicsStates(int cycle, double time)
Protected, non-virtual method to reset physics states to zero. This does not reset design parameters ...
Class for encapsulating the dual vector space of a finite element space (i.e. the space of linear for...
Class for encapsulating the critical MFEM components of a primal finite element field.
mfem_ext::StdFunctionOperator residual_with_bcs_
mfem::Operator that describes the weight residual and its gradient with respect to temperature
void setTemperature(const FiniteElementState temp)
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::unordered_map< std::string, FiniteElementState > getCheckpointedStates(int cycle_to_load) const override
Accessor for getting named finite element state primal solution from the physics modules at a given c...
const FiniteElementState & state(const std::string &state_name) const override
Accessor for getting named finite element state primal solution from the physics modules.
void setMaterial(MaterialType material)
This is an overloaded member function, provided for convenience. It differs from the above function o...
serac::FiniteElementDual temperature_rate_adjoint_load_
The downstream derivative of the qoi with repect to the primal temperature rate variable.
double dt_
The current timestep.
FiniteElementDual & computeTimestepShapeSensitivity() override
Compute the implicit sensitivity of the quantity of interest used in defining the load for the adjoin...
HeatTransfer(std::unique_ptr< serac::EquationSolver > solver, const serac::TimesteppingOptions timestepping_opts, const std::string &physics_name, std::string mesh_tag, std::vector< std::string > parameter_names={}, int cycle=0, double time=0.0, bool checkpoint_to_disk=false)
Construct a new heat transfer object.
virtual ~HeatTransfer()=default
Destroy the Thermal Solver object.
void resetStates(int cycle=0, double time=0.0) override
Method to reset physics states to zero. This does not reset design parameters or shape.
serac::FiniteElementState adjoint_temperature_
The adjoint temperature finite element states, the multiplier on the residual for a given timestep.
virtual void setAdjointLoad(std::unordered_map< std::string, const serac::FiniteElementDual & > loads) override
Set the loads for the adjoint reverse timestep solve.
mfem_ext::FirstOrderODE ode_
the ordinary differential equation that describes how to solve for the time derivative of temperature...
void setFluxBCs(FluxType flux_function, const std::optional< Domain > &optional_domain=std::nullopt)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setTemperature(std::function< double(const mfem::Vector &x, double t)> temp)
Set the underlying finite element state to a prescribed temperature.
std::unique_ptr< EquationSolver > nonlin_solver_
the specific methods and tolerances specified to solve the nonlinear residual equations
mfem::Vector u_
Predicted temperature true dofs.
void setShapeDisplacement(std::function< void(const mfem::Vector &x, mfem::Vector &shape_disp)> shape_disp)
Set the underlying finite element state to a prescribed shape displacement.
const serac::FiniteElementState & temperature() const
Get the temperature state.
void setSource(DependsOn< active_parameters... >, SourceType source_function, const std::optional< Domain > &optional_domain=std::nullopt)
Set the thermal source function.
void setMaterial(DependsOn< active_parameters... >, MaterialType material)
Set the thermal material model for the physics solver.
mfem::Vector u_predicted_
Predicted temperature true dofs.
void setShapeDisplacement(FiniteElementState &shape_disp)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setTemperatureBCs(const std::set< int > &temp_bdr, std::function< double(const mfem::Vector &x, double t)> temp)
Set essential temperature boundary conditions (strongly enforced)
std::unique_ptr< ShapeAwareFunctional< shape_trial, test(scalar_trial, scalar_trial, parameter_space...)> > residual_
serac::Functional that is used to calculate the residual and its derivatives
std::unique_ptr< mfem::HypreParMatrix > J_e_
FiniteElementDual & computeTimestepSensitivity(size_t parameter_field) override
Compute the implicit sensitivity of the quantity of interest used in defining the load for the adjoin...
void initializeThermalStates()
Non virtual method to reset thermal states to zero. This does not reset design parameters or shape.
virtual std::vector< std::string > stateNames() const override
Get a vector of the finite element state primal solution names.
const serac::FiniteElementState & temperatureRate() const
Get the temperature rate of change state.
void reverseAdjointTimestep() override
Solve the adjoint problem.
serac::FiniteElementDual temperature_adjoint_load_
The downstream derivative of the qoi with repect to the primal temperature variable.
HeatTransfer(const NonlinearSolverOptions nonlinear_opts, const LinearSolverOptions lin_opts, const serac::TimesteppingOptions timestepping_opts, const std::string &physics_name, std::string mesh_tag, std::vector< std::string > parameter_names={}, int cycle=0, double time=0.0, bool checkpoint_to_disk=false)
Construct a new heat transfer object.
serac::FiniteElementDual implicit_sensitivity_temperature_start_of_step_
The total/implicit sensitivity of the qoi with respect to the start of the previous timestep's temper...
serac::FiniteElementState temperature_
The temperature finite element state.
void completeSetup() override
Complete the initialization and allocation of the data structures.
void setFluxBCs(DependsOn< active_parameters... >, FluxType flux_function, const std::optional< Domain > &optional_domain=std::nullopt)
Set the thermal flux boundary condition.
std::unique_ptr< mfem::HypreParMatrix > J_
Assembled sparse matrix for the Jacobian.
void advanceTimestep(double dt) override
Advance the heat conduction physics module in time.
const FiniteElementState & adjoint(const std::string &state_name) const override
Accessor for getting named finite element state adjoint solution from the physics modules.
FiniteElementState temperature_rate_
Rate of change in temperature at the current adjoint timestep.
void addCustomBoundaryIntegral(DependsOn< active_parameters... >, callable qfunction, const std::optional< Domain > &optional_domain=std::nullopt)
register a custom boundary integral calculation as part of the residual
const std::unordered_map< std::string, const serac::FiniteElementDual & > computeInitialConditionSensitivity() override
Compute the implicit sensitivity of the quantity of interest with respect to the initial temperature.
void setSource(SourceType source_function, const std::optional< Domain > &optional_domain=std::nullopt)
This is an overloaded member function, provided for convenience. It differs from the above function o...
double previous_dt_
The previous timestep.
void setState(const std::string &state_name, const FiniteElementState &state) override
Set the primal solution field (temperature) for the underlying heat transfer solver.
std::shared_ptr< mfem::Coefficient > temp_bdr_coef_
Coefficient containing the essential boundary values.
std::unique_ptr< mfem::HypreParMatrix > M_
Assembled mass matrix.
HeatTransfer(const HeatTransferInputOptions &input_options, const std::string &physics_name, const std::string &mesh_tag, int cycle=0, double time=0.0)
Construct a new Nonlinear HeatTransfer Solver object.
An object containing the solver for a heat transfer PDE.
static void loadCheckpointedStates(int cycle_to_load, std::vector< std::reference_wrapper< FiniteElementState >> states_to_load)
loads the finite element states from a previously checkpointed cycle
static FiniteElementState newState(FunctionSpace space, const std::string &state_name, const std::string &mesh_tag)
Factory method for creating a new FEState object.
static mfem::ParMesh & mesh(const std::string &mesh_tag)
Returns a non-owning reference to mesh held by StateManager.
FirstOrderODE is a class wrapping mfem::TimeDependentOperator so that the user can use std::function ...
StdFunctionOperator is a class wrapping mfem::Operator so that the user can use std::function to defi...
A file defining some enums and structs that are used by the different physics modules.
A function intended to be used as part of a driver to initialize common libraries.
const TimesteppingOptions default_timestepping_options
Reasonable defaults for dynamic heat transfer simulations.
const TimesteppingOptions default_static_options
Reasonable defaults for static heat transfer simulations.
const LinearSolverOptions default_linear_options
Reasonable defaults for most thermal linear solver options.
const NonlinearSolverOptions default_nonlinear_options
Reasonable defaults for most thermal nonlinear solver options.
const LinearSolverOptions direct_linear_options
the default direct solver option for solving the linear stiffness equations
Accelerator functionality.
Domain EntireBoundary(const mfem::Mesh &mesh)
constructs a domain from all the boundary elements in a mesh
auto differentiate_wrt(const mfem::Vector &v)
this function is intended to only be used in combination with serac::Functional::operator(),...
tuple(T...) -> tuple< T... >
Class template argument deduction rule for tuples.
auto cross(const tensor< T, 3, 2 > &A)
compute the cross product of the columns of A: A(:,1) x A(:,2)
SERAC_HOST_DEVICE auto normalize(const tensor< T, n... > &A)
Normalizes the tensor Each element is divided by the Frobenius norm of the tensor,...
bool holds_alternative(const variant< T0, T1 > &v)
Checks whether a variant's active member is of a certain type.
Domain EntireDomain(const mfem::Mesh &mesh)
constructs a domain from all the elements in a mesh
Wrapper classes for using MFEM's ODE solver objects.
Wrapper of serac::Functional for evaluating integrals and derivatives of quantities with shape displa...
This file contains the declaration of the StateManager class.
Classes for defining an mfem::Operator with std::functions.
Compile-time alias for a dimension.
a class for representing a geometric region that can be used for integration
auto operator()(double, X x, T temperature, dT_dt dtemp_dt, Params... params) const
Evaluate integrand.
ThermalMaterialIntegrand(MaterialType material)
Construct a ThermalMaterialIntegrand functor with material model of type MaterialType.
Parameters for an iterative linear solution scheme.
LinearSolver linear_solver
Linear solver selection.
Nonlinear solution scheme parameters.
NonlinearSolver nonlin_solver
Nonlinear solver selection.
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
A timestep and boundary condition enforcement method for a dynamic solver.
TimestepMethod timestepper
The timestepping method to be applied.
DirichletEnforcementMethod enforcement_method
The essential boundary enforcement method to use.
Linear anisotropic thermal material model.
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...
A sentinel struct for eliding no-op tensor operations.
The material and load types for the thermal functional physics module.