Mimi Framework

Update_param! for temp in FUND

The FUND “climatedynamics” component calculates too much temperature rise for a given ECS and emissions scenario than the climate models when ECS is less than 3 C. I created a spreadsheet with a 2-box climate model that matches the climate model behavior. I created a new temperature profile of 1051 years and attempted to use the update_param! function in each component, such as;
update_param!(m, :ocean, :temp, Tempcor)
where “temp” is the global average temperature from FUND and “Tempcor” is my temperature from 2-box climate model, both parameter have the length 1051 and are one dimensional. However, this gives this error:
MethodError: no method matching update_param!(::Model, ::Symbol, ::Symbol, ::Array{Float64,1})
Closest candidates are:
update_param!(::Model, ::Symbol, ::Any; update_timesteps) at C:\Users\Ken.julia\packages\Mimi\mHt54\src\core\delegate.jl:54
update_param!(!Matched::Mimi.AbstractCompositeComponentDef, ::Symbol, ::Any; update_timesteps) at C:\Users\Ken.julia\packages\Mimi\mHt54\src\core\connections.jl:480
update_param!(!Matched::Mimi.ModelInstance, ::Symbol, ::Any) at C:\Users\Ken.julia\packages\Mimi\mHt54\src\core\connections.jl:484

Stacktrace:
[1] top-level scope at In[85]:1
[2] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

Can you tell me why the update_param! line doesn’t work?

Sorry in advance for length, but I wanted to be comprehensive and clear here!

You can only call update_param! on an existing model parameter that was previously created by calling set_param!.

In the original FUND model created with

m = MimiFUND.get_model()

the temp parameter in components such as ocean is never set with set_param!, so there is no model parameter :temp holding values that can be updated. The values are instead computed within the climatedynamics component as the temp variable and then connected to the temp parameter in various components, including ocean, with a call to connect_param!.

There are several options for changing how temperature is calculated and passed to components within FUND depending on your goals as written below, and the Mimi API is here for reference and clarification.



If you want to remove the climatedynamics component entirely, you can do so with delete_comp!. You will then need to fix up any missing connections that used to flow throw climatedynamics using new connections for dynamic computation, or set_param! to force with external values.



If you want to edit the climatedynamics component’s computation of temperature, you can create your own component from scratch or derived from the FUND climatedynamics component and then use the replace_comp! functionality. This could, for example, adapt FUND’s climatedynamics :temp variable to be computed in a different way, which would then automatically flow through the model.



If you want to leave the FUND components as they are but just force some components with your new Tempcor values, you could break the connections between climatedynamics and the various components like ocean and then call set_param! to set their values to your externally computed Tempcor.

Generally, the easiest way to do this would be to first disconnect all the component parameters you want to use your external values with disconnect_param!, so they no longer pull from climate dynamics, and then use set_param! create a new model parameter temp with values Tempcor, which at run time will set the value for parameter temp in any component with a parameter of that name that is not yet connected.

m = MimiFUND.get_model()
disconnect_param(m, :ocean, :temp)
disconnect_param(m, :other_component, :temp)
set_param!(m, :temp, Tempcor)

However, in FUND temp is a parameter in several components, not all of which use the same values (ie. in ocean it only has the time dimension but in others it has both time and regions), so Mimi cannot safely make the assumption that any component parameter :temp that is not unconnected at build time can be set to the same model parameter.

Instead, we must call set_param! for each component and be explicit about what we want the model parameter name to be using the longer set_param! method set_param!(m, comp_name, param_name, unique_param_name, value), so your code would be

m = MimiFUND.get_model()
disconnect_param(m, :ocean, :temp) # optional, the line below will do this automatically
set_param!(m, :ocean, :temp, :ocean_temp, Tempcor)

This will break any connections ocean's parameter temp has to other variables, create a new model parameter with the name ocean_temp (normally defaults to the temp) with value Tempcor, and then set ocean's parameter :temp to the have the values of the model parameter ocean_temp, which in this case are Tempcor.

Then if you want to update ocean's temp parameter in the future you would use

update_param!(m, :ocean_temp, new_values)

Thanks you for the detailed reply. It was very helpful and the code worked fine! Yes, I was aware that the parameter temp is a 1 dimensional vector in 3 components and a 2 dimensional array in 8 components. ‘temp’ is global average temperature anomaly, so it is the same in all 16 regions, so there is no point in having temp as an array. It appears to be just a waste of memory.

Of course, setting ‘temp’ from an Excel file calculation is a poor solution. I will now attempt to create a new climatedynamics component to include my 2-box climate model from Excel. I won’t be able to do that for a few days.