Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
39cf5ab
Working out the new interface.
tupek2 Feb 9, 2026
f8458a6
Merge branch 'tupek/differentiable_block_solver' into tupek/field_sto…
tupek2 Feb 10, 2026
ea0ca71
Some progress on the new design.
tupek2 Feb 10, 2026
0a44b2b
update new gretl.
tupek2 Feb 10, 2026
1b78255
Merge branch 'tupek/differentiable_block_solver' into tupek/field_sto…
tupek2 Feb 10, 2026
a03c722
Refactoring thermo mechanics example to use generic multiphysics time…
mrtupek2 Feb 11, 2026
cf22c89
Cleanup interface by having a build method to construct a system with…
mrtupek2 Feb 11, 2026
8e413ee
--aned
mrtupek2 Feb 11, 2026
1d8a7a5
Working through new interface issues. there is still a crash in the …
mrtupek2 Feb 11, 2026
1e5219f
Address interface changes in contact examples.
tupek2 Feb 11, 2026
a977f34
Still working on debugging reverse pass.
tupek2 Feb 11, 2026
121ff6a
Update new continutation solvers.
mrtupek2 Feb 11, 2026
36eeebb
Progress on debugging issue.
mrtupek2 Feb 12, 2026
d5544ff
Fix bug in sending multiple params to residuals in some cases.
mrtupek2 Feb 12, 2026
edfe764
some docs.
mrtupek2 Feb 12, 2026
9cc8d29
Line changes.
tupek2 Feb 12, 2026
a04b7cb
Use current continutation solvers.
tupek2 Feb 12, 2026
f44f16b
Fix some style.
tupek2 Feb 12, 2026
de69f85
Fix docs and style.
tupek2 Feb 12, 2026
fc8abbe
Add addition runtime checks for consistent use of spaces and fields.
mrtupek2 Feb 12, 2026
2441fcb
Refactor existing solid mechanics state advancer to use the new multi…
mrtupek2 Feb 13, 2026
04370ae
Refactoring to improve testing of backpropagation.
mrtupek2 Feb 13, 2026
ec0ab77
Clearer names for dims and such.
mrtupek2 Feb 13, 2026
211bc93
Fix style.
mrtupek2 Feb 13, 2026
fe0c79e
style change to reduce lines.
mrtupek2 Feb 13, 2026
1148e7f
refactor solid state advancer to reuse the multiphysics advancer.
mrtupek2 Feb 14, 2026
3ca1727
A working state, but there is a lot to cleanup and review.
mrtupek2 Feb 14, 2026
ae37692
Working tests, a bit cleaner interface.
mrtupek2 Feb 14, 2026
3e0bd29
Simplifying tests and implementations.
mrtupek2 Feb 15, 2026
2206310
Some rename clean remove heat transfer weak form that will be unused.
mrtupek2 Feb 15, 2026
8bf0819
Refactor solid mechanics system for cleaner integrand interface.
mrtupek2 Feb 15, 2026
58f2a60
Work out the interface a bit more.
mrtupek2 Feb 15, 2026
83a8e96
Some style adjusts.
mrtupek2 Feb 15, 2026
6302652
Work on simplifying the muliphysics interfaces.
mrtupek2 Feb 15, 2026
0432b96
Update naming, have some initial pressure testing.
mrtupek2 Feb 15, 2026
5e9b405
Get a lightweight thermal only system working.
mrtupek2 Feb 15, 2026
8af4f92
Fix style, accept the template oddness in that test which is due to i…
mrtupek2 Feb 15, 2026
c3bd1df
Small adjust to state variable evolution.
mrtupek2 Feb 16, 2026
c0d05ec
Some stylistic improvements, fix up the test to use state variables a…
mrtupek2 Feb 19, 2026
b51e655
Address a few more style points.
mrtupek2 Feb 19, 2026
7ee6ae3
Merge branch 'develop' into tupek/field_store_interface_extended
tupek2 Feb 19, 2026
154b63b
Fix up a bad change.
tupek2 Feb 19, 2026
126e0b6
Style and docs, , mostly.
tupek2 Feb 19, 2026
eed13b1
Merge branch 'develop' into tupek/field_store_interface_extended
tupek2 Mar 4, 2026
553b28a
Merge branch 'develop' into tupek/field_store_interface_extended
lihanyu97 Mar 10, 2026
731cf21
Change VALUE to VAL
lihanyu97 Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/smith/differentiable_numerics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@

set(differentiable_numerics_sources
field_state.cpp
field_store.cpp
differentiable_physics.cpp
lumped_mass_explicit_newmark_state_advancer.cpp
solid_mechanics_state_advancer.cpp
solid_mechanics_time_integrator.cpp
differentiable_solver.cpp
nonlinear_solve.cpp
evaluate_objective.cpp
dirichlet_boundary_conditions.cpp
multiphysics_time_integrator.cpp
)

set(differentiable_numerics_headers
field_state.hpp
field_store.hpp
state_advancer.hpp
reaction.hpp
differentiable_solver.hpp
Expand All @@ -25,15 +28,17 @@ set(differentiable_numerics_headers
explicit_dynamic_solve.hpp
lumped_mass_weak_form.hpp
lumped_mass_explicit_newmark_state_advancer.hpp
solid_mechanics_state_advancer.hpp
solid_mechanics_time_integrator.hpp
nonlinear_solve.hpp
evaluate_objective.hpp
dirichlet_boundary_conditions.hpp
time_integration_rule.hpp
time_discretized_weak_form.hpp
differentiable_solid_mechanics.hpp
paraview_writer.hpp
differentiable_test_utils.hpp
multiphysics_time_integrator.hpp
solid_dynamics_system.hpp
thermo_mechanics_system.hpp
system_base.hpp
)

set(differentiable_numerics_depends
Expand Down
13 changes: 9 additions & 4 deletions src/smith/differentiable_numerics/differentiable_physics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,14 @@ const FiniteElementDual& DifferentiablePhysics::dual(const std::string& dual_nam
reaction_name_to_reaction_index_.find(dual_name) == reaction_name_to_reaction_index_.end(),
axom::fmt::format("Could not find dual named {0} in mesh with tag \"{1}\" to get", dual_name, mesh_->tag()));
size_t reaction_index = reaction_name_to_reaction_index_.at(dual_name);

SLIC_ERROR_IF(reaction_states_.empty() && !reaction_names_.empty(),
"Reactions were not computed during advanceState, but were requested.");

SLIC_ERROR_IF(
reaction_index >= reaction_names_.size(),
reaction_index >= reaction_states_.size(),
"Dual reactions not correctly allocated yet, cannot get dual until after initializationStep is called.");

TimeInfo time_info(time_prev_, dt_prev_, static_cast<size_t>(cycle_prev_));
reaction_states_ = advancer_->computeReactions(time_info, *field_shape_displacement_, field_states_, field_params_);
return *reaction_states_[reaction_index].get();
}

Expand Down Expand Up @@ -225,7 +227,10 @@ void DifferentiablePhysics::advanceTimestep(double dt)
dt_prev_ = dt;

TimeInfo time_info(time_, dt, static_cast<size_t>(cycle_));
field_states_ = advancer_->advanceState(time_info, *field_shape_displacement_, field_states_, field_params_);
auto [states, reactions] =
advancer_->advanceState(time_info, *field_shape_displacement_, field_states_, field_params_);
field_states_ = states;
reaction_states_ = reactions;

cycle_++;
time_ += dt;
Expand Down

This file was deleted.

25 changes: 22 additions & 3 deletions src/smith/differentiable_numerics/differentiable_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,13 @@ std::vector<DifferentiableBlockSolver::FieldPtr> LinearDifferentiableBlockSolver
u_bars[static_cast<size_t>(row_i)]->space(), "u_dual_" + std::to_string(row_i));
}

// If it's a 1x1 system, pass the operator directly to avoid potential BlockOperator issues with smoothers
if (num_rows == 1) {
mfem_solver->SetOperator(*jacobian_transposed[0][0]);
mfem_solver->Mult(*u_bars[0], *u_duals[0]);
return u_duals;
}

mfem::Array<int> block_offsets;
block_offsets.SetSize(num_rows + 1);
block_offsets[0] = 0;
Expand Down Expand Up @@ -303,7 +310,7 @@ std::vector<DifferentiableBlockSolver::FieldPtr> NonlinearDifferentiableBlockSol

auto residual_op_ = std::make_unique<mfem_ext::StdFunctionOperator>(
block_u->Size(),
[&residual_funcs, num_rows, &u_guesses, &block_r](const mfem::Vector& u_, mfem::Vector& r_) {
[&residual_funcs, num_rows, &u_guesses, &block_r, &block_offsets](const mfem::Vector& u_, mfem::Vector& r_) {
const mfem::BlockVector* u = dynamic_cast<const mfem::BlockVector*>(&u_);
SLIC_ERROR_IF(!u, "Invalid u cast in block differentiable solver to a block vector");
for (int row_i = 0; row_i < num_rows; ++row_i) {
Expand All @@ -319,7 +326,11 @@ std::vector<DifferentiableBlockSolver::FieldPtr> NonlinearDifferentiableBlockSol
},
[this, &block_offsets, &u_guesses, jacobian_funcs, num_rows](const mfem::Vector& u_) -> mfem::Operator& {
const mfem::BlockVector* u = dynamic_cast<const mfem::BlockVector*>(&u_);
SLIC_ERROR_IF(!u, "Invalid u cast in block differentiable solver to a block vector");
mfem::BlockVector u_block_wrapper;
if (!u) {
u_block_wrapper.Update(const_cast<double*>(u_.GetData()), block_offsets);
u = &u_block_wrapper;
}
for (int row_i = 0; row_i < num_rows; ++row_i) {
*u_guesses[static_cast<size_t>(row_i)] = u->GetBlock(row_i);
}
Expand Down Expand Up @@ -359,6 +370,15 @@ std::vector<DifferentiableBlockSolver::FieldPtr> NonlinearDifferentiableBlockSol
u_bars[static_cast<size_t>(row_i)]->space(), "u_dual_" + std::to_string(row_i));
}

auto& linear_solver = nonlinear_solver_->linearSolver();

// If it's a 1x1 system, pass the operator directly to avoid potential BlockOperator issues with smoothers
if (num_rows == 1) {
linear_solver.SetOperator(*jacobian_transposed[0][0]);
linear_solver.Mult(*u_bars[0], *u_duals[0]);
return u_duals;
}

mfem::Array<int> block_offsets;
block_offsets.SetSize(num_rows + 1);
block_offsets[0] = 0;
Expand All @@ -382,7 +402,6 @@ std::vector<DifferentiableBlockSolver::FieldPtr> NonlinearDifferentiableBlockSol
}
}

auto& linear_solver = nonlinear_solver_->linearSolver();
linear_solver.SetOperator(*block_jac);
linear_solver.Mult(*block_r, *block_ds);

Expand Down
19 changes: 19 additions & 0 deletions src/smith/differentiable_numerics/differentiable_test_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,28 @@
#include "gretl/double_state.hpp"
#include "smith/differentiable_numerics/field_state.hpp"
#include "smith/physics/scalar_objective.hpp"
#include "smith/physics/boundary_conditions/boundary_condition_manager.hpp"

namespace smith {

/**
* @brief Verify that reaction forces are zero at non-Dirichlet DOFs.
* @param reaction The reaction field to check.
* @param bc_manager Boundary condition manager to identify Dirichlet DOFs.
* @param tolerance Absolute tolerance for zero check.
*/
inline void checkUnconstrainedReactions(const FiniteElementDual& reaction, const BoundaryConditionManager& bc_manager,
double tolerance = 1e-8)
{
FiniteElementState unconstrained_reactions(reaction.space(), "unconstrained_reactions");
unconstrained_reactions = reaction;
unconstrained_reactions.SetSubVector(bc_manager.allEssentialTrueDofs(), 0.0);

double max_unconstrained = unconstrained_reactions.Normlinf();
EXPECT_LT(max_unconstrained, tolerance)
<< "Reaction forces should be zero at non-Dirichlet DOFs. Max violation: " << max_unconstrained;
}

/// @brief Utility function to construct a smith::functional which evaluates the total kinetic energy
template <typename DispSpace, typename DensitySpace>
auto createKineticEnergyIntegrator(smith::Domain& domain, const mfem::ParFiniteElementSpace& velocity_space,
Expand Down
Loading
Loading