Saving update state output

Hi I am using below function to compare a scalar value and then use update state to update the inputs of function and get the updated value.

function  new_EnergyState(ψPlusPrev_in,ψhPos_in)
    ψPlus_in = ψhPos_in
    if ψPlus_in  >=ψPlusPrev_in
        ψPlus_out =ψPlus_in
    else
        ψPlus_out=ψPlusPrev_in
    end
    true,ψPlus_out
end
update_state!( new_EnergyState ,ψPlusPrev ,ψhPos_in)

I want to store the output value of update but i cant do this as the return function of new energy state is true and value. i cant delete true because it seems that update state work with that. could you please tell me how can i save the energy state?
thank you

It would help a lot if you could provide a complete example, i.e. something minimal that runs.

As @Joris_Pinkse said, a bit more information would be helpful.

Are you trying to do something like this?

function calculate_something(a, b)
    # Need to return a Bool and the result of the calculation
    return true, a + b
end

# This is defined somewhere else
function update_something!(f, a, b)
    flag, value = f(a, b)
    # Do some more stuff here
    return nothing # Cannot change the return of the update function
end

for i in 1:100
    update_something!(calculate_something, rand(), rand())
end

# Now, how to access the values of `calculate_something` ?

If you can’t change the update function, then you could use a variable that holds the results and gets updated like this:

function calculate_something_and_record_value(a, b, record)
    value = a + b
    push!(record, value)
    return true, value
end

function run_updates_and_save_results()
    # A vector to hold the results
    # If we know the length and/or element type, we should specify it as well.
    record = []

    # We need to match the argument signature expected by the update function,
    # so we wrap the recording function in a "closure"
    f(a, b) = calculate_something_and_record_value(a, b, record)

    for i in 1:100
        update_something!(f, rand(), rand())
    end

    return record
end

run_updates_and_save_results()
100-element Vector{Any}:
 0.9326293845337489
 1.0874839459729055
 1.0082781204954732
 0.5836277969172434
 1.4024936915908803
 0.6865361279464467
 0.9671876419825283
 0.6145749447883307
 0.49464888052707834
 ⋮
 0.12298307120303653
 0.2654180772308613
 1.3610828094748888
 0.5013004061965702
 1.104067998491948
 1.4623574406108641
 0.9781138176451926
 0.9795816463302204
 1.3227497030387108
1 Like

thank you for your kind explanation. unfortunately the code is not minimal to share sth that run and honestly i dont know how to make it simple to run.@Joris_Pinkse.
it is mostly like the code that you provided at first however updatestate! is a defined function in julia gridap and i didnt define it by myself anywhere. i want to save the output of update_state.

1 Like

I did like you said but it seems that it just save the record in some steps i have provided more detailed code below

function  new_EnergyState(ψPlusPrev_in,ψhPos_in, el)
    ψPlus_in = ψhPos_in
    if ψPlus_in  >=ψPlusPrev_in
        ψPlus_out =ψPlus_in
        push!(el, ψPlus_out)
    else
        ψPlus_out=ψPlusPrev_in
        push!(el, ψPlus_out)
    end
    true,ψPlus_out
end
function   stepPhaseField(fem_params, uh_in,ΨPlusPrev_in)
    A_PF(s,φ,uh_in,ΨPlusPrev_in) =Gc*ls*∇(φ)⋅∇(s) + (2*ΨPlusPrev_in*s*φ) + (Gc/ls)*s*φ
    a_PF(s,φ) = ∫(A_PF(s,φ,uh_in,ΨPlusPrev_in))fem_params.dΩ
    b_PF(φ) =∫((Gc/ls)*φ)fem_params.dΩ
    op_PF = AffineFEOperator(a_PF,b_PF ,U_PF ,V0_PF)
    sh_out = solve(op_PF)
#     return  sh_out
    return  get_free_dof_values(sh_out)

end
using Gridap.CellData
function  stepDisp(fem_params,pth, uh_in,sh_in, vApp)
    uApp1(x) = VectorValue(0.0,0.0)
    uApp2(x) = VectorValue(0.0,0.0)
    uApp3(x) = VectorValue(0.0,-vApp)
    U_Disp = TrialFESpace(V0_Disp ,[uApp1 ,uApp2 ,uApp3])
    A_Disp(u,v,pth,uh_in,sh_in) =  ((p->Em(p))∘pth) * (ε(v) ⊙ (σfun∘(ε(u), ε(uh_in), sh_in)))
    a_Disp(u,v) =∫(A_Disp(u,v,pth,uh_in,sh_in))fem_params.dΩ
    b_Disp(v) = 0.0
    op_Disp = AffineFEOperator(a_Disp ,b_Disp ,U_Disp ,fem_params.V0_Disp)
    uh_out = solve(op_Disp)
#     return  uh_out
    return  get_free_dof_values(uh_out)

end
innerMax = 10
count = 0
vApp = 0
ψPlusPrev = CellState(0.0,dΩ)
p0 = ones(fem_params.np)
pf_vec = Filter(p0;r, fem_params)
pfh = FEFunction(fem_params.Pf, pf_vec)
pth = (pf -> Threshold(pf; β, η)) ∘ pfh
sPrev = CellState(1.0,dΩ)
sh = project(sPrev, model ,dΩ,order)


sl = zeros(sr,co)
ul = zeros(ur,co)
vl = zeros(co)
el=[]
push!(el, ψPlusPrev)
while vApp .< vAppMax
    count = count .+ 1
    if vApp >= vAppmid
        delv = delvmid
    end
    vApp = vApp .+ delv
    print("\n step", float(vApp))
   for  inner = 1: innerMax
        ψhPlusPrev = project(ψPlusPrev ,model ,dΩ,order)
        RelErr = abs(sum(∫(Gc*ls*∇(sh)⋅∇(sh) + 2*ψhPlusPrev*sh*sh + (Gc/ls)*sh*sh)fem_params.dΩ-∫( (Gc/ls)*sh)fem_params.dΩ))/abs(sum(∫( (Gc/ls)*sh)fem_params.dΩ))
        sh_vec = stepPhaseField(fem_params,uh,ψhPlusPrev)
        sh = FEFunction(fem_params.U_PF, sh_vec)
        u_vec = stepDisp(fem_params,pth, uh, sh, vApp)
        uAppp1(x) = VectorValue(0.0,0.0)
        uAppp2(x) = VectorValue(0.0,0.0)
        uAppp3(x) = VectorValue(0.0,-vApp)
        U_Disp = TrialFESpace(V0_Disp ,[uAppp1 ,uAppp2 ,uAppp3])
        uh = FEFunction(U_Disp, u_vec)
        ψhPos_in = ψPos∘(ε(uh))
        update_state!( new_EnergyState ,ψPlusPrev ,ψhPos_in)
        if   RelErr  < 1e-8
            sl[:,count] = sh_vec
            ul[:,count] = u_vec
            vl[count] = vApp
            println("Energy", el)
            break
        end
   end
end
writevtk(Ω,"resultstph",cellfields=["uh"=>uh, "sh"=>sh])

and the output is like below


 step0.001EnergyAny[CellState()]

 step0.002EnergyAny[CellState()]

 step0.003EnergyAny[CellState()]

 step0.004EnergyAny[CellState()]

 step0.005EnergyAny[CellState()]

 step0.006EnergyAny[CellState()]

 step0.007EnergyAny[CellState()]

 step0.008EnergyAny[CellState()]

 step0.009000000000000001EnergyAny[CellState()]

 step0.010000000000000002EnergyAny[CellState()]

 step0.011000000000000003EnergyAny[CellState()]

 step0.012000000000000004EnergyAny[CellState()]

 step0.013000000000000005EnergyAny[CellState()]

 step0.014000000000000005EnergyAny[CellState()]

 step0.015000000000000006EnergyAny[CellState()]

 step0.016000000000000007EnergyAny[CellState()]

 step0.017000000000000008EnergyAny[CellState()]

 step0.01800000000000001EnergyAny[CellState()]

 step0.01900000000000001EnergyAny[CellState()]

 step0.02000000000000001EnergyAny[CellState()]

 step0.02100000000000001EnergyAny[CellState()]

 step0.022000000000000013EnergyAny[CellState()]

 step0.023000000000000013EnergyAny[CellState()]

 step0.024000000000000014EnergyAny[CellState()]

 step0.025000000000000015EnergyAny[CellState()]

 step0.026000000000000016EnergyAny[CellState()]

 step0.027000000000000017EnergyAny[CellState()]

 step0.028000000000000018EnergyAny[CellState()]

 step0.02900000000000002EnergyAny[CellState()]

 step0.03000000000000002EnergyAny[CellState()]

 step0.03010000000000002EnergyAny[CellState()]

 step0.03020000000000002EnergyAny[CellState()]

 step0.030300000000000018EnergyAny[CellState()]

 step0.030400000000000017EnergyAny[CellState()]

 step0.030500000000000017EnergyAny[CellState()]

 step0.030600000000000016EnergyAny[CellState()]

 step0.030700000000000015EnergyAny[CellState()]

 step0.030800000000000015EnergyAny[CellState()]

 step0.030900000000000014EnergyAny[CellState()]

 step0.031000000000000014EnergyAny[CellState()]

 step0.031100000000000013EnergyAny[CellState()]

 step0.031200000000000012EnergyAny[CellState()]

 step0.031300000000000015EnergyAny[CellState()]

 step0.03140000000000002EnergyAny[CellState()]

 step0.03150000000000002EnergyAny[CellState()]

 step0.031600000000000024EnergyAny[CellState()]

 step0.03170000000000003EnergyAny[CellState()]

 step0.03180000000000003EnergyAny[CellState()]

 step0.03190000000000003EnergyAny[CellState()]

 step0.032000000000000035EnergyAny[CellState()]

 step0.03210000000000004EnergyAny[CellState()]

 step0.03220000000000004EnergyAny[CellState()]

 step0.032300000000000044EnergyAny[CellState()]

 step0.03240000000000005EnergyAny[CellState()]

 step0.03250000000000005EnergyAny[CellState()]

 step0.03260000000000005EnergyAny[CellState()]

 step0.032700000000000055EnergyAny[CellState()]

 step0.03280000000000006EnergyAny[CellState()]

 step0.03290000000000006EnergyAny[CellState()]

 step0.033000000000000064EnergyAny[CellState()]

 step0.03310000000000007EnergyAny[CellState()]

 step0.03320000000000007EnergyAny[CellState()]

 step0.03330000000000007EnergyAny[CellState()]

 step0.033400000000000075EnergyAny[CellState()]

 step0.03350000000000008EnergyAny[CellState()]

 step0.03360000000000008EnergyAny[CellState()]

 step0.033700000000000084EnergyAny[CellState()]

 step0.03380000000000009EnergyAny[CellState()]

 step0.03390000000000009EnergyAny[CellState()]

 step0.03400000000000009EnergyAny[CellState()]

 step0.034100000000000096EnergyAny[CellState()]

 step0.0342000000000001EnergyAny[CellState()]

 step0.0343000000000001EnergyAny[CellState()]

 step0.034400000000000104EnergyAny[CellState()]

 step0.03450000000000011EnergyAny[CellState()]

 step0.03460000000000011EnergyAny[CellState()]

 step0.03470000000000011EnergyAny[CellState()]

 step0.034800000000000116
 step0.03490000000000012EnergyAny[CellState()]

 step0.03500000000000012
 step0.035100000000000124EnergyAny[CellState()]

 step0.03520000000000013
 step0.03530000000000013EnergyAny[CellState()]

 step0.03540000000000013
 step0.035500000000000136
 step0.03560000000000014EnergyAny[CellState()]

 step0.03570000000000014
 step0.035800000000000144
 step0.03590000000000015
 step0.03600000000000015
 step0.03610000000000015
 step0.036200000000000156
 step0.03630000000000016
 step0.03640000000000016
 step0.036500000000000164
 step0.03660000000000017
 step0.03670000000000017
 step0.03680000000000017
 step0.036900000000000176
 step0.03700000000000018
 step0.03710000000000018
 step0.037200000000000184
 step0.03730000000000019
 step0.03740000000000019
 step0.03750000000000019
 step0.037600000000000196
 step0.0377000000000002
 step0.0378000000000002
 step0.037900000000000204
 step0.03800000000000021
 step0.03810000000000021
 step0.03820000000000021
 step0.038300000000000216
 step0.03840000000000022
 step0.03850000000000022
 step0.038600000000000224
 step0.03870000000000023
 step0.03880000000000023
 step0.03890000000000023
 step0.039000000000000236
 step0.03910000000000024
 step0.03920000000000024

Also it seems that in this way by using record inside the calculate sth it will save record in every iteration of for loop in inner counter. I need the final value of calculate sth in each vApp
thank you

1 Like

Ah, that’s very useful information. After a bit of digging, I think the function update_state! is defined here

At the very end, it returns nothing , so the basic situation is the one I tried to describe above (plus the inner loop).

I’m not sure if the code you posted would really run, since new_EnergyState now requires three arguments, but you only supply two in update_state!. Unless you still have the original version of new_EnergyState defined (you can check by running methods(new_EnergyState) and inspecting the output), there should be a MethodError – also when you restart the Julia session. That would also explain why el is always empty, because at the moment, it never gets updated.

Note the “trick” of wrapping the three-argument function in a two-argument function using a closure:

el = [] # Some variable holding the recorded values.
new_EnergyState(a, b, record) = ... # Needs three arguments (two from the simulation, plus the record).
closure_of_new_EnergyState(a, b) = new_EnergyState(a, b, el) # Needs two arguments, so we can put it in `update_state!`. The record vector is now fixed to be the variable `el`.

If you want to save the output of new_EnergyState at the last iteration of the inner loop we need some extra bit of logic that only pushes the value to the vector if it’s the last iteration, or that overwrites the last entry if we stay in the inner loop. Here is a suggestion:

function new_EnergyState(ψPlusPrev_in, ψhPos_in)
    # Original function
end

# One function pushes a new entry ...
function new_EnergyState_push(ψPlusPrev_in, ψhPos_in, record)
    flag, value = new_EnergyState(ψPlusPrev_in, ψhPos_in)
    push!(record, value)
    return flag, value
end

# ... and another one updates the last entry
function new_EnergyState_update_last(ψPlusPrev_in, ψhPos_in, record)
    flag, value = new_EnergyState(ψPlusPrev_in, ψhPos_in)
    record[end] = value
    return flag, value
end

# ...

# Need to prepare the record variable ...
el = []
# ... as well as the closures
newE_push(a, b) = new_EnergyState_push(a, b, el)
newE_update(a, b) = new_EnergyState_update_last(a, b, el)

while ...

    for inner = 1:innerMax

        # We need to check whether to write a new entry or update the last one
        # Note that we cannot use `new_EnergyState` directly, but need to use the closures which "carry" the variable `el` with them:
        if inner == 1
            # First try: create a new entry in the record
            update_state!(newE_push, ψPlusPrev, ψhPos_in)
        else
            # We already created an entry in the record => update it
            update_state!(newE_update, ψPlusPrev, ψhPos_in)
        end

        # ...

    end

end
1 Like

thank you for your kind explanation. It really helps

1 Like

You’re welcome!