14 #include "smith/differentiable_numerics/field_store.hpp"
18 #include "smith/differentiable_numerics/multiphysics_time_integrator.hpp"
39 template <
int dim,
int order,
typename DisplacementTimeRule = ImplicitNewmarkSecondOrderTimeIntegrationRule,
40 typename... parameter_space>
42 static_assert(DisplacementTimeRule::num_states == 4,
"SolidMechanicsSystem requires a 4-state time integration rule");
55 std::shared_ptr<CycleZeroSolidWeakFormType>
57 std::shared_ptr<DirichletBoundaryConditions>
disp_bc;
107 template <
typename MaterialType>
108 void setMaterial(
const MaterialType& material,
const std::string& domain_name)
112 domain_name, [=](
auto t_info,
auto ,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto... params) {
113 auto [u_current, v_current, a_current] = captured_rule->interpolate(t_info, u, u_old, v_old, a_old);
115 typename MaterialType::State state;
116 auto pk_stress = material(state, get<DERIVATIVE>(u_current), params...);
118 return smith::tuple{get<VALUE>(a_current) * material.density, pk_stress};
123 domain_name, [=](
auto ,
auto ,
auto u,
auto ,
auto a,
auto... params) {
124 typename MaterialType::State state;
125 auto pk_stress = material(state, get<DERIVATIVE>(u), params...);
127 return smith::tuple{get<VALUE>(a) * material.density, pk_stress};
139 template <
int... active_parameters,
typename BodyForceType>
141 BodyForceType force_function)
145 depends_on, domain_name, [=](
auto t_info,
auto X,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto... params) {
146 auto [u_current, v_current, a_current] = captured_rule->interpolate(t_info, u, u_old, v_old, a_old);
147 return force_function(t_info.time(), X, u_current, v_current, a_current, params...);
150 addCycleZeroBodySourceImpl(
152 [=](
auto t_info,
auto X,
auto u,
auto v_old,
auto a,
auto... params) {
153 return force_function(t_info.time(), X, u, v_old, a, params...);
155 std::make_index_sequence<3 +
sizeof...(parameter_space)>{});
164 template <
typename BodyForceType>
165 void addBodyForce(
const std::string& domain_name, BodyForceType force_function)
167 addBodyForceAllParams(domain_name, force_function, std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
178 template <
int... active_parameters,
typename TractionType>
180 TractionType traction_function)
184 depends_on, domain_name,
185 [=](
auto t_info,
auto X,
auto n,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto... params) {
186 auto [u_current, v_current, a_current] = captured_rule->interpolate(t_info, u, u_old, v_old, a_old);
187 return traction_function(t_info.time(), X, n, u_current, v_current, a_current, params...);
190 addCycleZeroBoundaryFluxImpl(
192 [=](
auto t_info,
auto X,
auto n,
auto u,
auto v_old,
auto a,
auto... params) {
193 return traction_function(t_info.time(), X, n, u, v_old, a, params...);
195 std::make_index_sequence<3 +
sizeof...(parameter_space)>{});
204 template <
typename TractionType>
205 void addTraction(
const std::string& domain_name, TractionType traction_function)
207 addTractionAllParams(domain_name, traction_function, std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
218 template <
int... active_parameters,
typename PressureType>
220 PressureType pressure_function)
224 depends_on, domain_name, [=](
auto t_info,
auto X,
auto u,
auto u_old,
auto v_old,
auto a_old,
auto... params) {
225 auto u_current = captured_rule->value(t_info, u, u_old, v_old, a_old);
227 auto x_current = X + u_current;
228 auto n_deformed =
cross(get<DERIVATIVE>(x_current));
229 auto n_shape_norm =
norm(
cross(get<DERIVATIVE>(X)));
231 auto pressure = pressure_function(t_info.time(), get<VALUE>(X), get<VALUE>(params)...);
233 return pressure * n_deformed * (1.0 / n_shape_norm);
236 addCycleZeroBoundaryIntegralImpl(
238 [=](
auto t_info,
auto X,
auto u,
auto ,
auto ,
auto... params) {
241 auto x_current = X + u_current;
242 auto n_deformed =
cross(get<DERIVATIVE>(x_current));
243 auto n_shape_norm =
norm(
cross(get<DERIVATIVE>(X)));
245 auto pressure = pressure_function(t_info.time(), get<VALUE>(X), get<VALUE>(params)...);
247 return pressure * n_deformed * (1.0 / n_shape_norm);
249 std::make_index_sequence<3 +
sizeof...(parameter_space)>{});
258 template <
typename PressureType>
259 void addPressure(
const std::string& domain_name, PressureType pressure_function)
261 addPressureAllParams(domain_name, pressure_function, std::make_index_sequence<4 +
sizeof...(parameter_space)>{});
265 template <
typename BodyForceType, std::size_t... Is>
266 void addBodyForceAllParams(
const std::string& domain_name, BodyForceType force_function, std::index_sequence<Is...>)
271 template <
typename TractionType, std::size_t... Is>
272 void addTractionAllParams(
const std::string& domain_name, TractionType traction_function, std::index_sequence<Is...>)
274 addTraction(DependsOn<
static_cast<int>(Is)...>{}, domain_name, traction_function);
277 template <
typename PressureType, std::size_t... Is>
278 void addPressureAllParams(
const std::string& domain_name, PressureType pressure_function, std::index_sequence<Is...>)
280 addPressure(DependsOn<
static_cast<int>(Is)...>{}, domain_name, pressure_function);
284 template <
typename IntegrandType, std::size_t... Is>
285 void addCycleZeroBodySourceImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
290 template <
typename IntegrandType, std::size_t... Is>
291 void addCycleZeroBoundaryFluxImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
296 template <
typename IntegrandType, std::size_t... Is>
297 void addCycleZeroBoundaryIntegralImpl(
const std::string& name, IntegrandType f, std::index_sequence<Is...>)
318 template <
int dim,
int order,
typename DisplacementTimeRule,
typename... parameter_space>
320 std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver, DisplacementTimeRule disp_time_rule,
321 std::string prepend_name =
"", std::shared_ptr<CoupledSystemSolver> cycle_zero_solver =
nullptr,
324 auto field_store = std::make_shared<FieldStore>(mesh, 100);
326 auto prefix = [&](
const std::string& name) {
327 if (prepend_name.empty()) {
330 return prepend_name +
"_" + name;
335 field_store->addShapeDisp(shape_disp_type);
338 auto disp_time_rule_ptr = std::make_shared<DisplacementTimeRule>(disp_time_rule);
340 auto disp_bc = field_store->addIndependent(disp_type, disp_time_rule_ptr);
343 auto disp_old_type = field_store->addDependent(disp_type, FieldStore::TimeDerivative::VAL, prefix(
"displacement"));
348 std::vector<FieldState> parameter_fields;
350 (parameter_fields.push_back(field_store->getField(prefix(
"param_" + parameter_types.
name))), ...);
355 std::string force_name = prefix(
"solid_force");
356 auto solid_weak_form = std::make_shared<typename SystemType::SolidWeakFormType>(
357 force_name, field_store->getMesh(), field_store->getField(disp_type.
name).get()->space(),
358 field_store->createSpaces(force_name, disp_type.
name, disp_type, disp_old_type, velo_old_type, accel_old_type,
362 std::string cycle_zero_name = prefix(
"solid_reaction");
363 auto cycle_zero_solid_weak_form = std::make_shared<typename SystemType::CycleZeroSolidWeakFormType>(
364 cycle_zero_name, field_store->getMesh(), field_store->getField(accel_old_type.name).get()->space(),
365 field_store->createSpaces(cycle_zero_name, accel_old_type.name, disp_type, velo_old_type, accel_old_type,
368 if (cycle_zero_solver ==
nullptr) {
369 cycle_zero_solver = solver->singleBlockSolver(0);
371 SLIC_ERROR_IF(cycle_zero_solver ==
nullptr,
372 "Could not derive a cycle-zero solver for block 0 from the provided solid mechanics solver.");
375 std::vector<std::shared_ptr<WeakForm>> weak_forms{solid_weak_form};
376 auto advancer = std::make_shared<MultiphysicsTimeIntegrator>(field_store, weak_forms, solver,
377 cycle_zero_solid_weak_form, cycle_zero_solver);
379 return SystemType{{field_store, solver, advancer, parameter_fields, prepend_name},
381 cycle_zero_solid_weak_form,
389 template <
int dim,
int order,
typename DisplacementTimeRule,
typename... parameter_space>
391 std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver, DisplacementTimeRule disp_time_rule,
394 return buildSolidMechanicsSystem<dim, order>(mesh, solver, disp_time_rule, std::move(prepend_name),
nullptr,
401 template <
int dim,
int order,
typename DisplacementTimeRule,
typename... parameter_space>
403 std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver, DisplacementTimeRule disp_time_rule,
406 return buildSolidMechanicsSystem<dim, order>(mesh, solver, disp_time_rule,
"", cycle_zero_solver, parameter_types...);
412 template <
int dim,
int order,
typename DisplacementTimeRule,
typename... parameter_space>
414 std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver, DisplacementTimeRule disp_time_rule,
417 return buildSolidMechanicsSystem<dim, order>(mesh, solver, disp_time_rule,
"",
nullptr, 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)
SolidMechanicsSystem< dim, order, DisplacementTimeRule, parameter_space... > buildSolidMechanicsSystem(std::shared_ptr< Mesh > mesh, std::shared_ptr< CoupledSystemSolver > solver, DisplacementTimeRule disp_time_rule, std::string prepend_name="", std::shared_ptr< CoupledSystemSolver > cycle_zero_solver=nullptr, FieldType< parameter_space >... parameter_types)
Factory function to build a solid dynamics system with configurable time integration.
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.
decltype(detail::time_rule_params_impl< Space, Tail... >(std::make_index_sequence< Rule::num_states >{})) TimeRuleParams
Generate a Parameters<...> type with Rule::num_states copies of Space followed by additional Tail typ...
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 ...
System struct for solid dynamics with configurable time integration.
std::shared_ptr< DisplacementTimeRule > disp_time_rule
Time integration rule.
void addBodyForce(DependsOn< active_parameters... > depends_on, const std::string &domain_name, BodyForceType force_function)
Add a body force to the system (with DependsOn).
std::shared_ptr< CycleZeroSolidWeakFormType > cycle_zero_solid_weak_form
Cycle-zero weak form for initial acceleration solve.
std::shared_ptr< SolidWeakFormType > solid_weak_form
Solid mechanics weak form.
std::vector< ReactionInfo > getReactionInfos() const
Get information about reaction fields for this system.
void addBodyForce(const std::string &domain_name, BodyForceType force_function)
Add a body force to the system.
void addTraction(DependsOn< active_parameters... > depends_on, const std::string &domain_name, TractionType traction_function)
Add a surface traction (flux) to the system (with DependsOn).
std::vector< FieldState > getStateFields() const
Get the list of all state fields (displacement_solve_state, displacement, velocity,...
void addPressure(DependsOn< active_parameters... > depends_on, const std::string &domain_name, PressureType pressure_function)
Add a pressure boundary condition (follower force) (with DependsOn).
void addPressure(const std::string &domain_name, PressureType pressure_function)
Add a pressure boundary condition (follower force).
void setMaterial(const MaterialType &material, const std::string &domain_name)
Set the material model for a domain, defining integrals for the solid weak form.
std::shared_ptr< DirichletBoundaryConditions > disp_bc
Displacement boundary conditions.
std::vector< FieldState > getOutputFieldStates() const
Get the list of physical, non-solve state fields.
void addTraction(const std::string &domain_name, TractionType traction_function)
Add a surface traction (flux) to the system.
std::unique_ptr< DifferentiablePhysics > createDifferentiablePhysics(std::string physics_name)
Create a DifferentiablePhysics object for this system.
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.
Provides templated implementations for discretizing values, velocities and accelerations from current...