Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
4ccb49e
Initial gretl in serac. Need to work on some tests, maybe documentin…
tupek2 Mar 14, 2025
77b56ab
Revert back to original gretl.
tupek2 Mar 15, 2025
f7e758b
--amend
tupek2 Mar 15, 2025
c19b7ba
Trying to get original checkpoint tests passing again.
tupek2 Mar 15, 2025
4ec0b48
Operation gretl again.
tupek2 Mar 18, 2025
b72a057
Make it a bit less likely toa accidentally no specify a valid zero_du…
tupek2 Mar 18, 2025
ae86ce3
Additional cleanup of compilation warnings.
tupek2 Mar 18, 2025
0746ec4
Add in a highly nonlinear and more complicated graph.
tupek2 Mar 18, 2025
1ce7e8d
Add in a highly nonlinear and more complicated graph.
tupek2 Mar 18, 2025
2490a51
Get test tolerance in place.
tupek2 Mar 18, 2025
471dfa5
Fix style.
tupek2 Mar 18, 2025
a928494
Try to fix some gcc build issues.
tupek2 Mar 18, 2025
449b438
Fix another gcc issue.
tupek2 Mar 19, 2025
bb271cf
add all headers to cmake lists.
tupek2 Mar 19, 2025
dbe1feb
Another header missing.
tupek2 Mar 19, 2025
f5898c5
Another gcc build fix.
tupek2 Mar 19, 2025
be0ea51
Try again to fix gcc13 warnings.
tupek2 Mar 19, 2025
96fcff9
Trying to address gcc issues.
tupek2 Mar 20, 2025
37c76a7
Try to fix gcc warnings.
tupek2 Mar 20, 2025
61fd848
Try again to resolve gcc warning.
tupek2 Mar 20, 2025
44107f6
Debugging gretl.
tupek2 Jun 6, 2025
c90d23f
Trying to simplify gretl.
tupek2 Jun 6, 2025
0469141
Simplifying gretl implementation, no checkpointing yet.
tupek2 Jun 6, 2025
ba58d95
Seemingly got gretl, no checkpoint working again.
tupek2 Jun 8, 2025
02c56fd
Cleanup the initial, not dynamically checkpointed gretl.
tupek2 Jun 8, 2025
37c7340
Remove some prints, only clear shared pointer if no one else has a ha…
tupek2 Jun 8, 2025
ddee2ce
style.
tupek2 Jun 8, 2025
80d7b4d
Fix build.
tupek2 Jun 8, 2025
fce33b1
Fix style.
tupek2 Jun 8, 2025
094c1d0
Fix style.
tupek2 Jun 9, 2025
0474505
Trying to work out the dynamic checkpointing interface.
tupek2 Jun 12, 2025
5a7c418
Working toward dynamic implementation.
tupek2 Jun 12, 2025
1cb451f
Working toward gretl redesign.
tupek2 Jun 20, 2025
fa0e7cf
Get gretl tests working again with backend refactor.
tupek2 Jun 21, 2025
9e2b7a9
Cleanup some prints.
tupek2 Jun 21, 2025
feb37e1
Get test passing again.
tupek2 Jun 23, 2025
e6ce787
Nearly working dynamic checkpointing. forward pass looks to be correct.
tupek2 Jun 24, 2025
6206f9e
still seeming have forward part operating... need to figure out rever…
tupek2 Jun 24, 2025
065a335
Trying to manage the counting of the pass through states.
tupek2 Jun 24, 2025
0b72bd6
Progressing on graph dynamic checkpointing.
tupek2 Jul 1, 2025
c6078f6
Trying to be more careful tracking states and their passthroughts.
tupek2 Jul 3, 2025
457a261
Progress on checkpointing.
tupek2 Jul 7, 2025
1cc225b
Just have a single data store... we can make the Checkpointmanager vi…
tupek2 Jul 7, 2025
dda8d50
style.
tupek2 Jul 7, 2025
19a6bed
Get all checkpointing tests working again after refactor.
tupek2 Jul 7, 2025
bd16a6b
Remove some prints
tupek2 Jul 7, 2025
6458244
Fix some warnings and small cleanups.
tupek2 Jul 8, 2025
ea31d01
Get optimizations in. Need to document and figure out how to test co…
tupek2 Jul 8, 2025
40b10a6
Some more internal asserts to ensure correctness.
tupek2 Jul 8, 2025
b648971
Get other test working.
tupek2 Jul 9, 2025
0d0fb7a
Remove comments.
tupek2 Aug 4, 2025
1b7366d
Fix style.
tupek2 Aug 4, 2025
450e7b9
Working on documenting the gretl interface a bit more.
tupek2 Aug 5, 2025
3118646
Fix style and docs.
tupek2 Aug 5, 2025
13440ea
Fix last line.
tupek2 Aug 5, 2025
b620140
More ending lines.
tupek2 Aug 5, 2025
3e1423f
More docs improvements and file naming adjustments.
tupek2 Aug 5, 2025
c7a4c66
small fix.
tupek2 Aug 5, 2025
9a67661
Change upstream implementation, fix library name to serac.
tupek2 Aug 5, 2025
6cbf528
Try to fix gcc issues.
tupek2 Aug 5, 2025
d34c80b
Fix maybe nullptr.
tupek2 Aug 5, 2025
d8caccd
Try to fix maybe nullptr.
tupek2 Aug 5, 2025
fd371bf
Merge branch 'develop' into tupek/gretl_refactor
tupek2 Aug 18, 2025
5e3204d
Merge branch 'tupek/residual_interface_adjustments' into tupek/gretl_…
tupek2 Aug 18, 2025
eadb07f
Another working adjustment.
tupek2 Aug 18, 2025
40fab88
Merge branch 'develop' into tupek/gretl_refactor
tupek2 Aug 19, 2025
1f034c9
start introducing differentiable explicit dynamics.
tupek2 Aug 20, 2025
6ea2c9e
Get an explicit dynamics test working.
tupek2 Aug 21, 2025
de421d5
Fix style, put timestep estimator into its own file.
tupek2 Aug 21, 2025
36f578b
Working through documentation and simplifying interface.
tupek2 Aug 22, 2025
84de782
Some more documentations.
tupek2 Aug 22, 2025
daebe5b
Get tests working again.
tupek2 Aug 22, 2025
fd09f4d
Fix style, docs.
tupek2 Aug 22, 2025
0cf84c6
Rename datastore.
tupek2 Aug 22, 2025
027ce61
Merge branch 'develop' into tupek/gretl_field_state
tupek2 Aug 22, 2025
29f61d5
Fix up naming.
tupek2 Aug 24, 2025
59acd92
small naming adjust, more documentation.
tupek2 Aug 25, 2025
6ebe802
Try to fix cmake install.
tupek2 Aug 25, 2025
4f41b1e
Debug some more cases where the dynamic checkpointing was previously …
tupek2 Aug 27, 2025
46f7579
Standard library include.
tupek2 Aug 27, 2025
76ec37c
Fix style.
tupek2 Aug 27, 2025
d54a2a3
Fix some subtle logic with assignment operator.
tupek2 Aug 27, 2025
78bd706
Address state copy constructor.
tupek2 Aug 27, 2025
37799e9
Refactor so weak forms state a timeinfo struct.
tupek2 Aug 28, 2025
7f4fd93
Document time info.
tupek2 Aug 28, 2025
e8bd938
Working on some syntax helpers for adding and sscaling FieldStates.
tupek2 Aug 29, 2025
85006e1
Add some error messaging when objective is not set as the last step.
tupek2 Aug 30, 2025
63d7e23
Implement generic weighted sum.
tupek2 Sep 3, 2025
b2f0b31
Working toward operator overloaded helper functions.
tupek2 Sep 4, 2025
da81c14
Progress on operator overloading abstractions.
tupek2 Sep 4, 2025
d24e8d8
Support some more addition operators with the FieldStateWeightedSum.
tupek2 Sep 4, 2025
c5bd859
A few more additions.
tupek2 Sep 4, 2025
e61ce6a
Implement and test a solid first round of overloaded operators for Fi…
tupek2 Sep 5, 2025
6e29aec
Merge branch 'develop' into tupek/gretl_field_state
tupek2 Sep 5, 2025
bbd6384
Fix docs.
tupek2 Sep 5, 2025
7247f45
Style and test State double double multiply
tupek2 Sep 5, 2025
bc5ffc6
Use the type specific clone and create_state interface for some imple…
tupek2 Sep 5, 2025
da8cf67
Try to resolve constructor ambiguity for gcc.
tupek2 Sep 5, 2025
53b9915
Transition stat advancer to use DoubleState.
tupek2 Sep 5, 2025
6c76be1
Fix style, docs.
tupek2 Sep 5, 2025
3e57c1c
Cleanup a few usages of new interface.
tupek2 Sep 8, 2025
55b2bcd
Add docs.
tupek2 Sep 8, 2025
d9c697b
Improve some error messages, stricter on types for getting duals to a…
tupek2 Sep 11, 2025
df4aac2
Merge branch 'develop' into tupek/gretl_field_state
tupek2 Sep 11, 2025
70966fd
Export the new differentiable utils in the serac library.
tupek2 Sep 11, 2025
33f6146
Rename.
tupek2 Sep 11, 2025
a21f093
Fix style.
tupek2 Sep 11, 2025
859f3d4
Merge branch 'develop' into tupek/gretl_field_state
tupek2 Sep 15, 2025
6fc519a
Fix up graph reset if the graph needs to be rebuilt in the base physics.
tupek2 Sep 17, 2025
f0566d7
Fix style.
tupek2 Sep 17, 2025
b783fe7
Fix the style issues consistent with the original gretl.
tupek2 Sep 18, 2025
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
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ set(exported_targets
serac_infrastructure
serac_mesh_utils
serac_numerics
serac_physics)
serac_physics
serac_gretl
serac_differentiable_numerics)

add_library(serac INTERFACE)
target_link_libraries(serac INTERFACE ${exported_targets})
Expand Down
2 changes: 2 additions & 0 deletions src/serac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ add_subdirectory(infrastructure)
add_subdirectory(numerics)
add_subdirectory(physics)
add_subdirectory(mesh_utils)
add_subdirectory(gretl)
add_subdirectory(differentiable_numerics)
54 changes: 54 additions & 0 deletions src/serac/differentiable_numerics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright (c) Lawrence Livermore National Security, LLC and
# other Serac Project Developers. See the top-level LICENSE file for
# details.
#
# SPDX-License-Identifier: (BSD-3-Clause)

set(differentiable_numerics_sources
state_advancer.cpp
field_state.cpp
mechanics.cpp
)

set(differentiable_numerics_headers
field_state.hpp
state_advancer.hpp
timestep_estimator.hpp
mechanics.hpp
explicit_dynamic_solve.hpp
lumped_mass_weak_form.hpp
differentiable_utils.hpp
)

set(differentiable_numerics_depends
serac_state
serac_boundary_conditions
serac_contact
serac_numerics
serac_physics
serac_gretl
)

blt_add_library(
NAME serac_differentiable_numerics
SOURCES ${differentiable_numerics_sources}
HEADERS ${differentiable_numerics_headers}
DEPENDS_ON ${differentiable_numerics_depends}
)

serac_write_unified_header(
NAME differentiable_numerics
HEADERS ${differentiable_numerics_headers}
)

install(FILES ${differentiable_numerics_headers} DESTINATION include/serac/differentiable_numerics )

install(TARGETS serac_differentiable_numerics
EXPORT serac-targets
DESTINATION lib
)

if(SERAC_ENABLE_TESTS)
add_subdirectory(tests)
endif()

195 changes: 195 additions & 0 deletions src/serac/differentiable_numerics/differentiable_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
// Copyright (c) Lawrence Livermore National Security, LLC and
// other Serac Project Developers. See the top-level LICENSE file for
// details.
//
// SPDX-License-Identifier: (BSD-3-Clause)

/**
* @file differentiable_utils.hpp
*
* @brief Utility functions for testing.
*/

#pragma once

#include "serac/gretl/double_state.hpp"
#include "serac/differentiable_numerics/field_state.hpp"

namespace serac {

/// @brief Utility function to construct a serac::functional which evaluates the total kinetic energy
template <typename DispSpace, typename DensitySpace>
auto create_kinetic_energy_integrator(serac::Domain& domain, const mfem::ParFiniteElementSpace& velocity_space,
const mfem::ParFiniteElementSpace& density_space)
{
static constexpr int dim = DispSpace::components;
auto ke_integrator = std::make_shared<serac::Functional<double(DispSpace, DispSpace, DensitySpace)>>(
std::array<const mfem::ParFiniteElementSpace*, 3>{&velocity_space, &velocity_space, &density_space});
ke_integrator->AddDomainIntegral(
Dimension<dim>{}, DependsOn<0, 1, 2>{},
[&](auto /*t*/, auto /*X*/, auto U, auto V, auto Rho) {
auto rho = get<VALUE>(Rho);
auto v = get<VALUE>(V);
auto ke = 0.5 * rho * inner(v, v);
auto dx_dX = get<DERIVATIVE>(U) + Identity<dim>();
auto J = det(dx_dX);
return ke * J;
},
domain);
return ke_integrator;
}

/// @brief Utility function which computes the kinetic energy and returns it as a gretl state (with its vjp defined)
template <typename DispSpace, typename DensitySpace>
gretl::State<double> compute_kinetic_energy(
const std::shared_ptr<serac::Functional<double(DispSpace, DispSpace, DensitySpace)>>& energy_func,
serac::FieldState disp, serac::FieldState velo, serac::FieldState density, double scaling)
{
return gretl::create_state<double, double>(
// specify how to zero the dual
[](double forwardVal) { return 0 * forwardVal; },
// define how to (re)evaluate the output
[=](const serac::FEFieldPtr& Disp, const serac::FEFieldPtr& Velo, const serac::FEFieldPtr& Density) -> double {
return (*energy_func)(0.0, *Disp, *Velo, *Density) * scaling;
},
// define how to backpropagate the vjp
[=](const serac::FEFieldPtr& Disp, const serac::FEFieldPtr& Velo, const serac::FEFieldPtr& Density,
const double& /*ke*/, serac::FEDualPtr& Disp_dual, serac::FEDualPtr& Velo_dual,
serac::FEDualPtr& Density_dual, const double& ke_dual) -> void {
auto ddisp = (*energy_func)(0.0, serac::differentiate_wrt(*Disp), *Velo, *Density);
auto de_ddisp = assemble(serac::get<serac::DERIVATIVE>(ddisp));

auto dvelo = (*energy_func)(0.0, *Disp, serac::differentiate_wrt(*Velo), *Density);
auto de_dvelo = assemble(serac::get<serac::DERIVATIVE>(dvelo));

auto ddens = (*energy_func)(0.0, *Disp, *Velo, serac::differentiate_wrt(*Density));
auto de_ddensity = assemble(serac::get<serac::DERIVATIVE>(ddens));

Disp_dual->Add(scaling * ke_dual, *de_ddisp);
Velo_dual->Add(scaling * ke_dual, *de_dvelo);
Density_dual->Add(scaling * ke_dual, *de_ddensity);
},
// give the input values
disp, velo, density);
}

/// testing utility to confirm order of convergence of the finite differences relative to the backprop gradient
inline auto check_gradients(const gretl::State<double>& objectiveState, FieldState& inputState,
FiniteElementDual& inputDual, double objectiveBase, gretl::DataStore& dataStore, double eps)
{
serac::FiniteElementState inputSave(*inputState.get());
dataStore.reset();
serac::FiniteElementState& input = *inputState.get();
serac::FiniteElementState pert(input.space(), input.name() + "_pert");

int sz = pert.Size();
for (int i = 0; i < sz; ++i) {
pert[i] = -1.2 + 2.02 * (double(i) / sz);
input[i] += eps * pert[i];
}

double objectivePlus = objectiveState.get();

double directionDeriv = 0.0;
for (int i = 0; i < sz; ++i) {
directionDeriv += pert[i] * inputDual[i];
}

*inputState.get() = inputSave;

return std::make_pair(directionDeriv, (objectivePlus - objectiveBase) / eps);
}

/// testing utility to confirm order of convergence of the finite differences relative to the backprop gradient
inline auto check_gradients(const gretl::State<double>& objectiveState, gretl::State<double, double>& inputState,
double& inputDual, double objectiveBase, gretl::DataStore& dataStore, double eps)
{
double inputSave = inputState.get();
dataStore.reset();
inputState.set(inputSave + eps);
double objectivePlus = objectiveState.get();
inputState.set(inputSave);
return std::make_pair(inputDual, (objectivePlus - objectiveBase) / eps);
}

/// @brief Testing utility function which runs a gretl graph num_fd_steps (with increasingly smaller finite difference
/// steps) to check if the computed graph gradients are converging to the finite differenced gradients at the expected
/// rate
inline double check_grad_wrt(const gretl::State<double>& objective, serac::FieldState& input, gretl::DataStore& graph,
double eps, size_t num_fd_steps = 4, bool printmore = false)
{
// reset each time, just to be sure
graph.reset();

// re-evaluate the final objective value
double objectiveBase = objective.get();

// back-propagate to get sensitivity wrt input states
gretl::set_as_objective(objective);
graph.back_prop();

auto dual_vec = *input.get_dual();

std::vector<double> grad_errors;
auto [grad, grad_fd] = check_gradients(objective, input, dual_vec, objectiveBase, graph, eps);
grad_errors.push_back(std::abs(grad - grad_fd));

for (size_t step = 1; step < num_fd_steps; ++step) {
eps /= 2;
std::tie(grad, grad_fd) = check_gradients(objective, input, dual_vec, objectiveBase, graph, eps);
if (printmore) std::cout << "grad = " << grad << "\ngrad fd = " << grad_fd << std::endl;
grad_errors.push_back(std::abs(grad - grad_fd));
}

for (size_t step = 0; step < num_fd_steps; ++step) {
std::cout << "grad error " << step << " = " << grad_errors[step] << std::endl;
}

if (num_fd_steps >= 2) {
return std::log2(grad_errors[0] / grad_errors[num_fd_steps - 1]) / static_cast<double>(num_fd_steps - 1);
}

return 0;
};

/// @brief Testing utility function which runs a gretl graph num_fd_steps (with increasingly smaller finite difference
/// steps) to check if the computed graph gradients are converging to the finite differenced gradients at the expected
/// rate
inline double check_grad_wrt(const gretl::State<double>& objective, gretl::State<double, double>& input,
gretl::DataStore& graph, double eps, size_t num_fd_steps = 4, bool printmore = false)
{
// reset each time, just to be sure
graph.reset();

// re-evaluate the final objective value
double objectiveBase = objective.get();

// back-propagate to get sensitivity wrt input states
gretl::set_as_objective(objective);
graph.back_prop();

auto dual = input.get_dual();

std::vector<double> grad_errors;
auto [grad, grad_fd] = check_gradients(objective, input, dual, objectiveBase, graph, eps);
grad_errors.push_back(std::abs(grad - grad_fd));

for (size_t step = 1; step < num_fd_steps; ++step) {
eps /= 2;
std::tie(grad, grad_fd) = check_gradients(objective, input, dual, objectiveBase, graph, eps);
if (printmore) std::cout << "grad = " << grad << "\ngrad fd = " << grad_fd << std::endl;
grad_errors.push_back(std::abs(grad - grad_fd));
}

for (size_t step = 0; step < num_fd_steps; ++step) {
std::cout << "grad error " << step << " = " << grad_errors[step] << std::endl;
}

if (num_fd_steps >= 2) {
return std::log2(grad_errors[0] / grad_errors[num_fd_steps - 1]) / static_cast<double>(num_fd_steps - 1);
}

return 0;
};

} // namespace serac
Loading