# Access node in custom\_recorders during historical simulation (SDDP.jl)

**URL:** <https://discourse.julialang.org/t/access-node-in-custom-recorders-during-historical-simulation-sddp-jl/128507>\
**Category:** Optimization (Mathematical)\
**Tags:** sddp\
**Created:** [April 29, 2025, 12:18am UTC](https://discourse.julialang.org/t/access-node-in-custom-recorders-during-historical-simulation-sddp-jl/128507 "2025-04-29T00:18:36Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sorooshsa](https://avatars.discourse-cdn.com/v4/letter/s/977dab/32.png) [@Sorooshsa](https://discourse.julialang.org/u/Sorooshsa)\
**Post date:** [April 29, 2025, 12:18am UTC](https://discourse.julialang.org/t/access-node-in-custom-recorders-during-historical-simulation-sddp-jl/128507/1 "2025-04-29T00:18:36Z")

</div>

Hey,

I am calculating the dual values of some constraints during historical simulation, and the constraint index depends on the `node` in the body of the problem. Therefore, in the simulation part, I need to refer to the `node`:

```julia
simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> Dict(
            i => JuMP.dual(sp[:cons1][i]) for i in block_function(node)
        )
    ),
    skip_undefined_variables = true
)

```

Here, `Sim` is my historical data and `block_function` is a function that takes `node` as input and returns the correct range for the constraint indices.

**My question is:** How can I access `node` inside the custom recorder function?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [April 29, 2025, 12:40am UTC](https://discourse.julialang.org/t/access-node-in-custom-recorders-during-historical-simulation-sddp-jl/128507/2 "2025-04-29T00:40:14Z")

</div>

You have a couple of options.

First, you probably don’t need the node. Use broadcasting and things will probably work:

```Julia
simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> JuMP.dual.(sp[:cons1]),
    ),
    skip_undefined_variables = true
)

```

Second, you could store a new `:node` key in the subproblem

```julia
SDDP.LinearPolicyGraph() do sp, node
    sp[:node] = t
end

simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> Dict(
            i => JuMP.dual(sp[:cons1][i]) for i in block_function(sp[:node])
        )
    ),
    skip_undefined_variables = true
)

```
