import mikeplus as mp
= mp.open('data/Dyrup_uncalibrated_copy.sqlite') db
Scenarios
MIKE+Py allows you to programmatically manage scenarios and alternatives within your MIKE+ model database, enabling automation of scenario-based analyses.
Concept Overview
MIKE+ uses a system of scenarios and alternatives to manage different model setups and variations.
- Scenarios
- Represent a complete model configuration for a specific simulation case (e.g., “Current Conditions”, “Future Development with Pipe Upgrade A”). Scenarios can inherit from a parent scenario. Only one scenario may be active at a time.
- Alternative Groups
- Organize different types of model data that can vary between scenarios (e.g., “CS Network data”). Each group contains one or more alternatives, which can inherit from parent alternatives. Only one alternative may be active at a time within an alternative group.
- Alternatives
- Represent a specific version of the data within an alternative group (e.g., for “CS Network data”, you might have a “Base Network” alternative and a “Upgraded Pipes” alternative).
For a detailed conceptual understanding of scenarios and alternatives, please refer to the MIKE+ documentation. This section focuses on how to interact with them using MIKE+Py.
Alternative Groups
List the names of all alternative groups. These are the main categories visible from the MIKE+ Scenarios editor.
db.alternative_groups.group_names()
['CS Network data',
'River network data',
'Loads and boundaries data',
'Catchments and hydrology data',
'Transport data',
'Control rules data',
'Long Term Statistics data',
'Profiles and curves',
'2D overland',
'2D boundaries data']
Access a specific alternative group by its name:
= db.alternative_groups["CS Network data"]
network_group network_group
<AlternativeGroup CS Network data>
Each group has a base alternative:
network_group.base
Alternative(CS Network data) <Base Alternative>
And an active alternative (which is part of the active scenario):
network_group.active
Alternative(CS Network data) <Base Alternative>
List the tables associated with an alternative group:
network_group.tables
['msm_Node',
'msm_Link',
'msm_Pump',
'msm_Weir',
'msm_Orifice',
'msm_Valve',
'msm_CurbInlet',
'msm_OnGrade',
'msm_OnGradeD']
Alternatives
See all alternatives for the group.
list(network_group)
[Alternative(CS Network data) <Base Alternative>]
Access an alternative within a group by its name:
"Base Alternative") network_group.by_name(
Alternative(CS Network data) <Base Alternative>
Create a new alternative. It will be a child of its parent (defaults to the group’s base alternative if not specified):
= network_group.create("New Roughness Values", parent=network_group.base)
new_roughness_alt new_roughness_alt
Alternative(CS Network data) <New Roughness Values>
Alternatives have several properties. For example, change an alternative’s comment:
= "Alternative for testing higher roughness."
new_roughness_alt.comment new_roughness_alt.comment
'Alternative for testing higher roughness.'
Scenarios
Scenarios combine various alternatives to define a complete model state. Access all scenarios in the database:
db.scenarios
ScenarioCollection <1>
Get the currently active scenario:
db.scenarios.active
Scenario <Base>
Get the base scenario:
db.scenarios.base
Scenario <Base>
Access a scenario by its name (returns the first match):
"Base") db.scenarios.by_name(
Scenario <Base>
List all scenarios:
list(db.scenarios)
[Scenario <Base>]
Create new scenarios with a name and its parent scenario (defaults to base scenario if not provided)
= db.scenarios.create("My Scenario", parent=db.scenarios.base)
new_scenario list(db.scenarios)
[Scenario <Base>, Scenario <My Scenario>]
Similar to Alternatives, Scenarios have several properties. For example:
= "This is a test scenario" new_scenario.comment
List the alternatives used by a scenario:
new_scenario.alternatives
[Alternative(CS Network data) <Base Alternative>,
Alternative(River network data) <Base Alternative>,
Alternative(Loads and boundaries data) <Base Alternative>,
Alternative(Catchments and hydrology data) <Base Alternative>,
Alternative(Transport data) <Base Alternative>,
Alternative(Control rules data) <Base Alternative>,
Alternative(Long Term Statistics data) <Base Alternative>,
Alternative(Profiles and curves) <Base Alternative>,
Alternative(2D overland) <Base Alternative>,
Alternative(2D boundaries data) <Base Alternative>]
Check if a scenario is active
new_scenario.is_active
False
Activate a scenario. This makes it the current context for data modifications and simulations.
new_scenario.activate() new_scenario.is_active
True
Set a specific alternative for a scenario. This will replace any existing alternative from the same group.
Let’s use the new_roughness_alt
created earlier and assign it to new_scenario
.
new_scenario.set_alternative(new_roughness_alt)list(new_scenario.alternatives)
[Alternative(CS Network data) <New Roughness Values>,
Alternative(River network data) <Base Alternative>,
Alternative(Loads and boundaries data) <Base Alternative>,
Alternative(Catchments and hydrology data) <Base Alternative>,
Alternative(Transport data) <Base Alternative>,
Alternative(Control rules data) <Base Alternative>,
Alternative(Long Term Statistics data) <Base Alternative>,
Alternative(Profiles and curves) <Base Alternative>,
Alternative(2D overland) <Base Alternative>,
Alternative(2D boundaries data) <Base Alternative>]
Delete a scenario. You cannot delete the base scenario.
db.scenarios.delete(new_scenario)list(db.scenarios)
[Scenario <Base>]
Practical Example
Let’s continue with the catchment examples of the previous section. We would like to test two different scenarios:
- Time of concentration = 2000s for all catchments draining to Flow Meter B
- Time of concentration = 3000s for all catchments draining to Flow Meter B
Recall that the initial time of concentration for these catchments was 2500 seconds.
First, get a list of the catchment MUIDs again.
= "Flow_Meter_B_Catchments"
selection_name = (
catchment_muids_to_modify
db.tables.m_Selection'ItemMUID'])
.select([f"{db.tables.m_Selection.columns.SelectionID} = {mp.to_sql(selection_name)}")
.where(f"{db.tables.m_Selection.columns.TableName} = {mp.to_sql(db.tables.msm_Catchment.name)}")
.where('ItemMUID']
.to_dataframe()[
.tolist()
)3] # Show first few MUIDs catchment_muids_to_modify[:
['G61F180_7321', 'G62F060_7424', 'G62F070_7425']
Our catchments are in table msm_Catchment
, which is part of the Catchments and hydrology data
Alternative Group. Let’s create two new alternatives.
= db.alternative_groups["Catchments and hydrology data"].create("Time of Concentration = 2000s")
alternative_2000 = db.alternative_groups["Catchments and hydrology data"].create("Time of Concentration = 3000s")
alternative_3000 list(db.alternative_groups["Catchments and hydrology data"])
[Alternative(Catchments and hydrology data) <Base Alternative>,
Alternative(Catchments and hydrology data) <Time of Concentration = 2000s>,
Alternative(Catchments and hydrology data) <Time of Concentration = 3000s>]
Let’s create two new scenarios, and apply the alternatives to them.
= db.scenarios.create("Time of Concentration = 2000s")
scenario_2000
scenario_2000.set_alternative(alternative_2000)
= db.scenarios.create("Time of Concentration = 3000s")
scenario_3000
scenario_3000.set_alternative(alternative_3000)
list(db.scenarios)
[Scenario <Base>,
Scenario <Time of Concentration = 2000s>,
Scenario <Time of Concentration = 3000s>]
Now let’s activate each scenario and make changes to the new alternative.
scenario_2000.activate()= (
updated
db.tables.msm_Catchment
.update({2000
db.tables.msm_Catchment.columns.ModelAConcTime :
})
.by_muid(catchment_muids_to_modify)
.execute()
)len(updated)
32
scenario_3000.activate()= (
updated
db.tables.msm_Catchment
.update({3000
db.tables.msm_Catchment.columns.ModelAConcTime :
})
.by_muid(catchment_muids_to_modify)
.execute()
)len(updated)
32
Now let’s verify by activating each scenario and checking time of concentration values.
import pandas as pd
# Check base scenario
db.scenarios.base.activate()
df_base = (
db.tables.msm_Catchment
.select([db.tables.msm_Catchment.columns.ModelAConcTime])
.by_muid(catchment_muids_to_modify)
.to_dataframe()
)
df_base.columns = ["Base Tc"]
# Check Tc = 2000
db.scenarios.by_name("Time of Concentration = 2000s").activate()
df_2000 = (
db.tables.msm_Catchment
.select([db.tables.msm_Catchment.columns.ModelAConcTime])
.by_muid(catchment_muids_to_modify)
.to_dataframe()
)
df_2000.columns = ["Tc = 2000s"]
# Check Tc = 3000
db.scenarios.by_name("Time of Concentration = 3000s").activate()
df_3000 = (
db.tables.msm_Catchment
.select([db.tables.msm_Catchment.columns.ModelAConcTime])
.by_muid(catchment_muids_to_modify)
.to_dataframe()
)
df_3000.columns = ["Tc = 3000s"]
# Concatenate into common DataFrame for comparison
df_compare = pd.concat([df_base, df_2000, df_3000], axis=1)
df_compare.describe()
Base Tc | Tc = 2000s | Tc = 3000s | |
---|---|---|---|
count | 32.0 | 32.0 | 32.0 |
mean | 2500.0 | 2000.0 | 3000.0 |
std | 0.0 | 0.0 | 0.0 |
min | 2500.0 | 2000.0 | 3000.0 |
25% | 2500.0 | 2000.0 | 3000.0 |
50% | 2500.0 | 2000.0 | 3000.0 |
75% | 2500.0 | 2000.0 | 3000.0 |
max | 2500.0 | 2000.0 | 3000.0 |
This section demonstrated how to view, create, and manage scenarios and alternatives. In the next section, you’ll learn how to run MIKE+ simulations.