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_.updateGaps(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_.updateGaps(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP],
true);
150 contact_.updateGaps(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_.update(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP], multipliers);
182 contact_.update(cycle, time, dt, std::nullopt, std::nullopt, multipliers);
185 return contact_.forces();
200 std::unique_ptr<mfem::HypreParMatrix> residual_contribution_jacobian(
double time,
double dt,
201 const std::vector<ConstFieldPtr>& fields,
202 const mfem::Vector& multipliers,
int direction,
203 bool update_fields =
true,
204 bool fresh_derivative =
true)
const override
206 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
209 if (update_fields || fresh_derivative) {
211 contact_.update(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP], multipliers);
213 contact_.update(cycle, time, dt, std::nullopt, std::nullopt, multipliers);
215 J_contact_ = contact_.mergedJacobian();
218 auto Hessian = obtainBlock(J_contact_.get(), 0, 0);
232 std::unique_ptr<mfem::HypreParMatrix> jacobian_tilde(
double time,
double dt,
const std::vector<ConstFieldPtr>& fields,
233 int direction,
bool update_fields =
true,
234 [[maybe_unused]]
bool fresh_derivative =
true)
const override
236 SLIC_ERROR_IF(direction != ContactFields::DISP,
"requesting a non displacement-field derivative");
239 if (update_fields || fresh_derivative) {
240 mfem::Vector p = contact_.mergedPressures();
242 contact_.update(cycle, time, dt, *fields[ContactFields::SHAPE], *fields[ContactFields::DISP], p);
244 contact_.update(cycle, time, dt, std::nullopt, std::nullopt, p);
246 J_contact_ = contact_.mergedJacobian();
249 auto dgduT = obtainBlock(J_contact_.get(), 0, 1);
250 std::unique_ptr<mfem::HypreParMatrix> dgdu(dgduT->Transpose());
254 int numPressureDofs()
const {
return contact_.numPressureDofs(); }
260 mutable ContactData contact_;
265 ContactOptions contact_opts_;
275 mutable std::unique_ptr<mfem::BlockOperator> J_contact_;
280 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.