Hi William,
I gave your first suggestion a shot and compiled OpenSim's dependencies using LTO (e.g., added "-flto" to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS and replaced my linker with lld). I ran the following example:
#include <cstdio>
#include <OpenSim/Common/PolynomialFunction.h>
#include <OpenSim/Actuators/DeGrooteFregly2016Muscle.h>
#include <OpenSim/Common/Sine.h>
using namespace OpenSim;
extern int enzyme_dup;
extern int enzyme_dupnoneed;
extern int enzyme_out;
extern int enzyme_const;
template < typename return_type, typename ... T >
return_type __enzyme_fwddiff(void*, T ... );
template < typename return_type, typename ... T >
return_type __enzyme_autodiff(void*, T ... );
template < typename T, typename ... arg_types >
auto wrapperMuscle(T obj, arg_types && ... args) {
return obj.calcTendonForceMultiplier(args ... );
}
void testDeGrooteFreglyMuscle() {
DeGrooteFregly2016Muscle muscle;
muscle.finalizeFromProperties();
SimTK::Real y = 1.1;
SimTK::Real dy = 1.0;
SimTK::Real f = muscle.calcTendonForceMultiplier(y);
SimTK::Real dfdy = muscle.calcTendonForceMultiplierDerivative(y);
printf("Muscle analytic derivative\n");
printf("f(y) = %f, f'(y) = %f\n\n", f, dfdy);
dfdy = __enzyme_fwddiff<SimTK::Real>(
(void*)wrapperMuscle<DeGrooteFregly2016Muscle, SimTK::Real>,
enzyme_const, muscle,
enzyme_dup, &y, &dy);
printf("Muscle derivative w/ Enzyme\n");
printf("f(y) = %f, f'(y) = %f\n\n", wrapperMuscle(muscle, y), dfdy);
}
int main() {
testDeGrooteFreglyMuscle();
return 0;
}
However, I run into the following linker error:
[build] [100%] Linking CXX executable ../../../sandboxEnzyme
[build] ld.lld: error: OpenSim/Common/PropertyTable.h:105:40: in function preprocess__Z13wrapperMuscleIN7OpenSim24DeGrooteFregly2016MuscleEJdEEDaT_DpOT0_ double (ptr, ptr): Enzyme: No forward mode derivative found for _ZNK7OpenSim13PropertyTable26getAbstractPropertyByIndexEi
[build] at context: %6 = tail call noundef nonnull align 8 dereferenceable(84) ptr @_ZNK7OpenSim13PropertyTable26getAbstractPropertyByIndexEi(ptr noundef nonnull align 8 dereferenceable(80) %4, i32 noundef %5) #39, !dbg !26244
[build]
This example requires derefencing a custom smart pointer implemented by the dependency Simbody, which I believe explains the "ptr noundef nonnull align 8 dereferenceable(80)" message. (The pointer is used to store "property" values in OpenSim, which are serializable static parameters in OpenSim models, via the "AbstractProperty" class.)
I'm planning to join the ODM tomorrow to discuss the options you suggested above, but figured I'd post my progress here beforehand.
Best,