18 #include "smith/smith_config.hpp"
20 #ifdef SMITH_USE_TRIBOL
22 #include "tribol/interface/tribol.hpp"
53 static std::unique_ptr<mfem::HypreParMatrix> obtainBlock(mfem::BlockOperator* block_operator,
int iblock,
int jblock)
55 SLIC_ERROR_IF(iblock < 0 || jblock < 0,
"block indicies must be non-negative");
56 SLIC_ERROR_IF(iblock > block_operator->NumRowBlocks() || jblock > block_operator->NumColBlocks(),
57 "one or more block indicies are too large and the requested block does not exist");
58 SLIC_ERROR_IF(block_operator->IsZeroBlock(iblock, jblock),
"attempting to extract a null block");
59 auto Ablk =
dynamic_cast<mfem::HypreParMatrix*
>(&block_operator->GetBlock(iblock, jblock));
60 SLIC_ERROR_IF(!Ablk,
"failed cast block to mfem::HypreParMatrix");
62 auto Ablk_unique = std::make_unique<mfem::HypreParMatrix>(*Ablk);
66 class FiniteElementState;
76 class ContactConstraint :
public Constraint {
88 ContactConstraint(
int interaction_id,
const mfem::ParMesh& mesh,
const std::set<int>& bdry_attr_surf1,
89 const std::set<int>& bdry_attr_surf2, ContactOptions contact_opts,
90 const std::string& name =
"contact_constraint")
91 : Constraint(name), contact_(mesh), contact_opts_{contact_opts}
94 contact_.addContactInteraction(interaction_id, bdry_attr_surf1, bdry_attr_surf2, contact_opts_);
95 interaction_id_ = interaction_id;
99 virtual ~ContactConstraint() {}
110 mfem::Vector evaluate(
double time,
double dt,
const std::vector<ConstFieldPtr>& fields,
111 bool update_fields =
true)
const override
116 contact_.updateGeometry(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP]);
117 auto gaps_hpv = contact_.mergedGaps(
false);
120 cached_gap_.SetSize(gaps_hpv.Size());
121 cached_gap_.Set(1.0, gaps_hpv);
137 std::unique_ptr<mfem::HypreParMatrix> jacobian(
double time,
double dt,
const std::vector<ConstFieldPtr>& fields,
138 int direction,
bool update_fields =
true,
139 [[maybe_unused]]
bool fresh_derivative =
true)
const override
141 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
145 if (update_fields || fresh_derivative) {
148 contact_.updateGeometry(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP],
true);
150 contact_.updateGeometry(cycle, time, dt, std::nullopt, std::nullopt,
true);
152 J_contact_ = contact_.mergedJacobian();
155 auto dgdu = obtainBlock(J_contact_.get(), 1, 0);
172 mfem::Vector residual_contribution(
double time,
double dt,
const std::vector<ConstFieldPtr>& fields,
173 const mfem::Vector& multipliers,
int direction,
bool update_fields =
true,
174 bool fresh_derivative =
true)
const override
176 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
178 if (update_fields || fresh_derivative) {
180 contact_.updateForcesAndJacobian(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP],
183 contact_.updateForcesAndJacobian(cycle, time, dt, std::nullopt, std::nullopt, multipliers);
186 return contact_.forces();
201 std::unique_ptr<mfem::HypreParMatrix> residual_contribution_jacobian(
double time,
double dt,
202 const std::vector<ConstFieldPtr>& fields,
203 const mfem::Vector& multipliers,
int direction,
204 bool update_fields =
true,
205 bool fresh_derivative =
true)
const override
207 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
210 if (update_fields || fresh_derivative) {
212 contact_.updateForcesAndJacobian(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP],
215 contact_.updateForcesAndJacobian(cycle, time, dt, std::nullopt, std::nullopt, multipliers);
217 J_contact_ = contact_.mergedJacobian();
220 auto Hessian = obtainBlock(J_contact_.get(), 0, 0);
234 std::unique_ptr<mfem::HypreParMatrix> jacobian_tilde(
double time,
double dt,
const std::vector<ConstFieldPtr>& fields,
235 int direction,
bool update_fields =
true,
236 [[maybe_unused]]
bool fresh_derivative =
true)
const override
238 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
241 if (update_fields || fresh_derivative) {
242 mfem::Vector p = contact_.mergedPressures();
244 contact_.updateForcesAndJacobian(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP],
247 contact_.updateForcesAndJacobian(cycle, time, dt, std::nullopt, std::nullopt, p);
249 J_contact_ = contact_.mergedJacobian();
252 auto dgduT = obtainBlock(J_contact_.get(), 0, 1);
253 std::unique_ptr<mfem::HypreParMatrix> dgdu(dgduT->Transpose());
257 int numPressureDofs()
const {
return contact_.numPressureDofs(); }
263 mutable ContactData contact_;
268 ContactOptions contact_opts_;
278 mutable std::unique_ptr<mfem::BlockOperator> J_contact_;
283 mutable mfem::Vector cached_gap_;
Specifies interface for evaluating distributed constriants from fields as well as their Jacobians and...
Defines common types and helper functions for using the residual and scalar_objective classes.
Accelerator functionality.