Skip to content

Commit

Permalink
Separate config to store just transport fluxes.
Browse files Browse the repository at this point in the history
  • Loading branch information
Maginor committed Sep 2, 2024
1 parent e2f5b07 commit badcc61
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 269 deletions.
7 changes: 3 additions & 4 deletions dev_notes/todo.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@

Add forums on github page? (github Discussions)

Would like to be able to use in_flux in initial code (for e.g. setting initial steady states easily), but then we also need to be able to compute initial values for fluxes. With in_flux_connection it could be tricky to determine what initial fluxes must be computed (?).
Would like to be able to use in_flux in initial code (for e.g. setting initial steady states easily), but then we also need to be able to compute initial values for fluxes. With in_flux_connection it could be tricky to determine what initial fluxes must be computed (Not tricky, maybe, but a lot of work.. ?).

Made it possible to add properties to solvers manually, but it could be error prone.
Fix errors if they appear.

Specific models

Keep better track of what elevation different models want wind speed. Maybe convert between different elevations if necessary.

Maybe factor out common phyto module for EasyChem and FjordChem.
Also for O2 (found a difficulty with that earlier, but maybe we could resolve it?)

NIVAFjord!

Expand Down Expand Up @@ -92,7 +91,7 @@
Alternatively, in the ODE codegen, directly make a subtraction of the flux (on condition of correct index).
This is maybe the easiest, but is still a bit of work for this special case.

Actually in grid1d the connection aggregate is always unnecessary unless it is referenced. Would be better to remove it as a default and only generate it if it is referenced by in_flux(connection).
Actually in grid1d the connection aggregate is always unnecessary unless it is referenced. Would it be better to remove it as a default and only generate it if it is referenced in code by in_flux(connection)?


.specific target:
Expand Down
2 changes: 1 addition & 1 deletion docs/existingmodels/existingmodels.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Mobius2 framework comes with several existing modules and models that can be
If desired, the above models can be coupled together into a full catchment-to-coast system, or you can use them separately to study smaller sub-systems.

The following model is stand-alone:
- [MAGIC](magic.html). This is a longer-timescale model for development of soil water chemistry (with a focus on acidity) in smaller catchment.
- [MAGIC](magic.html). This is a longer-timescale model for development of soil water chemistry (with a focus on acidity) in smaller catchments.

In addition to these, Mobius2 comes with modules for other processes that are convenient to include into larger models, for instance
- [Snow pack and melt](autogen/auxiliary.html#hbvsnow)
Expand Down
5 changes: 3 additions & 2 deletions docs/mobius2docs/guide_chapters/07_layered_lake.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ var(layer.water.N2freq, [s-2]) {
Note how we can reference a value below us along a `grid1d` connection by using a square bracket.

The `@no_store` directive just tells Mobius2 to not store the time series of this variable. This can be useful for a couple of reasons
- It saves memory. This is especially important for variables in compartments that are distributed over large index sets.
- Too many variables can clutter up the user interface, and not all of them are interesting in themselves.

- It saves memory. This is especially important for variables in compartments that are distributed over large index sets.
- Too many variables can clutter up the user interface, and not all of them are interesting in themselves.

The mixing coefficient $$K$$ is (as in MyLake) given by

Expand Down
280 changes: 53 additions & 227 deletions example_notebooks/basic_julia.ipynb

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion example_notebooks/basic_python.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x20a1c881340>"
"<matplotlib.legend.Legend at 0x1c818f6eae0>"
]
},
"execution_count": 3,
Expand Down Expand Up @@ -249,6 +249,14 @@
"app.run()\n",
"app.var('Reach flow flux')['Coull'].plot(figsize=(10, 5), legend=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4a9a5de3-9040-4c9c-bee7-e51c9b921a9e",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
24 changes: 21 additions & 3 deletions mobipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ class Mobius_Entity_Metadata(ctypes.Structure) :
("min", Parameter_Value),
("max", Parameter_Value)
]

class Mobius_Base_Config(ctypes.Structure) :
_fields_ = [
("store_transport_fluxes", ctypes.c_bool),
("store_all_series", ctypes.c_bool),
("developer_mode", ctypes.c_bool),
]

def mobius2_path() :
#NOTE: We have to add a trailing slash to the path for Mobius2 to understand it.
Expand Down Expand Up @@ -106,7 +113,7 @@ def load_dll() :
dll.mobius_encountered_log.argtypes = [ctypes.c_char_p, ctypes.c_int64]
dll.mobius_encountered_log.restype = ctypes.c_int64

dll.mobius_build_from_model_and_data_file.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_bool, ctypes.c_bool]
dll.mobius_build_from_model_and_data_file.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(Mobius_Base_Config)]
dll.mobius_build_from_model_and_data_file.restype = ctypes.c_void_p

dll.mobius_delete_application.argtypes = [ctypes.c_void_p]
Expand Down Expand Up @@ -391,9 +398,20 @@ def __exit__(self, type, value, tb) :
self.__del__()

@classmethod
def build_from_model_and_data_file(cls, model_file, data_file, store_all_series=False, dev_mode=False) :
def build_from_model_and_data_file(cls, model_file, data_file,
store_all_series=False, dev_mode=False, store_transport_fluxes=False
) :

base_path = mobius2_path()
data_ptr = dll.mobius_build_from_model_and_data_file(_c_str(model_file), _c_str(data_file), _c_str(base_path), store_all_series, dev_mode)

# TODO: We could use the args as dict thing here to make this more dynamic.
config = Mobius_Base_Config()
config.store_all_series = store_all_series
config.dev_mode = dev_mode
config.store_transport_fluxes = store_transport_fluxes

cfgptr = ctypes.POINTER(Mobius_Base_Config)(config)
data_ptr = dll.mobius_build_from_model_and_data_file(_c_str(model_file), _c_str(data_file), _c_str(base_path), cfgptr)
_check_for_errors()
return cls(data_ptr, True)

Expand Down
16 changes: 13 additions & 3 deletions mobius_jl/mobius.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ struct Entity_Ref
entity_id::Entity_Id
end

struct Mobius_Base_Config
store_transport_fluxes::Cint
store_all_series::Cint
developer_mode::Cint
end

invalid_entity_id = Entity_Id(-1, -1)
invalid_var = Var_Id(-1, -1)
no_index = Mobius_Index_Value(C_NULL, 0)
Expand Down Expand Up @@ -97,11 +103,15 @@ function check_error()
end
end

function setup_model(model_file::String, data_file::String, store_series::Bool = false, dev_mode::Bool = false)::Model_Data
function setup_model(model_file::String, data_file::String, ; store_transport_fluxes::Bool = false, store_all_series::Bool = false, dev_mode::Bool = false)::Model_Data
#mobius_path = string(dirname(dirname(Base.source_path())), "\\") # Doesn't work in IJulia
mobius_path = string(dirname(dirname(@__FILE__)), "\\")
result = ccall(setup_model_h, Ptr{Cvoid}, (Cstring, Cstring, Cstring, Cint, Cint),
model_file, data_file, mobius_path, store_series, dev_mode)

cfg = Mobius_Base_Config(store_transport_fluxes, store_all_series, dev_mode)
cfgptr = Ref(cfg)

result = ccall(setup_model_h, Ptr{Cvoid}, (Cstring, Cstring, Cstring, Ptr{Mobius_Base_Config}),
model_file, data_file, mobius_path, cfgptr)
check_error()
return Model_Data(result, true)
end
Expand Down
33 changes: 16 additions & 17 deletions models/modules/airsea_fpv.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,6 @@ Authors: Francois Clayer, Magnus D. Norling

/*

# TODO: Separate heat fluxes between FPV-surface (and FPV-air) ?

# TODO: Make the below work (and add the correct heat budget for the basin?)

k_vis : property("Kinematic viscosity")
Expand All @@ -202,25 +200,26 @@ Authors: Francois Clayer, Magnus D. Norling

# TODO: Name the magic constants, and/or reference the formula

#T_front_final := air.temp->[K],
#need to iterate to updte T_front (what is the breaking condition?)
T_front := top_water.temp->[K],
T_air := air.temp->[K],
T_sky := (0.0552 * (T_air=>[]^(1.5))) => [K],
T_water := top_water.temp -> [K], # Why is it the same as T_front?
h_air := (2.8 + 3*air.wind=>[]) => [W, m-2, K-1],
h_sky := (1/(1/0.88+1/0.80-1)) * 5.67e-8[W, m-2, K-4] * (T_front+T_sky)*(T_front^2 + T_sky^2),
B_back := A_both + h_water,
C_back := h_water * T_water,
T_air := air.temp->[K],
T_sky := (0.0552 * (T_air=>[]^1.5)) => [K],
T_water := top_water.temp -> [K],
h_air := (2.8 + 3*air.wind=>[]) => [W, m-2, K-1],
B_back := A_both + h_water,
C_back := h_water * T_water,

T_front := top_water.temp->[K] + 3[K],
eps := 0.001[K]
i:{
h_sky := (1/(1/0.88+1/0.80-1)) * 5.67e-8[W, m-2, K-4] * (T_front+T_sky)*(T_front^2 + T_sky^2),
B_front := A_both + h_air + h_sky,
C_front := h_air*T_air + h_sky*T_sky,
numer := B_front*B_back*2*A_both - (A_both^2)*(B_front - B_back),
T_cell := (B_front*B_back*(1- FPV_alb) * (1-FPV_eff)*air.g_rad + A_both*B_back*C_front + A_both*B_front*C_back) / numer -> [deg_c],
#A_both * h_water / (A_both + h_water) + A_both / (A_both + h_air + h_sky)*(h_air + h_sky*(Tc - T_sky)/(Tc - T_air))
T_front_final := ((A_both =>[] * (T_cell->[K])=>[]) + C_front=>[]) / B_front=>[],
T_cell := (B_front*B_back*(1- FPV_alb)*(1-FPV_eff)*air.g_rad + A_both*(B_back*C_front + B_front*C_back)) / numer -> [deg_c],
T_front_update := ((A_both =>[] * (T_cell->[K])=>[]) + C_front=>[]) / B_front=>[K],

T_cell

T_cell if abs(T_front - T_front_update) < eps,
{T_front <- T_front_update, iterate i} otherwise
}
}

var(fpv.T_s_back, [deg_c]) {
Expand Down
3 changes: 2 additions & 1 deletion models/modules/pet.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ Authors: Magnus D. Norling
# Also, the energy balance should take snow melt into account.
net_rad := net_sw + air.lwd - lwu,

u := max(0.5[m, s-1], air.wind),
w := air.wind * 0.75, # Convert from 10m to 2m altitude
u := max(0.5[m, s-1], w),
# Modified psychrometric constant
psy_corr := {
psy if pt,
Expand Down
6 changes: 2 additions & 4 deletions src/c_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,10 @@ mobius_encountered_log(char *msg_out, s64 buf_len) {
}

DLLEXPORT Model_Data *
mobius_build_from_model_and_data_file(char * model_file, char * data_file, char *base_path, bool store_series, bool dev_mode) {
mobius_build_from_model_and_data_file(char * model_file, char * data_file, char *base_path, Mobius_Base_Config *cfg) {

Mobius_Config config;
Mobius_Config config = *cfg;
config.mobius_base_path = base_path;
config.store_all_series = store_series;
config.developer_mode = dev_mode;

try {
Mobius_Model *model = load_model(model_file, &config);
Expand Down
2 changes: 1 addition & 1 deletion src/c_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ DLLEXPORT s64
mobius_encountered_log(char *msg_out, s64 buf_len);

DLLEXPORT Model_Data *
mobius_build_from_model_and_data_file(char * model_file, char * data_file, char *base_path, bool store_series, bool dev_mode);
mobius_build_from_model_and_data_file(char * model_file, char * data_file, char *base_path, Mobius_Base_Config *cfg);

DLLEXPORT void
mobius_delete_application(Model_Data *data);
Expand Down
2 changes: 1 addition & 1 deletion src/model_composition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ prelim_compose(Model_Application *app, std::vector<std::string> &input_names) {
sprintf(varname, "carried_flux(%s, %s)", var_name.data(), flux_name.data());

// It is just much cleaner in MobiView if this is off, but on the other hand we do want to know some of these fluxes quite often. Make a more granular way to specify which ones to store?
bool no_store = true;
bool no_store = !model->config.store_transport_fluxes;

Var_Id gen_flux_id = register_state_variable<State_Var::Type::dissolved_flux>(app, invalid_entity_id, false, varname, no_store);
auto gen_flux = as<State_Var::Type::dissolved_flux>(app->vars[gen_flux_id]);
Expand Down
9 changes: 7 additions & 2 deletions src/model_declaration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1466,19 +1466,24 @@ load_config(String_View file_name) {
match_declaration(decl, {{Token_Type::quoted_string, Token_Type::boolean}}, false);

config.developer_mode = single_arg(decl, 1)->val_bool;

log_print(Log_Mode::dev, file_name, ": Configured to developer mode.\n");
} else if(item == "Just store all the series") {
match_declaration(decl, {{Token_Type::quoted_string, Token_Type::boolean}}, false);

config.store_all_series = single_arg(decl, 1)->val_bool;
} else if(item == "Store transport fluxes") {
match_declaration(decl, {{Token_Type::quoted_string, Token_Type::boolean}}, false);

config.store_transport_fluxes = single_arg(decl, 1)->val_bool;
} else {
decl->source_loc.print_error_header();
fatal_error("Unknown config option \"", item, "\".");
}
delete decl;
}

if(config.developer_mode)
log_print(Log_Mode::dev, file_name, ": Configured to developer mode.\n");

return std::move(config);
}

Expand Down
12 changes: 10 additions & 2 deletions src/model_declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,20 @@ Solver_Function_Registration : Registration_Base {
};

struct
Mobius_Config {
std::string mobius_base_path;
Mobius_Base_Config {
bool store_transport_fluxes = false;
bool store_all_series = false;
bool developer_mode = false;
};

struct
Mobius_Config : Mobius_Base_Config {
std::string mobius_base_path;

Mobius_Config() = default;
Mobius_Config(const Mobius_Base_Config &c) : Mobius_Base_Config(c) {}
};

struct
Mobius_Model : Catalog {

Expand Down

0 comments on commit badcc61

Please sign in to comment.