@@ -1101,37 +1101,50 @@ J_b_val = J_b(storage, trajectories, tlist; g_b)
11011101returns
11021102
11031103```math
1104- J_b = ∑_k ∑_n g_b(|Ψ_k(t_n)⟩) Δt_n
1104+ J_b = ∑_k ∑_{n=0}^{N_T}{}^′ g_b(|Ψ_k(t_n)⟩) Δt_n
11051105```
11061106
1107- as the piecewise-constant discretization of
1107+ as the [trapezoid discretization](https://en.wikipedia.org/wiki/Trapezoidal_rule)
1108+ of the integral
11081109
11091110```math
1110- J_b = ∑_k \\ int g_b(|Ψ_k(t)⟩) dt
1111+ J_b = ∑_k ∫_0^T g_b(|Ψ_k(t)⟩) dt ,
11111112```
11121113
11131114where `storage[k]` contains the forward-propagated states for trajectory `k`
1114- at each point of `tlist`; for example, the `fw_storage` component of the
1115- [GRAPE workspace](@extref `GRAPE.GrapeWrk`). The ``Δt_n`` is the
1116- [time step around the time grid point ``t_n``](@extref GRAPE Overview-Running-Costs).
1115+ at each time grid point in `tlist`, ``t_0 = 0, t_1, … t_{N_T} = T``;
1116+ for example, the `fw_storage` component of the
1117+ [GRAPE workspace](@extref `GRAPE.GrapeWrk`). The ``Δt_n`` are defined at
1118+ the endpoints as ``Δt_0 = t_1 - t_0`` and ``Δt_{N_T} = (t_{N_T} - t_{N_T-1})``,
1119+ and at the interior points as ``Δt_n = \\ frac{(t_{n+1} - t_{n-1})}{2}``.
1120+ For uniform time grids, ``Δt_n ≡ dt``. The prime in the sum over ``n``
1121+ indicates that the terms at the endpoints ``n=0`` and ``n=N_T`` are halved.
11171122
11181123Note that `g_b` is a mandatory keyword argument and must be a function
1119- `g_b(Ψ, trajectory, tlist, n) -> Float64`.
1124+ `g_b(Ψ, trajectory, tlist, n) -> Float64` where `Ψ` is the state ``|Ψ(t)⟩``
1125+ at ``t`` corresponding to the the (one-based) time grid point `tlist[n]`, and
1126+ `trajectory` is a [`QuantumControl.Trajectory`](@ref) that may hold additional
1127+ data in a custom property that is relevant to the calculation of ``g_b``.
1128+
1129+ The definition of `J_b` here is compatible with the
1130+ [treatment of running costs in GRAPE](@extref GRAPE Overview-Running-Costs).
11201131"""
11211132function J_b (storage, trajectories, tlist; g_b)
11221133 N = length (trajectories)
11231134 result = 0.0
11241135 for k = 1 : N
11251136 Ψ₁ = get_from_storage (storage[k], 1 )
1126- result += g_b (Ψ₁, trajectories[k], tlist, 1 ) * (tlist[2 ] - tlist[1 ])
1137+ dt = tlist[2 ] - tlist[1 ]
1138+ result += g_b (Ψ₁, trajectories[k], tlist, 1 ) * (dt/ 2 )
11271139 for n_tl = 2 : length (tlist)
11281140 Ψₙ = get_from_storage (storage[k], n_tl)
11291141 if n_tl < length (tlist)
11301142 dt = 0.5 * (tlist[n_tl+ 1 ] - tlist[n_tl- 1 ])
1143+ result += g_b (Ψₙ, trajectories[k], tlist, n_tl) * dt
11311144 else
11321145 dt = tlist[end ] - tlist[end - 1 ]
1146+ result += g_b (Ψₙ, trajectories[k], tlist, n_tl) * (dt/ 2 )
11331147 end
1134- result += g_b (Ψₙ, trajectories[k], tlist, n_tl) * dt
11351148 end
11361149 end
11371150 return result
0 commit comments