diff --git a/docs/source/quick_start.rst b/docs/source/quick_start.rst index 12272620..aaa62d0f 100644 --- a/docs/source/quick_start.rst +++ b/docs/source/quick_start.rst @@ -97,9 +97,12 @@ solver. HiGHS is automatically available when you install Temoa and requires no Running Temoa ------------- -To run the model, a configuration (``config``) file is needed. An +To run the model, a configuration (``config``) file is needed. While an example config file called :code:`config_sample.toml` is available as a package resource -in :code:`temoa/tutorial_assets`. Running the model with a config file allows +in :code:`temoa/tutorial_assets`, it is not directly runnable on its own. The tutorial +flow also generates the SQLite database and copies :code:`mc_settings.csv` alongside it. +Users should follow the **temoa tutorial** command (see below) to obtain a fully runnable +setup. Running the model with a config file allows the user to (1) use a sqlite database for storing input and output data, (2) create a formatted Excel output file, (2) specify the solver to use, (3) return the log file produced during model execution, (4) return the lp file utilized by diff --git a/pyproject.toml b/pyproject.toml index d12fb368..0e4b3557 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -134,6 +134,10 @@ filterwarnings = [ "error::FutureWarning:tests.*", "error::RuntimeWarning:tests.*", "error::UserWarning:tests.*", + # Ignore SyntaxWarning from mpi-sppy (third-party package). + # These are caused by invalid escape sequences in regex strings within sputils.py. + # Mitigation should be removed once mpi-sppy is upgraded to a version where these are fixed (0.13.1+). + "ignore:invalid escape sequence:SyntaxWarning:mpisppy.utils.sputils", ] [tool.mypy] diff --git a/temoa/cli.py b/temoa/cli.py index fa8c8587..c57a5b6b 100644 --- a/temoa/cli.py +++ b/temoa/cli.py @@ -688,10 +688,13 @@ def tutorial( # Check for existing files and handle conflicts existing_files = [] + target_mc_settings = target_config.parent / 'mc_settings.csv' if target_config.exists(): existing_files.append(str(target_config)) if target_database.exists(): existing_files.append(str(target_database)) + if target_mc_settings.exists(): + existing_files.append(str(target_mc_settings)) if existing_files and not force: rich.print('[yellow]Tutorial files already exist:[/yellow]') diff --git a/temoa/extensions/method_of_morris/MM_README.md b/temoa/extensions/method_of_morris/MM_README.md index 74f30a70..f92a6010 100644 --- a/temoa/extensions/method_of_morris/MM_README.md +++ b/temoa/extensions/method_of_morris/MM_README.md @@ -34,15 +34,18 @@ relevant `config.toml` file which can then be run. ### Example: `morris_utopia` -1. Convert the `.sql` source file to a database. If you have the `morris_utopia.sql` file: +The files for this example must reside in the same directory as the extension code (`temoa/extensions/method_of_morris/`) because `morris.py` resolves them relative to its own path. + +1. **Prepare the database**: Obtain or create `morris_utopia.sql` and convert it to a SQLite database in the extension directory: ```bash + # From the temoa/extensions/method_of_morris/ directory: sqlite3 morris_utopia.sqlite < morris_utopia.sql ``` -2. Observe the markings (3 groups) in the `MMAnalysis` columns in `cost_variable` and `efficiency`. -3. Observe the `morris` configuration comments in the relevant config file (e.g., `morris_utopia.toml`). -4. Run the config as normal. +2. **Ensure the configuration file is present**: Place `morris_utopia.toml` in the same directory. +3. Observe the markings (3 groups) in the `MMAnalysis` columns in `cost_variable` and `efficiency`. +4. Run the example from the extension directory. 5. MM analysis is reported on screen and in 2 csv files for the objective and `co2` in the Outputs folder 6. The DB will contain updated values (tagged by scenario name and "dash run") in `output_objective` and `output_emissions` _only_ which might be of secondary value to the modeler. Other output tables are _not_ updated. diff --git a/temoa/extensions/monte_carlo/example_builds/scenario_analyzer.py b/temoa/extensions/monte_carlo/example_builds/scenario_analyzer.py index 2593ca8a..08b68894 100644 --- a/temoa/extensions/monte_carlo/example_builds/scenario_analyzer.py +++ b/temoa/extensions/monte_carlo/example_builds/scenario_analyzer.py @@ -11,19 +11,31 @@ scenario_name = 'Purple Onion' # must match config file # To run this example, ensure tutorial_database.sqlite is in your current directory. # You can generate it using: temoa tutorial +# IMPORTANT: You must also run the model to populate results before analyzing: +# temoa run tutorial_config.toml db_resource = 'tutorial_database.sqlite' if not Path(db_resource).exists(): raise FileNotFoundError( f"Database file '{db_resource}' not found. " - "Please run 'temoa tutorial' to create the required files." + "Please run 'temoa tutorial' to create the base files." ) with Connection(db_resource) as conn: cur = conn.cursor() + # Check if results exist before attempting to plot obj_values = cur.execute( - f"SELECT total_system_cost FROM output_objective WHERE scenario LIKE '{scenario_name}-%'" + "SELECT total_system_cost FROM output_objective WHERE scenario LIKE ?", + (f"{scenario_name}-%",) ).fetchall() + + if len(obj_values) == 0: + raise RuntimeError( + f"No results found for scenario '{scenario_name}-*' in '{db_resource}'. " + "Please run 'temoa run tutorial_config.toml' or run the tutorial model " + "to populate output_objective with results first." + ) + obj_values_tuple = tuple(t[0] for t in obj_values) plt.hist(obj_values_tuple, bins=int(sqrt(len(obj_values_tuple)))) diff --git a/temoa/tutorial_assets/config_sample.toml b/temoa/tutorial_assets/config_sample.toml index 755787e2..6b522212 100644 --- a/temoa/tutorial_assets/config_sample.toml +++ b/temoa/tutorial_assets/config_sample.toml @@ -59,30 +59,6 @@ cycle_count_limit = 100 # Use this to filter out very small cycles if needed cycle_length_limit = 1 -# ------------------------------------ -# SQLITE PERFORMANCE TUNING -# ------------------------------------ - -[sqlite] -# These settings improve database performance, especially for large-scale -# runs and myopic/MGA modes which perform many small writes. - -# journal_mode: WAL (Write-Ahead Logging) provides better concurrency and speed. -# Note: This creates sidecar files (-wal and -shm) during execution. -journal_mode = 'WAL' - -# synchronous: NORMAL reduces disk flushes while remaining safe against -# application-level crashes. -synchronous = 'NORMAL' - -# mmap_size: Memory-map the database file for faster reads (bytes). -# 8589934592 = 8GB -mmap_size = 8589934592 - -# cache_size: SQLite page cache size. Negative values specify size in KiB. -# -512000 = 500MiB -cache_size = -512000 - # ------------------------------------ # SOLVER # Solver Selection @@ -167,6 +143,30 @@ days_per_period = 365 # capacity value = flow out * reserve capacity derate reserve_margin = 'dynamic' +# ------------------------------------ +# SQLITE PERFORMANCE TUNING +# ------------------------------------ + +[sqlite] +# These settings improve database performance, especially for large-scale +# runs and myopic/MGA modes which perform many small writes. + +# journal_mode: WAL (Write-Ahead Logging) provides better concurrency and speed. +# Note: This creates sidecar files (-wal and -shm) during execution. +journal_mode = 'WAL' + +# synchronous: NORMAL reduces disk flushes while remaining safe against +# application-level crashes. +synchronous = 'NORMAL' + +# mmap_size: Memory-map the database file for faster reads (bytes). +# 8589934592 = 8GB +mmap_size = 8589934592 + +# cache_size: SQLite page cache size. Negative values specify size in KiB. +# -512000 = 500MiB +cache_size = -512000 + # --------------------------------------------------- # MODE OPTIONS # options below are mode-specific and will be ignored