From f45d135f0ff06f6e27b7d9aead4967b27b5f60f6 Mon Sep 17 00:00:00 2001 From: ChouaneLouis Date: Tue, 21 May 2024 11:15:58 +0200 Subject: [PATCH] project file structure implemented enable the possibility to use the command with only the parameter --study fix the fact that the preloaded_libraries parameter in the resolve_library method didn't keep the preloaded models in the returned library --- src/andromede/main/main.py | 70 ++++++++++++++----- src/andromede/model/resolve_library.py | 2 + .../input/components/components.yml} | 6 +- .../input/components/series/demand-ts.txt} | 0 .../input/models/lib_1.yml} | 42 ----------- tests/functional/input/models/lib_2.yml | 64 +++++++++++++++++ 6 files changed, 124 insertions(+), 60 deletions(-) rename tests/{unittests/data/components_for_thermal_cluster.yml => functional/input/components/components.yml} (81%) rename tests/{unittests/data/demand-ts_2.txt => functional/input/components/series/demand-ts.txt} (100%) rename tests/{unittests/data/lib_2.yml => functional/input/models/lib_1.yml} (65%) create mode 100644 tests/functional/input/models/lib_2.yml diff --git a/src/andromede/main/main.py b/src/andromede/main/main.py index 9413c2c1..26e159e2 100644 --- a/src/andromede/main/main.py +++ b/src/andromede/main/main.py @@ -10,8 +10,9 @@ # # This file is part of the Antares project. import argparse +from os import listdir from pathlib import Path -from typing import Optional +from typing import List, Optional from andromede.model.library import Library from andromede.model.parsing import parse_yaml_library @@ -32,9 +33,13 @@ class AntaresTimeSeriesImportError(Exception): pass -def input_models(model_path: Path) -> Library: - with model_path.open() as lib: - return resolve_library(parse_yaml_library(lib)) +def input_models(model_path: List[Path]) -> Library: + with model_path[0].open("r") as file: + lib = resolve_library(parse_yaml_library(file)) + for path in model_path[1:]: + with path.open("r") as file: + lib = resolve_library(parse_yaml_library(file), [lib]) + return lib def input_database(study_path: Path, timeseries_path: Optional[Path]) -> DataBase: @@ -50,13 +55,16 @@ def input_components(study_path: Path, model: Library) -> NetworkComponents: def main() -> None: parser = argparse.ArgumentParser() parser.add_argument( - "--model", type=Path, help="path to the model file, *.yml", required=True + "--study", type=Path, help="path to the root dirertory of the study" ) parser.add_argument( - "--study", type=Path, help="path to the study file, *.yml", required=True + "--models", nargs="+", type=Path, help="list of path to model file, *.yml" ) parser.add_argument( - "--timeseries", type=Path, help="path to the timeseries repertory" + "--component", type=Path, help="path to the component file, *.yml" + ) + parser.add_argument( + "--timeseries", type=Path, help="path to the timeseries dirertory" ) parser.add_argument( "--duration", type=int, help="duration of the simulation", default=1 @@ -67,16 +75,46 @@ def main() -> None: args = parser.parse_args() - models = input_models(args.model) - components = input_components(args.study, models) - consistency_check(components.components, models.models) + components = None + database = None + + if args.study: + if args.models or args.component or args.timeseries: + parser.error( + "--study flag can't be use with --models, --component and --timeseries" + ) + components_path = args.study / "input" / "components" / "components.yml" + timeseries_dir = args.study / "input" / "components" / "series" + model_paths = [ + args.study / "input" / "models" / file + for file in listdir(args.study / "input" / "models") + ] + + models = input_models(model_paths) + components = input_components(components_path, models) + consistency_check(components.components, models.models) + try: + database = input_database(components_path, timeseries_dir) + except UnboundLocalError: + raise AntaresTimeSeriesImportError( + f"An error occurred while importing time series. Are all timeseries files in {timeseries_dir} ?" + ) + + else: + if not args.models or not args.component: + parser.error("--models and --component must be entered") + + models = input_models(args.models) + components = input_components(args.component, models) + consistency_check(components.components, models.models) + + try: + database = input_database(args.component, args.timeseries) + except UnboundLocalError: + raise AntaresTimeSeriesImportError( + "An error occurred while importing time series. Did you correctly use the '--timeseries' parameter ?" + ) - try: - database = input_database(args.study, args.timeseries) - except UnboundLocalError: - raise AntaresTimeSeriesImportError( - "An error occurred while importing time series. Did you correctly use the '--timeseries' parameter ?" - ) network = build_network(components) for scenario in range(1, args.scenario + 1): diff --git a/src/andromede/model/resolve_library.py b/src/andromede/model/resolve_library.py index 0b80d191..1f9b4e13 100644 --- a/src/andromede/model/resolve_library.py +++ b/src/andromede/model/resolve_library.py @@ -60,6 +60,8 @@ def resolve_library( port_types.extend(lib.port_types.values()) port_types_dict = dict((p.id, p) for p in port_types) models = [_resolve_model(m, port_types_dict) for m in input_lib.models] + for lib in preloaded_libraries: + models.extend(lib.models.values()) return library(port_types, models) diff --git a/tests/unittests/data/components_for_thermal_cluster.yml b/tests/functional/input/components/components.yml similarity index 81% rename from tests/unittests/data/components_for_thermal_cluster.yml rename to tests/functional/input/components/components.yml index c477f351..5606c177 100644 --- a/tests/unittests/data/components_for_thermal_cluster.yml +++ b/tests/functional/input/components/components.yml @@ -13,7 +13,9 @@ #test file for command line execution #run : -#$ python src/andromede/main/main.py --model tests/unittests/data/lib_2.yml --study tests/unittests/data/components_for_thermal_cluster.yml --duration 3 --timeseries tests/unittests/data/ +#$ python src/andromede/main/main.py --models tests/functional/input/models/lib_1.yml tests/functional/input/models/lib_2.yml --component tests/functional/input/components/components.yml --duration 3 --timeseries tests/functional/input/components/series/ +# or +#$ python src/andromede/main/main.py --study tests/functional/ --duration 3 #expected value : #> 0 #> 72000 @@ -53,7 +55,7 @@ study: parameters: - name: demand type: timeseries - timeseries: demand-ts_2 + timeseries: demand-ts - id: S model: spillage parameters: diff --git a/tests/unittests/data/demand-ts_2.txt b/tests/functional/input/components/series/demand-ts.txt similarity index 100% rename from tests/unittests/data/demand-ts_2.txt rename to tests/functional/input/components/series/demand-ts.txt diff --git a/tests/unittests/data/lib_2.yml b/tests/functional/input/models/lib_1.yml similarity index 65% rename from tests/unittests/data/lib_2.yml rename to tests/functional/input/models/lib_1.yml index cf398567..b57e6da7 100644 --- a/tests/unittests/data/lib_2.yml +++ b/tests/functional/input/models/lib_1.yml @@ -21,48 +21,6 @@ library: models: - - - id: node - description: A basic balancing node model - ports: - - name: injection_port - type: flow - binding-constraints: - - name: balance - expression: sum_connections(injection_port.flow) = 0 - - - id: spillage - description: A basic spillage model - parameters: - - name: cost - time-dependent: false - scenario-dependent: false - variables: - - name: spillage - lower-bound: 0 - ports: - - name: injection_port - type: flow - port-field-definitions: - - port: injection_port - field: flow - definition: -spillage - objective: expec(sum(cost * spillage)) - - - id: demand - description: A basic fixed demand model - parameters: - - name: demand - time-dependent: true - scenario-dependent: true - ports: - - name: injection_port - type: flow - port-field-definitions: - - port: injection_port - field: flow - definition: -demand - - id: thermal-cluster-dhd parameters: - name: p_max diff --git a/tests/functional/input/models/lib_2.yml b/tests/functional/input/models/lib_2.yml new file mode 100644 index 00000000..722a71b1 --- /dev/null +++ b/tests/functional/input/models/lib_2.yml @@ -0,0 +1,64 @@ +# Copyright (c) 2024, RTE (https://www.rte-france.com) +# +# See AUTHORS.txt +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 +# +# This file is part of the Antares project. +library: + id: basic + description: Basic library + + port-types: + - id: flow + description: A port which transfers power flow + fields: + - name: flow + + models: + + + - id: node + description: A basic balancing node model + ports: + - name: injection_port + type: flow + binding-constraints: + - name: balance + expression: sum_connections(injection_port.flow) = 0 + + - id: spillage + description: A basic spillage model + parameters: + - name: cost + time-dependent: false + scenario-dependent: false + variables: + - name: spillage + lower-bound: 0 + ports: + - name: injection_port + type: flow + port-field-definitions: + - port: injection_port + field: flow + definition: -spillage + objective: expec(sum(cost * spillage)) + + - id: demand + description: A basic fixed demand model + parameters: + - name: demand + time-dependent: true + scenario-dependent: true + ports: + - name: injection_port + type: flow + port-field-definitions: + - port: injection_port + field: flow + definition: -demand \ No newline at end of file