|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +""" |
| 3 | +""" |
| 4 | + |
| 5 | +from numpy import zeros |
| 6 | + |
| 7 | +from ..float_handling import float_type |
| 8 | +from ..solve.solution import ode_system |
| 9 | +from ..utils import get_solutions |
| 10 | +from .utils import analysis_func_wrapper |
| 11 | + |
| 12 | + |
| 13 | +def compute_jacobian( |
| 14 | + *, γ, a_0, norm_kepler_sq, init_con, θ_scale, η_derivs, use_E_r, θ, params, |
| 15 | + eps, |
| 16 | +): |
| 17 | + rhs_eq, _ = ode_system( |
| 18 | + γ=γ, a_0=a_0, norm_kepler_sq=norm_kepler_sq, init_con=init_con, |
| 19 | + θ_scale=θ_scale, with_taylor=False, η_derivs=η_derivs, |
| 20 | + store_internal=False, use_E_r=use_E_r, v_θ_sonic_crit=None, |
| 21 | + after_sonic=None, deriv_v_θ_func=None, check_params=False |
| 22 | + ) |
| 23 | + |
| 24 | + solution_length = params.shape[0] |
| 25 | + ode_size = params.shape[1] |
| 26 | + |
| 27 | + J = zeros([solution_length, ode_size, ode_size], dtype=float_type) |
| 28 | + |
| 29 | + # compute column for each param |
| 30 | + for i in range(ode_size): |
| 31 | + derivs_h = zeros([solution_length, ode_size], dtype=float_type) |
| 32 | + derivs_l = zeros([solution_length, ode_size], dtype=float_type) |
| 33 | + params_h = params.copy() |
| 34 | + params_l = params.copy() |
| 35 | + |
| 36 | + # offset only the value associated with this column |
| 37 | + params_h[:, i] += eps |
| 38 | + params_l[:, i] -= eps |
| 39 | + |
| 40 | + # we don't check the validity of inputs as we have these from the |
| 41 | + # solution |
| 42 | + rhs_eq(θ, params_h, derivs_h) |
| 43 | + rhs_eq(θ, params_l, derivs_l) |
| 44 | + |
| 45 | + J[:, :, i] = (derivs_h - derivs_l) / (2 * eps) |
| 46 | + return J |
| 47 | + |
| 48 | + |
| 49 | +def compute_jacobian_from_solution(soln, *, eps, θ_scale=float_type(1)): |
| 50 | + solution = soln.solution |
| 51 | + angles = soln.angles |
| 52 | + cons = soln.initial_conditions |
| 53 | + soln_input = soln.solution_input |
| 54 | + |
| 55 | + init_con = cons.init_con |
| 56 | + γ = cons.γ |
| 57 | + a_0 = cons.a_0 |
| 58 | + norm_kepler_sq = cons.norm_kepler_sq |
| 59 | + |
| 60 | + η_derivs = soln_input.η_derivs |
| 61 | + use_E_r = soln_input.use_E_r |
| 62 | + |
| 63 | + return compute_jacobian( |
| 64 | + γ=γ, a_0=a_0, norm_kepler_sq=norm_kepler_sq, init_con=init_con, |
| 65 | + θ_scale=θ_scale, η_derivs=η_derivs, use_E_r=use_E_r, θ=angles, |
| 66 | + params=solution, eps=eps, |
| 67 | + ) |
| 68 | + |
| 69 | + |
| 70 | +@analysis_func_wrapper |
| 71 | +def compute_jacobian_from_file( |
| 72 | + soln_file, *, soln_range=None, eps, θ_scale=float_type(1), **kwargs |
| 73 | +): |
| 74 | + |
| 75 | + soln = get_solutions(soln_file, soln_range) |
| 76 | + return compute_jacobian_from_solution(soln, eps=eps, θ_scale=θ_scale) |
0 commit comments