# Sensitivity of an SDE with non-diagonal noise

**URL:** <https://discourse.julialang.org/t/sensitivity-of-an-sde-with-non-diagonal-noise/127714>\
**Category:** Modelling & Simulations\
**Tags:** sde, forwarddiff, differentialequation\
**Created:** [April 4, 2025, 4:07pm UTC](https://discourse.julialang.org/t/sensitivity-of-an-sde-with-non-diagonal-noise/127714 "2025-04-04T16:07:17Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![stochasticguy](https://avatars.discourse-cdn.com/v4/letter/s/278dde/32.png) [@stochasticguy](https://discourse.julialang.org/u/stochasticguy)\
**Post date:** [April 4, 2025, 4:07pm UTC](https://discourse.julialang.org/t/sensitivity-of-an-sde-with-non-diagonal-noise/127714/1 "2025-04-04T16:07:17Z")

</div>

Hi everyone,

I’m simulating an SDE with non-diagonal noise and I’m trying to compute the gradient (using ForwardDiff) of a loss function that uses the SDE solution. When I try to compute the gradient the following error happens:

```julia
    nested task error: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(loss_function), Float64}, Float64, 6})
    The type `Float64` exists, but no method is defined for this combination of argument types when trying to construct it.
    
    Closest candidates are:
      (::Type{T})(::Real, ::RoundingMode) where T<:AbstractFloat
       @ Base rounding.jl:265
      (::Type{T})(::T) where T<:Number
       @ Core boot.jl:900
      Float64(::IrrationalConstants.Quartπ)
       @ IrrationalConstants ~/.julia/packages/IrrationalConstants/lWTip/src/macro.jl:131

   Stacktrace:
      [1] convert(::Type{Float64}, x::ForwardDiff.Dual{ForwardDiff.Tag{typeof(loss_function), Float64}, Float64, 6})
        @ Base ./number.jl:7
      [2] setindex!
        @ ./array.jl:994 [inlined]
      [3] diffusion!(du::Matrix{Float64}, u::Vector{ForwardDiff.Dual{…}}, p::Vector{ForwardDiff.Dual{…}}, t::Float64)

```

Which indicates that there’s an error when trying to convert the diffusion du.

The code I’m using is as follows:

```julia

using DifferentialEquations, SciMLSensitivity, ForwardDiff

# Define drift function
function drift!(du, u, p, t)
    du[1] = p[1] * u[1]
    du[2] = p[2] * u[2]
end

# Define diffusion function with non-diagonal noise
function diffusion!(du, u, p, t)
    du[1, 1] = p[3] * u[1]
    du[1, 2] = p[4] * u[2]
    du[2, 1] = p[5] * u[1]
    du[2, 2] = p[6] * u[2]
end

# Initial conditions and parameters
u0 = [1.0, 1.0]
p = [0.5, -0.3, 0.1, 0.2, 0.3, 0.1]
tspan = (0.0, 1.0)

noise_prototype = zeros(eltype(p), 2, 2)

# Define SDE problem
sde_prob = SDEProblem(drift!, diffusion!, u0, tspan, p, noise_rate_prototype=noise_prototype)

# Define the number of ensemble realizations
num_trajectories = 100

# Function to compute loss for a given parameter set
function loss_function(p)
    prob = remake(sde_prob, p=p)
    
    # Solve ensemble of SDEs
    ensemble_prob = EnsembleProblem(prob)
    ensemble_sol = solve(ensemble_prob, SRA1(), EnsembleThreads(), trajectories=num_trajectories, saveat=0.1)

    return sum(sum(sol[1, :] for sol in ensemble_sol.u))
end

# Compute gradients using ForwardDiff
grad = ForwardDiff.gradient(loss_function, p)
println("Gradients: ", grad)

```

Any ideas on how to solve this issue?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 4, 2025, 7:25pm UTC](https://discourse.julialang.org/t/sensitivity-of-an-sde-with-non-diagonal-noise/127714/2 "2025-04-04T19:25:46Z")

</div>

> [@stochasticguy](#):
>
> `noise_prototype = zeros(eltype(p), 2, 2)`

Your noise rate prototype matrix isn’t converted. We should do that automatically in the library, but until we do this should work:

```julia
function loss_function(p)
    noise_prototype = zeros(eltype(p), 2, 2)
    sde_prob = SDEProblem(drift!, diffusion!, u0, tspan, p, noise_rate_prototype=noise_prototype)
    
    # Solve ensemble of SDEs
    ensemble_prob = EnsembleProblem(prob)
    ensemble_sol = solve(ensemble_prob, SRA1(), EnsembleThreads(), trajectories=num_trajectories, saveat=0.1)

    return sum(sum(sol[1, :] for sol in ensemble_sol.u))
end

```

---

<div class="post-metadata">

**Author:** ![stochasticguy](https://avatars.discourse-cdn.com/v4/letter/s/278dde/32.png) [@stochasticguy](https://discourse.julialang.org/u/stochasticguy)\
**Post date:** [April 4, 2025, 9:17pm UTC](https://discourse.julialang.org/t/sensitivity-of-an-sde-with-non-diagonal-noise/127714/3 "2025-04-04T21:17:10Z")

</div>

Amazing, thank you very much, Chris!
