14 #include "smith/differentiable_numerics/field_store.hpp"
18 #include "smith/differentiable_numerics/multiphysics_time_integrator.hpp"
43 template <
int dim,
int disp_order,
typename StateSpace,
44 typename DisplacementTimeRule = QuasiStaticSecondOrderTimeIntegrationRule,
45 typename InternalVarTimeRule = BackwardEulerFirstOrderTimeIntegrationRule,
typename... parameter_space>
47 static_assert(DisplacementTimeRule::num_states == 4,
48 "SolidMechanicsWithInternalVarsSystem requires a 4-state displacement rule");
49 static_assert(InternalVarTimeRule::num_states == 2,
50 "SolidMechanicsWithInternalVarsSystem requires a 2-state internal variable rule");
77 std::shared_ptr<DirichletBoundaryConditions>
disp_bc;
78 std::shared_ptr<DirichletBoundaryConditions>
state_bc;
138 template <
typename MaterialType>
139 void setMaterial(
const MaterialType& material,
const std::string& domain_name)
144 solid_weak_form->addBodyIntegral(domain_name, [=](
auto t_info,
auto ,
auto u,
auto u_old,
auto v_old,
145 auto a_old,
auto alpha,
auto alpha_old,
auto... params) {
146 auto [u_current, v_current, a_current] = captured_disp_rule->interpolate(t_info, u, u_old, v_old, a_old);
147 auto alpha_current = captured_state_rule->value(t_info, alpha, alpha_old);
149 typename MaterialType::State state;
150 auto pk_stress = material(state, get<DERIVATIVE>(u_current), get<VALUE>(alpha_current), params...);
152 return smith::tuple{get<VALUE>(a_current) * material.density, pk_stress};
157 domain_name, [=](
auto ,
auto ,
auto u,
auto ,
auto a,
auto alpha,
auto... params) {
158 auto alpha_current = alpha;
159 typename MaterialType::State state;
160 auto pk_stress = material(state, get<DERIVATIVE>(u), get<VALUE>(alpha_current), params...);
162 return smith::tuple{get<VALUE>(a) * material.density, pk_stress};
172 template <
int... active_parameters,
typename BodyForceType>
174 BodyForceType force_function)
179 depends_on, domain_name,
180 [=](
auto t_info,
auto X,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto alpha,
auto alpha_old,
182 auto [u_current, v_current, a_current] = captured_disp_rule->interpolate(t_info, u, u_old, v_old, a_old);
183 auto [alpha_current, alpha_dot] = captured_state_rule->interpolate(t_info, alpha, alpha_old);
184 return force_function(t_info.time(), X, u_current, v_current, a_current, alpha_current, alpha_dot, params...);
187 addCycleZeroBodySourceImpl(
189 [=](
auto t_info,
auto X,
auto u,
auto v,
auto a,
auto alpha,
auto... params) {
190 auto alpha_dot = 0.0 * alpha;
191 return force_function(t_info.time(), X, u, v, a, alpha, alpha_dot, params...);
193 std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
201 template <
typename BodyForceType>
202 void addBodyForce(
const std::string& domain_name, BodyForceType force_function)
204 addBodyForceAllParams(domain_name, force_function, std::make_index_sequence<6 +
sizeof...(parameter_space)>{});
213 template <
int... active_parameters,
typename TractionType>
215 TractionType traction_function)
220 depends_on, domain_name,
221 [=](
auto t_info,
auto X,
auto n,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto alpha,
auto alpha_old,
223 auto [u_current, v_current, a_current] = captured_disp_rule->interpolate(t_info, u, u_old, v_old, a_old);
224 auto [alpha_current, alpha_dot] = captured_state_rule->interpolate(t_info, alpha, alpha_old);
225 return traction_function(t_info.time(), X, n, u_current, v_current, a_current, alpha_current, alpha_dot,
229 addCycleZeroBoundaryFluxImpl(
231 [=](
auto t_info,
auto X,
auto n,
auto u,
auto v,
auto a,
auto alpha,
auto... params) {
232 auto alpha_dot = 0.0 * alpha;
233 return traction_function(t_info.time(), X, n, u, v, a, alpha, alpha_dot, params...);
235 std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
243 template <
typename TractionType>
244 void addTraction(
const std::string& domain_name, TractionType traction_function)
246 addTractionAllParams(domain_name, traction_function, std::make_index_sequence<6 +
sizeof...(parameter_space)>{});
255 template <
int... active_parameters,
typename PressureType>
257 PressureType pressure_function)
262 depends_on, domain_name,
263 [=](
auto t_info,
auto X,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto alpha,
auto alpha_old,
265 auto [u_current, v_current, a_current] = captured_disp_rule->interpolate(t_info, u, u_old, v_old, a_old);
266 auto [alpha_current, alpha_dot] = captured_state_rule->interpolate(t_info, alpha, alpha_old);
268 auto x_current = X + u_current;
269 auto n_deformed =
cross(get<DERIVATIVE>(x_current));
270 auto n_shape_norm =
norm(
cross(get<DERIVATIVE>(X)));
272 auto pressure = pressure_function(t_info.time(), get<VALUE>(X), u_current, v_current, a_current,
273 alpha_current, alpha_dot, get<VALUE>(params)...);
275 return pressure * n_deformed * (1.0 / n_shape_norm);
278 addCycleZeroBoundaryIntegralImpl(
280 [=](
auto t_info,
auto X,
auto u,
auto v,
auto a,
auto alpha,
auto... params) {
281 auto alpha_val = get<VALUE>(alpha);
282 auto alpha_dot = 0.0 * alpha_val;
284 auto x_current = X + u;
285 auto n_deformed =
cross(get<DERIVATIVE>(x_current));
286 auto n_shape_norm =
norm(
cross(get<DERIVATIVE>(X)));
288 auto pressure = pressure_function(t_info.time(), get<VALUE>(X), get<VALUE>(u), get<VALUE>(v), get<VALUE>(a),
289 alpha_val, alpha_dot, get<VALUE>(params)...);
291 return pressure * n_deformed * (1.0 / n_shape_norm);
293 std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
301 template <
typename PressureType>
302 void addPressure(
const std::string& domain_name, PressureType pressure_function)
304 addPressureAllParams(domain_name, pressure_function, std::make_index_sequence<6 +
sizeof...(parameter_space)>{});
313 template <
typename EvolutionType>
319 state_weak_form->addBodyIntegral(domain_name, [=](
auto t_info,
auto ,
auto alpha,
auto alpha_old,
auto u,
320 auto u_old,
auto v_old,
auto a_old,
auto... params) {
321 auto [u_current, v_current, a_current] = captured_disp_rule->interpolate(t_info, u, u_old, v_old, a_old);
322 auto [alpha_current, alpha_dot] = captured_state_rule->interpolate(t_info, alpha, alpha_old);
324 auto residual_val = evolution_law(t_info, get<VALUE>(alpha_current), get<VALUE>(alpha_dot),
325 get<DERIVATIVE>(u_current), params...);
333 template <
typename BodyForceType, std::size_t... Is>
334 void addBodyForceAllParams(
const std::string& domain_name, BodyForceType force_function, std::index_sequence<Is...>)
339 template <
typename TractionType, std::size_t... Is>
340 void addTractionAllParams(
const std::string& domain_name, TractionType traction_function, std::index_sequence<Is...>)
342 addTraction(DependsOn<
static_cast<int>(Is)...>{}, domain_name, traction_function);
345 template <
typename PressureType, std::size_t... Is>
346 void addPressureAllParams(
const std::string& domain_name, PressureType pressure_function, std::index_sequence<Is...>)
348 addPressure(DependsOn<
static_cast<int>(Is)...>{}, domain_name, pressure_function);
352 template <
typename IntegrandType, std::size_t... Is>
353 void addCycleZeroBodySourceImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
358 template <
typename IntegrandType, std::size_t... Is>
359 void addCycleZeroBoundaryFluxImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
364 template <
typename IntegrandType, std::size_t... Is>
365 void addCycleZeroBoundaryIntegralImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
382 template <
int dim,
int disp_order,
typename StateSpace,
typename DisplacementTimeRule,
typename InternalVarTimeRule,
383 typename... parameter_space>
384 SolidMechanicsWithInternalVarsSystem<dim, disp_order, StateSpace, DisplacementTimeRule, InternalVarTimeRule,
387 DisplacementTimeRule disp_rule, InternalVarTimeRule state_rule,
388 std::string prepend_name =
"",
389 std::shared_ptr<CoupledSystemSolver> cycle_zero_solver =
nullptr,
392 auto field_store = std::make_shared<FieldStore>(mesh, 100);
394 auto prefix = [&](
const std::string& name) {
395 if (prepend_name.empty()) {
398 return prepend_name +
"_" + name;
403 field_store->addShapeDisp(shape_disp_type);
406 auto disp_time_rule_ptr = std::make_shared<DisplacementTimeRule>(disp_rule);
408 auto disp_bc = field_store->addIndependent(disp_type, disp_time_rule_ptr);
409 auto disp_old_type = field_store->addDependent(disp_type, FieldStore::TimeDerivative::VAL, prefix(
"displacement"));
414 auto state_time_rule_ptr = std::make_shared<InternalVarTimeRule>(state_rule);
416 auto state_bc = field_store->addIndependent(state_type, state_time_rule_ptr);
417 auto state_old_type = field_store->addDependent(state_type, FieldStore::TimeDerivative::VAL, prefix(
"state"));
420 std::vector<FieldState> parameter_fields;
422 (parameter_fields.push_back(field_store->getField(prefix(
"param_" + parameter_types.
name))), ...);
425 InternalVarTimeRule, parameter_space...>;
428 std::string solid_res_name = prefix(
"solid_residual");
429 auto solid_weak_form = std::make_shared<typename SystemType::SolidWeakFormType>(
430 solid_res_name, field_store->getMesh(), field_store->getField(disp_type.
name).get()->space(),
431 field_store->createSpaces(solid_res_name, disp_type.
name, disp_type, disp_old_type, velo_old_type, accel_old_type,
432 state_type, state_old_type,
436 std::string state_res_name = prefix(
"state_residual");
437 auto state_weak_form = std::make_shared<typename SystemType::StateWeakFormType>(
438 state_res_name, field_store->getMesh(), field_store->getField(state_type.
name).get()->space(),
439 field_store->createSpaces(state_res_name, state_type.
name, state_type, state_old_type, disp_type, disp_old_type,
440 velo_old_type, accel_old_type,
444 std::string cycle_zero_name = prefix(
"solid_reaction");
445 auto cycle_zero_solid_weak_form = std::make_shared<typename SystemType::CycleZeroSolidWeakFormType>(
446 cycle_zero_name, field_store->getMesh(), field_store->getField(accel_old_type.name).get()->space(),
447 field_store->createSpaces(cycle_zero_name, accel_old_type.name, disp_type, velo_old_type, accel_old_type,
450 if (cycle_zero_solver ==
nullptr) {
451 cycle_zero_solver = solver->singleBlockSolver(0);
453 SLIC_ERROR_IF(cycle_zero_solver ==
nullptr,
454 "Could not derive a cycle-zero solver for block 0 from the provided internal-vars solid mechanics "
458 std::vector<std::shared_ptr<WeakForm>> weak_forms{solid_weak_form, state_weak_form};
459 auto advancer = std::make_shared<MultiphysicsTimeIntegrator>(field_store, weak_forms, solver,
460 cycle_zero_solid_weak_form, cycle_zero_solver);
462 return SystemType{{field_store, solver, advancer, parameter_fields, prepend_name},
465 cycle_zero_solid_weak_form,
469 state_time_rule_ptr};
475 template <
int dim,
int disp_order,
typename StateSpace,
typename DisplacementTimeRule,
typename InternalVarTimeRule,
476 typename... parameter_space>
478 DisplacementTimeRule disp_rule, InternalVarTimeRule state_rule,
479 std::shared_ptr<CoupledSystemSolver> cycle_zero_solver =
nullptr,
482 return buildSolidMechanicsWithInternalVarsSystem<dim, disp_order, StateSpace>(mesh, solver, disp_rule, state_rule,
"",
483 cycle_zero_solver, parameter_types...);
Defines a BasePhysics implementation backed by FieldState objects and a gretl computational graph.
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Accelerator functionality.
SMITH_HOST_DEVICE auto cross(const tensor< T, 3, 2 > &A)
compute the cross product of the columns of A: A(:,1) x A(:,2)
SolidMechanicsWithInternalVarsSystem< dim, disp_order, StateSpace, DisplacementTimeRule, InternalVarTimeRule, parameter_space... > buildSolidMechanicsWithInternalVarsSystem(std::shared_ptr< Mesh > mesh, std::shared_ptr< CoupledSystemSolver > solver, DisplacementTimeRule disp_rule, InternalVarTimeRule state_rule, std::string prepend_name="", std::shared_ptr< CoupledSystemSolver > cycle_zero_solver=nullptr, FieldType< parameter_space >... parameter_types)
Factory function to build a solid mechanics system with internal variable.
constexpr SMITH_HOST_DEVICE auto norm(const isotropic_tensor< T, m, m > &I)
compute the Frobenius norm (sqrt(tr(dot(transpose(I), I)))) of an isotropic tensor
mfem::future::tuple< T... > tuple
Expose MFEM tuple in the Smith namespace.
This file contains nonlinear block solver interfaces and helpers.
Interface and implementations for advancing from one step to the next. Typically these are time integ...
@ DOT
The first time derivative.
@ DDOT
The second time derivative.
Representation of a field type with a name and an optional unknown index.
std::string name
Name of the field.
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
Base struct for physics systems containing common members and helper functions.
std::string prefix(const std::string &name) const
Helper function to prepend the physics name to a string.
std::shared_ptr< StateAdvancer > advancer
The state advancer.
std::shared_ptr< FieldStore > field_store
Field store managing the system's fields.
const std::vector< FieldState > & getParameterFields() const
Get the list of all parameter fields.
Defines the SystemBase struct for common system functionality.
Implementation of the tensor class used by Functional.
Provides templated implementations for discretizing values, velocities and accelerations from current...
Smith tuple compatibility layer over mfem::future::tuple.