Skip to content

Commit

Permalink
exp contact optimizations (idaholab#29732)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxnezdyur committed Feb 5, 2025
1 parent 31fbe2f commit 461e0e5
Show file tree
Hide file tree
Showing 15 changed files with 809 additions and 261 deletions.
2 changes: 1 addition & 1 deletion framework/include/timeintegrators/ExplicitTimeIntegrator.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class ExplicitTimeIntegrator : public TimeIntegrator, public MeshChangedInterfac
NumericVector<Real> * _solution_update;

/// Diagonal of the lumped mass matrix (and its inversion)
NumericVector<Real> * _mass_matrix_diag;
NumericVector<Real> * _mass_matrix_diag_inverted;

/// Vector of 1's to help with creating the lumped mass matrix
NumericVector<Real> * _ones;
Expand Down
19 changes: 8 additions & 11 deletions framework/src/timeintegrators/ExplicitTimeIntegrator.C
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ ExplicitTimeIntegrator::ExplicitTimeIntegrator(const InputParameters & parameter
_solve_type(getParam<MooseEnum>("solve_type")),
_explicit_residual(addVector("explicit_residual", false, PARALLEL)),
_solution_update(addVector("solution_update", true, PARALLEL)),
_mass_matrix_diag(addVector("mass_matrix_diag", false, PARALLEL))
_mass_matrix_diag_inverted(addVector("mass_matrix_diag_inverted", true, GHOSTED))
{
_Ke_time_tag = _fe_problem.getMatrixTagID("TIME");

Expand All @@ -52,10 +52,7 @@ ExplicitTimeIntegrator::ExplicitTimeIntegrator(const InputParameters & parameter
_fe_problem.solverParams()._type = Moose::ST_LINEAR;

if (_solve_type == LUMPED || _solve_type == LUMP_PRECONDITIONED)
_ones = addVector("ones", false, PARALLEL);

// don't set any of the common SNES-related petsc options to prevent unused option warnings
Moose::PetscSupport::dontAddCommonSNESOptions(_fe_problem);
_ones = addVector("ones", true, PARALLEL);
}

void
Expand Down Expand Up @@ -89,7 +86,7 @@ ExplicitTimeIntegrator::meshChanged()

if (_solve_type == LUMP_PRECONDITIONED)
{
_preconditioner = std::make_unique<LumpedPreconditioner>(*_mass_matrix_diag);
_preconditioner = std::make_unique<LumpedPreconditioner>(*_mass_matrix_diag_inverted);
_linear_solver->attach_preconditioner(_preconditioner.get());
_linear_solver->init();
}
Expand All @@ -116,13 +113,13 @@ ExplicitTimeIntegrator::performExplicitSolve(SparseMatrix<Number> & mass_matrix)
// Computes the sum of each row (lumping)
// Note: This is actually how PETSc does it
// It's not "perfectly optimal" - but it will be fast (and universal)
mass_matrix.vector_mult(*_mass_matrix_diag, *_ones);
mass_matrix.vector_mult(*_mass_matrix_diag_inverted, *_ones);

// "Invert" the diagonal mass matrix
_mass_matrix_diag->reciprocal();
_mass_matrix_diag_inverted->reciprocal();

// Multiply the inversion by the RHS
_solution_update->pointwise_mult(*_mass_matrix_diag, *_explicit_residual);
_solution_update->pointwise_mult(*_mass_matrix_diag_inverted, *_explicit_residual);

// Check for convergence by seeing if there is a nan or inf
auto sum = _solution_update->sum();
Expand All @@ -135,8 +132,8 @@ ExplicitTimeIntegrator::performExplicitSolve(SparseMatrix<Number> & mass_matrix)
}
case LUMP_PRECONDITIONED:
{
mass_matrix.vector_mult(*_mass_matrix_diag, *_ones);
_mass_matrix_diag->reciprocal();
mass_matrix.vector_mult(*_mass_matrix_diag_inverted, *_ones);
_mass_matrix_diag_inverted->reciprocal();

converged = solveLinearSystem(mass_matrix);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

This object implements node-face constraints for the enforcement of normal
mechanical contact in explicit dynamics. Surrogate balance-momentum equations are
solved at each node on the secondary surface using density and wave speed
material properties and the velocities of the two surfaces in contact.
solved at each node on the secondary surface. For production runs set
[!param](/Constraints/ExplicitDynamicsContactConstraint/optimized) to `true`. While this parameter speeds up the simulation, there will be less outputs available for debugging.

This method MUST be used with the [DirectCentralDifference](source/timeintegrators/DirectCentralDifference.md) time integrator found in the Solid Mechanics module.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class ExplicitDynamicsContactAction : public Action
/// Type that we use in Actions for declaring coupling
typedef std::vector<VariableName> CoupledName;

/// Whether to run in an optimized form.
const bool _optimized;

private:
/**
* Generate constraints for node to face contact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class ExplicitDynamicsContactConstraint : public NodeFaceConstraint,

MooseSharedPointer<DisplacedProblem> _displaced_problem;
Real gapOffset(const Node & node);
Real nodalArea(const Node & node);
Real getPenalty(const Node & node);

const unsigned int _component;
Expand All @@ -109,12 +108,6 @@ class ExplicitDynamicsContactConstraint : public NodeFaceConstraint,
const bool _has_mapped_primary_gap_offset;
const MooseVariable * const _mapped_primary_gap_offset_var;

MooseVariable * _nodal_area_var;
const MooseVariable * _nodal_density_var;
const MooseVariable * _nodal_wave_speed_var;

SystemBase & _aux_system;
const NumericVector<Number> * const _aux_solution;
const Real _penalty;

const bool _print_contact_nodes;
Expand All @@ -123,12 +116,6 @@ class ExplicitDynamicsContactConstraint : public NodeFaceConstraint,

NumericVector<Number> & _residual_copy;

/// Density material for neighbor projection
const MaterialProperty<Real> & _neighbor_density;

/// Wave speed material for neighbor projection
const MaterialProperty<Real> & _neighbor_wave_speed;

/// Nodal gap rate (output for debugging or analyst perusal)
MooseWritableVariable * _gap_rate;

Expand All @@ -141,6 +128,13 @@ class ExplicitDynamicsContactConstraint : public NodeFaceConstraint,

private:
std::unordered_map<dof_id_type, Real> _dof_to_position;

/**
*
* @param lumped_mass The inverted lumped mass vector
* @return Effictive mass of the face
*/
Real computeFaceMass(const NumericVector<Real> & lumped_mass);
};

inline const std::unordered_set<unsigned int> &
Expand Down
78 changes: 40 additions & 38 deletions modules/contact/src/actions/ExplicitDynamicsContactAction.C
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,17 @@ ExplicitDynamicsContactAction::validParams()
"Offset to gap distance from secondary side");
params.addParam<VariableName>("mapped_primary_gap_offset",
"Offset to gap distance mapped from primary side");
params.addParam<bool>(
"optimized", false, "Run contact in optimized form. Same results but less outputs.");

return params;
}

ExplicitDynamicsContactAction::ExplicitDynamicsContactAction(const InputParameters & params)
: Action(params),
_boundary_pairs(getParam<BoundaryName, BoundaryName>("primary", "secondary")),
_model(getParam<MooseEnum>("model").getEnum<ExplicitDynamicsContactModel>())
_model(getParam<MooseEnum>("model").getEnum<ExplicitDynamicsContactModel>()),
_optimized(getParam<bool>("optimized"))
{
// The resulting velocity of the contact algorithm is applied, as the code stands, by modifying
// the old position. This causes artifacts in the internal forces as old position, new position,
Expand Down Expand Up @@ -109,7 +112,7 @@ ExplicitDynamicsContactAction::act()

addNodeFaceContact();

if (_current_task == "add_aux_kernel")
if (_current_task == "add_aux_kernel" && !_optimized)
{ // Add ContactPenetrationAuxAction.
if (!_problem->getDisplacedProblem())
mooseError("Contact requires updated coordinates. Use the 'displacements = ...' line in the "
Expand Down Expand Up @@ -158,56 +161,59 @@ ExplicitDynamicsContactAction::act()
.system()
.variable_type(displacements[0])
.order.get_order();
// Add ContactPenetrationVarAction
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "penetration", var_params);
}
// Add ContactPressureVarAction
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "contact_pressure", var_params);
}
// Add gap rate for output
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";
_problem->addAuxVariable("MooseVariable", "gap_rate", var_params);
}
// Add nodal area contact variable
if (!_optimized)
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";
// Add ContactPenetrationVarAction
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "nodal_area", var_params);
}
// Add nodal density variable
_problem->addAuxVariable("MooseVariable", "penetration", var_params);
}
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "nodal_density", var_params);
_problem->addAuxVariable("MooseVariable", "contact_pressure", var_params);
}
// Add nodal wave speed
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";
// Add nodal area contact variable
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "nodal_wave_speed", var_params);
_problem->addAuxVariable("MooseVariable", "nodal_area", var_params);
}
// Add nodal density variable
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "nodal_density", var_params);
}
// Add nodal wave speed
{
auto var_params = _factory.getValidParams("MooseVariable");
var_params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(OrderWrapper{order});
var_params.set<MooseEnum>("family") = "LAGRANGE";

_problem->addAuxVariable("MooseVariable", "nodal_wave_speed", var_params);
}
}
}

if (_current_task == "add_user_object")
if (_current_task == "add_user_object" && !_optimized)
{
{
auto var_params = _factory.getValidParams("NodalArea");
Expand Down Expand Up @@ -291,7 +297,7 @@ ExplicitDynamicsContactAction::addContactPressureAuxKernel()
ed_contact_action_counter++;

// Add auxiliary kernel if we are the last contact action object.
if (ed_contact_action_counter == actions.size())
if (ed_contact_action_counter == actions.size() && !_optimized)
{
std::vector<BoundaryName> boundary_vector;
std::vector<BoundaryName> pair_boundary_vector;
Expand Down Expand Up @@ -321,8 +327,7 @@ ExplicitDynamicsContactAction::addContactPressureAuxKernel()
params.set<bool>("use_displaced_mesh") = true;

std::string name = _name + "_contact_pressure";
params.set<ExecFlagEnum>("execute_on",
true) = {EXEC_NONLINEAR, EXEC_TIMESTEP_END, EXEC_TIMESTEP_BEGIN};
params.set<ExecFlagEnum>("execute_on", true) = {EXEC_TIMESTEP_END};
_problem->addAuxKernel("ContactPressureAux", name, params);
}
}
Expand Down Expand Up @@ -363,9 +368,6 @@ ExplicitDynamicsContactAction::addNodeFaceContact()

for (const auto & contact_pair : _boundary_pairs)
{
params.set<std::vector<VariableName>>("nodal_area") = {"nodal_area"};
params.set<std::vector<VariableName>>("nodal_density") = {"nodal_density"};
params.set<std::vector<VariableName>>("nodal_wave_speed") = {"nodal_wave_speed"};

if (isParamValid("vel_x"))
params.set<std::vector<VariableName>>("vel_x") = getParam<std::vector<VariableName>>("vel_x");
Expand Down
Loading

0 comments on commit 461e0e5

Please sign in to comment.