From af088226c7c04852c5aff5c2a05419034038ba22 Mon Sep 17 00:00:00 2001 From: Kenneth Lyons Date: Wed, 5 Aug 2026 11:21:06 -0700 Subject: [PATCH 1/2] Defer state jac construction until needed by TrajectoryAnalysisSGM --- src/condor/implementations/sgm_trajectory.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/condor/implementations/sgm_trajectory.py b/src/condor/implementations/sgm_trajectory.py index f0913e65..67a16d5f 100644 --- a/src/condor/implementations/sgm_trajectory.py +++ b/src/condor/implementations/sgm_trajectory.py @@ -134,13 +134,6 @@ def construct( model.dot, self.simulation_signature, subs=control_sub_expression ) - self.state_jacobian_expr = jacobian(state_equation_func.expr, self.x) - self.state_dot_jac_func = expression_to_operator( - self.simulation_signature, - self.state_jacobian_expr, - f"{ode_model.__name__}_state_jacobian", - ) - self.e_exprs = [] self.h_exprs = [] @@ -307,7 +300,7 @@ class Terminate(ode_model.Event): dim_state=model.state._count, initial_state=self.state0, dot=state_equation_func, - jac=self.state_dot_jac_func, + jac=None, time_generator=sgm.TimeGeneratorFromSlices(at_time_slices), events=expression_to_operator( self.simulation_signature, @@ -344,6 +337,13 @@ def generate_sgm_jacobian(self, jacobian_of): model = self.model control_sub_expression = self.control_sub_expression + state_jacobian_expr = jacobian(state_equation_func.expr, self.x) + state_dot_jac_func = expression_to_operator( + self.simulation_signature, + state_jacobian_expr, + f"{self.ode_model.__name__}_state_jacobian", + ) + state_param_jac = jacobian(state_equation_func.expr, self.p) param_dot_jac_func = expression_to_operator( @@ -524,7 +524,7 @@ def generate_sgm_jacobian(self, jacobian_of): trajectory_analysis=self.trajectory_analysis_nom, dte_dxs=self.dte_dxs, dh_dxs=self.dh_dxs, - state_jac=self.state_dot_jac_func, + state_jac=state_dot_jac_func, p_x0_p_params=p_state0_p_p, p_dots_p_params=param_dot_jac_func, dh_dps=self.dh_dps, From 170f9ee9bbdd9bd8f8b8f2087b1d2afcb525d036 Mon Sep 17 00:00:00 2001 From: Kenneth Lyons Date: Wed, 5 Aug 2026 11:33:05 -0700 Subject: [PATCH 2/2] Make state jac func a cached property in case needed for CVODE --- src/condor/implementations/sgm_trajectory.py | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/condor/implementations/sgm_trajectory.py b/src/condor/implementations/sgm_trajectory.py index 67a16d5f..7797db0a 100644 --- a/src/condor/implementations/sgm_trajectory.py +++ b/src/condor/implementations/sgm_trajectory.py @@ -1,4 +1,5 @@ from enum import Enum +from functools import cached_property import numpy as np @@ -300,7 +301,7 @@ class Terminate(ode_model.Event): dim_state=model.state._count, initial_state=self.state0, dot=state_equation_func, - jac=None, + jac=None if solver is not self.Solver.CVODE else self.state_jac_func, time_generator=sgm.TimeGeneratorFromSlices(at_time_slices), events=expression_to_operator( self.simulation_signature, @@ -331,18 +332,21 @@ class Terminate(ode_model.Event): jacobian_of=None, ) - def generate_sgm_jacobian(self, jacobian_of): - state_equation_func = self.state_equation_func - # lamda_jac = self.state_jacobian_expr.T - model = self.model - control_sub_expression = self.control_sub_expression - - state_jacobian_expr = jacobian(state_equation_func.expr, self.x) + @cached_property + def state_jac_func(self): + state_jacobian_expr = jacobian(self.state_equation_func.expr, self.x) state_dot_jac_func = expression_to_operator( self.simulation_signature, state_jacobian_expr, f"{self.ode_model.__name__}_state_jacobian", ) + return state_dot_jac_func + + def generate_sgm_jacobian(self, jacobian_of): + state_equation_func = self.state_equation_func + # lamda_jac = self.state_jacobian_expr.T + model = self.model + control_sub_expression = self.control_sub_expression state_param_jac = jacobian(state_equation_func.expr, self.p) @@ -524,7 +528,7 @@ def generate_sgm_jacobian(self, jacobian_of): trajectory_analysis=self.trajectory_analysis_nom, dte_dxs=self.dte_dxs, dh_dxs=self.dh_dxs, - state_jac=state_dot_jac_func, + state_jac=self.state_jac_func, p_x0_p_params=p_state0_p_p, p_dots_p_params=param_dot_jac_func, dh_dps=self.dh_dps,