import logging
import click
from message_ix_models import Context
from message_ix_models.model.structure import get_codes
from message_ix_models.util.click import common_params, scenario_param
log = logging.getLogger(__name__)
# allows to activate water module
@click.group("water-ix")
@common_params("regions")
@scenario_param("--ssp", default="SSP2")
@click.option("--time", help="Manually defined time")
@click.pass_obj
def cli(context: "Context", regions, time):
"""MESSAGEix-Water and Nexus variant."""
water_ini(context, regions, time)
[docs]
def water_ini(context: "Context", regions, time):
"""Add components of the MESSAGEix-Nexus module
This function modifies model name & scenario name
and verifies the region setup
Parameters
----------
context : `class`:message.Context
Information about target Scenario.
regions : str (if not defined already in context.regions)
Specifies what region definition is used ['R11','R12','ISO3']
"""
from .utils import read_config
# Ensure water model configuration is loaded
read_config(context)
if not context.scenario_info:
context.scenario_info.update(
dict(model="ENGAGE_SSP2_v4.1.7", scenario="baseline_clone_test")
)
context.output_scenario = context.scenario_info["scenario"]
context.output_model = context.scenario_info["model"]
# Handle --regions; use a sensible default for MESSAGEix-Nexus
if regions:
log.info(f"Regions choice {regions}")
if regions in ["R14", "R32", "RCP"]:
log.warning(
"the MESSAGEix-Nexus module might not be compatible"
"with your 'regions' choice"
)
else:
log.info("Use default --regions=R11")
regions = "R11"
# add an attribute to distinguish country models
if regions in ["R11", "R12", "R14", "R32", "RCP"]:
context.type_reg = "global"
else:
context.type_reg = "country"
context.regions = regions
# create a mapping ISO code :
# a region name, for other scripts
# only needed for 1-country models
nodes = get_codes(f"node/{context.regions}")
nodes = list(map(str, nodes[nodes.index("World")].child))
if context.type_reg == "country":
map_ISO_c = {context.regions: nodes[0]}
context.map_ISO_c = map_ISO_c
log.info(f"mapping {context.map_ISO_c[context.regions]}")
# deinfe the timestep
if not time:
sc_ref = context.get_scenario()
time = sc_ref.set("time")
sub_time = list(time[time != "year"])
if len(sub_time) == 0:
context.time = ["year"]
else:
context.time = sub_time
else:
context.time = [time]
log.info(f"Using the following time-step for the water module: {context.time}")
# setting the time information in context
_RCPS = ["no_climate", "6p0", "2p6", "7p0"]
_REL = ["low", "med", "high"]
@cli.command("nexus")
@click.pass_obj
@click.option(
"--rcps",
default="no_climate",
type=click.Choice(_RCPS),
show_default=True,
help="Specifies the climate scenario used ['no_climate','6p0','2p6']",
)
@click.option(
"--rels",
default="low",
type=click.Choice(_REL),
show_default=True,
help="Specifies the reliability of hydrological data ['low','mid','high']",
)
@click.option(
"--sdgs",
default="baseline",
help="Defines if and what water SDG measures are activated",
)
@click.option(
"--macro",
is_flag=True,
help="Defines whether the model solves with macro",
)
@common_params("regions")
@scenario_param("--ssp")
def nexus_cli(context: "Context", regions, rcps, sdgs, rels, macro=False):
"""
Add basin structure connected to the energy sector and
water balance linking different water demands to supply.
"""
nexus(context, regions, rcps, sdgs, rels, macro)
[docs]
def nexus(context: "Context", regions, rcps, sdgs, rels, macro=False):
"""Add basin structure connected to the energy sector and
water balance linking different water demands to supply.
Use the --url option to specify the base scenario.
Parameters
----------
context : `class`:message.Context
Information about target Scenario.
regions : str (if not defined already in context.regions)
Specifies what region definition is used ['R11','R12','ISO3']
RCP : str
Specifies the climate scenario used ['no_climate','6p0','2p6']
SDG : Str
Defines if and what water SDG measures are activated
REL: str
Specifies the reliability of hydrological data ['low','mid','high']
"""
# add input information to the class context
context.nexus_set = "nexus"
if not context.regions:
context.regions = regions
context.RCP = rcps
context.SDG = sdgs
context.REL = rels
log.info(
f"SSP assumption is {context.ssp}. SDG is {context.SDG}. "
f"RCP is {context.RCP}. REL is {context.REL}."
)
from .build import main as build
# Determine the output scenario name based on the --url CLI option. If the
# user did not give a recognized value, this raises an error
output_scenario_name = context.output_scenario + "_nexus"
output_model_name = context.output_model
# Clone and build
sc_ref = context.get_scenario()
scen = sc_ref.clone(
model=output_model_name, scenario=output_scenario_name, keep_solution=False
)
log.info(
f" clone from {sc_ref.model}.{sc_ref.scenario} to {scen.model}.{scen.scenario}"
)
# Exporting the built model (Scenario) to GAMS with an optional case name
caseName = scen.model + "__" + scen.scenario + "__v" + str(scen.version)
# Build
build(context, scen)
# Set scenario as default
scen.set_as_default()
# Solve
if macro:
scen.solve(
model="MESSAGE-MACRO",
solve_options={"lpmethod": "4", "scaind": "1"},
case=caseName,
)
else:
scen.solve(solve_options={"lpmethod": "4"}, case=caseName)
# if options["report"]:
# # Also output diagnostic reports
# from message_data.model.water import report, run_old_reporting
#
# old reporting
# run_old_reporting(scen)
# log.info(f"Report plots to {rep.graph['config']['output_dir']}")
# mark_time()
@cli.command("cooling")
@common_params("regions")
@scenario_param("--ssp")
@click.option(
"--rcps",
default="no_climate",
type=click.Choice(_RCPS),
show_default=True,
help="Specifies the climate scenario used ['no_climate','6p0','2p6']",
)
@click.option(
"--rels",
default="low",
type=click.Choice(_REL),
show_default=True,
help="Specifies the reliability of hydrological data ['low','mid','high']",
)
@click.pass_obj
def cooling_cli(context, regions, rcps, rels):
"""Build and solve model with new cooling technologies."""
cooling(context, regions, rcps, rels)
[docs]
def cooling(context, regions, rcps, rels):
"""Build and solve model with new cooling technologies.
Use the --url option to specify the base scenario.
Parameters
----------
context : `class`:message.Context
Information about target Scenario.
regions : str (if not defined already in context.regions)
Specifies what region definition is used ['R11','R12','ISO3']
RCP : str
Specifies the climate scenario used ['no_climate','6p0','2p6']
"""
context.nexus_set = "cooling"
context.RCP = rcps
context.REL = rels
log.info(
f"SSP assumption is {context.ssp}. "
f"RCP is {context.RCP}. REL is {context.REL}."
)
from .build import main as build
# Determine the output scenario name based on the --url CLI option. If the
# user did not give a recognized value, this raises an error.
output_scenario_name = context.output_scenario + "_cooling"
output_model_name = context.output_model
# Clone and build
scen = context.get_scenario().clone(
model=output_model_name, scenario=output_scenario_name, keep_solution=False
)
print(scen.model)
print(scen.scenario)
# Exporting the built model (Scenario) to GAMS with an optional case name
caseName = scen.model + "__" + scen.scenario + "__v" + str(scen.version)
# Build
build(context, scen)
# Set scenario as default
scen.set_as_default()
# Solve
scen.solve(solve_options={"lpmethod": "4", "scaind": "1"}, case=caseName)
@cli.command("report")
@click.pass_obj
@click.option(
"--sdgs",
default="baseline",
help="Defines if and what water SDG measures are activated",
)
@click.option(
"--water",
is_flag=True,
help="Default running legacy and water (full) otherwise only water, if specified",
)
@common_params("output_model")
def report_cli(context: "Context", output_model, sdgs, water=False):
"""function to run the water report_full from cli to the
scenario defined by the user with --url
Parameters
----------
context : `class`:message.Context
Information about target Scenario.
output_model : str (optional, otherwise default args used)
Specifies the model name of the scenarios which are run.
SDG : Str
Defines if and what water SDG measures are activated
"""
reg = context.model.regions
sc = context.get_scenario()
if water:
from message_ix_models.model.water.report import report
report(sc, reg, sdgs)
else:
from message_ix_models.model.water.report import report_full
report_full(sc, reg, sdgs)