• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

blue-marble / gridpath / 18023281822

25 Sep 2025 11:23PM UTC coverage: 89.043% (-0.01%) from 89.053%
18023281822

push

github

web-flow
Test with coverage on one parallel run only (#1296)

27687 of 31094 relevant lines covered (89.04%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.99
/tests/test_examples.py
1
# Copyright 2016-2025 Blue Marble Analytics LLC.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
import ast
1✔
16
import csv
1✔
17
import logging
1✔
18
import multiprocessing
1✔
19
import os
1✔
20
import pandas as pd
1✔
21
import platform
1✔
22
import sqlite3
1✔
23
import unittest
1✔
24

25
from gridpath import run_end_to_end, run_scenario, validate_inputs
1✔
26
from db import create_database
1✔
27
from db.common_functions import connect_to_database
1✔
28
from db.utilities import port_csvs_to_db, scenario
1✔
29

30
# Change directory to 'gridpath' directory, as that's what run_scenario.py
31
# expects; the rest of the global variables are relative paths from there
32
os.chdir(os.path.join(os.path.dirname(__file__), "..", "gridpath"))
1✔
33
EXAMPLES_DIRECTORY = os.path.join("..", "examples")
1✔
34
DB_NAME = "unittest_examples"
1✔
35
DB_PATH = f"../db/{DB_NAME}.db"
1✔
36
DB_SCHEMA = f"../db/db_schema.sql"
1✔
37
DATA_DIRECTORY = "../db/data"
1✔
38
CSV_PATH = "../db//csvs_test_examples"
1✔
39
SCENARIOS_CSV = os.path.join(CSV_PATH, "scenarios.csv")
1✔
40
TEST_SCENARIOS_CSV = "../tests/test_data/test_scenario_objective_function_values.csv"
1✔
41

42
# Platform check
43
LINUX = True if platform.system() == "Linux" else False
1✔
44
MACOS = True if platform.system() == "Darwin" else False
1✔
45
WINDOWS = True if platform.system() == "Windows" else False
1✔
46

47
# Python version
48
PYTHON_VERSION = platform.python_version()
1✔
49

50

51
class TestExamples(unittest.TestCase):
1✔
52
    """ """
53

54
    df = pd.read_csv(TEST_SCENARIOS_CSV, delimiter=",")
1✔
55
    df.set_index("test_scenario", inplace=True)
1✔
56

57
    def assertDictAlmostEqual(self, d1, d2, msg=None, places=7):
1✔
58
        # check if both inputs are dicts
59
        self.assertIsInstance(d1, dict, "First argument is not a dictionary")
1✔
60
        self.assertIsInstance(d2, dict, "Second argument is not a dictionary")
1✔
61

62
        # check if both inputs have the same keys
63
        self.assertEqual(d1.keys(), d2.keys())
1✔
64

65
        # check each key
66
        for key, value in d1.items():
1✔
67
            if isinstance(value, dict):
1✔
68
                self.assertDictAlmostEqual(d1[key], d2[key], places=places, msg=msg)
1✔
69
            else:
70
                self.assertAlmostEqual(d1[key], d2[key], places=places, msg=msg)
1✔
71

72
    def check_validation(self, test):
1✔
73
        """
74
        Check that validate inputs runs without errors, and that there
75
        are no validation issues recorded in the status_validation table
76
        :return:
77
        """
78

79
        # Check that test validation runs without errors
80
        validate_inputs.main(["--database", DB_PATH, "--scenario", test, "--quiet"])
1✔
81

82
        # Check that no validation issues are recorded in the db for the test
83
        expected_validations = []
1✔
84

85
        conn = connect_to_database(
1✔
86
            db_path=DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES
87
        )
88
        c = conn.cursor()
1✔
89
        validations = c.execute(
1✔
90
            """
91
            SELECT scenario_name FROM status_validation
92
            INNER JOIN
93
            (SELECT scenario_id, scenario_name FROM scenarios)
94
            USING (scenario_id)
95
            WHERE scenario_name = '{}'
96
            """.format(
97
                test
98
            )
99
        )
100
        actual_validations = validations.fetchall()
1✔
101
        conn.close()
1✔
102

103
        self.assertListEqual(expected_validations, actual_validations)
1✔
104

105
    def run_and_check_objective(
1✔
106
        self, scenario_name, expected_objective, solver=None, parallel=1
107
    ):
108
        """
109

110
        :param scenario_name: str, name of the test example
111
        :param expected_objective: float or dict, expected objective
112
        :param parallel: int, set to a number > 1 to test
113
            parallelization functionality
114
        :return:
115
        """
116

117
        args_to_pass = [
1✔
118
            "--database",
119
            DB_PATH,
120
            "--scenario",
121
            scenario_name,
122
            "--scenario_location",
123
            EXAMPLES_DIRECTORY,
124
            # "--log",
125
            # "--write_solver_files_to_logs_dir",
126
            # "--keepfiles",
127
            # "--symbolic",
128
            "--n_parallel_get_inputs",
129
            str(parallel),
130
            "--n_parallel_solve",
131
            str(parallel),
132
            "--quiet",
133
            "--mute_solver_output",
134
            "--testing",
135
        ]
136
        if solver is not None:
1✔
137
            args_to_pass.append("--solver")
×
138
            args_to_pass.append(solver)
×
139

140
        actual_objective = run_end_to_end.main(args_to_pass)
1✔
141

142
        expected_objective = objective_function_overwrite(
1✔
143
            scenario_name=scenario_name, starting_objective=expected_objective
144
        )
145

146
        # Check if we have a multiprocessing manager
147
        # If so, convert the manager proxy dictionary to a simple dictionary
148
        # to avoid errors
149
        # Done via copies to avoid broken pipe error
150
        if hasattr(multiprocessing, "managers"):
1✔
151
            if isinstance(actual_objective, multiprocessing.managers.DictProxy):
1✔
152
                # Make a dictionary from a copy of the objective
153
                actual_objective_copy = dict(actual_objective.copy())
×
154
                for subproblem in actual_objective.keys():
×
155
                    # If we have stages, make a dictionary form a copy of the
156
                    # stage dictionary for each subproblem
157
                    if isinstance(
×
158
                        actual_objective[subproblem], multiprocessing.managers.DictProxy
159
                    ):
160
                        stage_dict_copy = dict(actual_objective_copy[subproblem].copy())
×
161
                        # Reset the stage dictionary to the new simple
162
                        # dictionary object
163
                        actual_objective_copy[subproblem] = stage_dict_copy
×
164
                # Reset the objective to the new dictionary object
165
                actual_objective = actual_objective_copy
×
166

167
        # Uncomment this to save new objective function values
168
        df = pd.read_csv(TEST_SCENARIOS_CSV, delimiter=",")
1✔
169
        df.set_index("test_scenario", inplace=True)
1✔
170
        # Set dtype to 'object' so that we can have floats and dictionaries
171
        # in the column
172
        df["actual_objective"] = df["actual_objective"].astype("object")
1✔
173
        df.at[scenario_name, "actual_objective"] = actual_objective
1✔
174
        df.to_csv(TEST_SCENARIOS_CSV, index=True)
1✔
175

176
        if scenario_name == "test_new_solar_carbon_cap_dac":
1✔
177
            # This test is particularly sensitive to platform and
178
            # Python version, so we relax the precision of the test a bit
179
            # more
180
            places = -1
1✔
181
        else:
182
            places = 1
1✔
183

184
        self.assertDictAlmostEqual(expected_objective, actual_objective, places=places)
1✔
185

186
    @classmethod
1✔
187
    def setUpClass(cls):
1✔
188
        """
189
        Set up the testing database
190
        :return:
191
        """
192

193
        if os.path.exists(DB_PATH):
1✔
194
            os.remove(DB_PATH)
×
195

196
        create_database.main(
1✔
197
            [
198
                "--database",
199
                DB_PATH,
200
                "--db_schema",
201
                DB_SCHEMA,
202
                "--data_directory",
203
                DATA_DIRECTORY,
204
            ]
205
        )
206

207
        try:
1✔
208
            port_csvs_to_db.main(
1✔
209
                ["--database", DB_PATH, "--csv_location", CSV_PATH, "--quiet"]
210
            )
211
        except Exception as e:
×
212
            print(
×
213
                "Error encountered during population of testing database "
214
                "{}.db. Deleting database ...".format(DB_NAME)
215
            )
216
            logging.exception(e)
×
217
            os.remove(DB_PATH)
×
218

219
        try:
1✔
220
            scenario.main(
1✔
221
                ["--database", DB_PATH, "--csv_path", SCENARIOS_CSV, "--quiet"]
222
            )
223
        except Exception as e:
×
224
            print(
×
225
                "Error encountered during population of testing database "
226
                "{}.db. Deleting database ...".format(DB_NAME)
227
            )
228
            logging.exception(e)
×
229
            os.remove(DB_PATH)
×
230

231
    def validate_and_test_example_generic(
1✔
232
        self, scenario_name, solver=None, skip_validation=False
233
    ):
234
        # Use the expected objective column by default
235
        # Since most development happens on MacOS, the generic expected
236
        # objective column is set to the MacOS value
237
        column_to_use = "expected_objective"
1✔
238
        if MACOS and not pd.isnull(
1✔
239
            self.df.loc[scenario_name]["expected_objective_darwin"]
240
        ):
241
            column_to_use = "expected_objective_darwin"
×
242
        if WINDOWS and not pd.isnull(
1✔
243
            self.df.loc[scenario_name]["expected_objective_windows"]
244
        ):
245
            column_to_use = "expected_objective_windows"
×
246
        if LINUX and not pd.isnull(
1✔
247
            self.df.loc[scenario_name]["expected_objective_linux"]
248
        ):
249
            column_to_use = "expected_objective_linux"
1✔
250

251
        # Evaluate the objective function as a literal (as it is in
252
        # dictionary format stored as string in the CSV)
253
        # This is now done for all scenarios, even if they have no iterations
254
        # or multiple subproblem/stages
255
        objective = ast.literal_eval(self.df.loc[scenario_name][column_to_use])
1✔
256

257
        if not skip_validation:
1✔
258
            self.check_validation(scenario_name)
1✔
259
        self.run_and_check_objective(
1✔
260
            scenario_name=scenario_name, solver=solver, expected_objective=objective
261
        )
262

263
    def test_example_test(self):
1✔
264
        """
265
        Check validation and objective function value of "test" example
266
        :return:
267
        """
268
        scenario_name = "test"
1✔
269
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
270

271
    def test_example_test_no_overgen_allowed(self):
1✔
272
        """
273
        Check validation and objective function value of
274
        "test_no_overgen_allowed" example
275
        :return:
276
        """
277

278
        scenario_name = "test_no_overgen_allowed"
1✔
279
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
280

281
    def test_example_test_new_build_storage(self):
1✔
282
        """
283
        Check validation and objective function value of
284
        "test_new_build_storage" example
285
        :return:
286
        """
287

288
        scenario_name = "test_new_build_storage"
1✔
289
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
290

291
    def test_example_test_new_binary_build_storage(self):
1✔
292
        """
293
        Check validation and objective function value of
294
        "test_new_binary_build_storage" example
295
        :return:
296
        """
297
        scenario_name = "test_new_binary_build_storage"
1✔
298
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
299

300
    def test_example_test_new_build_storage_cumulative_min_max(self):
1✔
301
        """
302
        Check validation and objective function value of
303
        "test_new_build_storage_cumulative_min_max" example
304
        :return:
305
        """
306
        scenario_name = "test_new_build_storage_cumulative_min_max"
1✔
307
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
308

309
    def test_example_test_no_reserves(self):
1✔
310
        """
311
        Check validation and objective function value of
312
        "test_no_reserves" example
313
        :return:
314
        """
315
        scenario_name = "test_no_reserves"
1✔
316
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
317

318
    def test_example_test_w_hydro(self):
1✔
319
        """
320
        Check validation and objective function value of "test_w_hydro" example
321
        :return:
322
        """
323
        scenario_name = "test_w_hydro"
1✔
324
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
325

326
    def test_example_test_w_storage(self):
1✔
327
        """
328
        Check validation and objective function value of "test_w_storage" example
329
        :return:
330
        """
331
        scenario_name = "test_w_storage"
1✔
332
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
333

334
    def test_example_2horizons(self):
1✔
335
        """
336
        Check validation and objective function value of "2horizons" example
337
        :return:
338
        """
339
        scenario_name = "2horizons"
1✔
340
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
341

342
    def test_example_2horizons_w_hydro(self):
1✔
343
        """
344
        Check validation and objective function value of
345
        "2horizons_w_hydro" example
346
        :return:
347
        """
348
        scenario_name = "2horizons_w_hydro"
1✔
349
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
350

351
    def test_example_2horizons_w_hydro_and_nuclear_binary_availability(self):
1✔
352
        """
353
        Check validation and objective function value of
354
        "2horizons_w_hydro_and_nuclear_binary_availability" example
355

356
        NOTE: the objective function for this example is lower than that for
357
        the '2horizons_w_hydro' example because of the unrealistically high
358
        relative heat rate of the 'Nuclear' project relative to the gas
359
        projects; allowing binary availability for a must-run project
360
        actually allows lower-cost power when the nuclear plant is
361
        unavailable. We should probably re-think this example as part of a
362
        future more general revamp of the examples.
363

364
        :return:
365
        """
366
        scenario_name = "2horizons_w_hydro_and_nuclear_binary_availability"
1✔
367
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
368

369
    def test_example_2horizons_w_hydro_w_balancing_types(self):
1✔
370
        """
371
        Check validation and objective function value of
372
        "2horizons_w_hydro_w_balancing_types" example. The objective
373
        function of this example should be lower than that of the
374
        '2horizons_w_hydro' example, as the average hydro budget is the
375
        same across all timepoints, but the hydro balancing horizon is now
376
        longer.
377
        :return:
378
        """
379
        scenario_name = "2horizons_w_hydro_w_balancing_types"
1✔
380
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
381

382
    def test_example_2periods(self):
1✔
383
        """
384
        Check validation and objective function value of "2periods" example
385
        :return:
386
        """
387
        scenario_name = "2periods"
1✔
388
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
389

390
    def test_example_2periods_new_build(self):
1✔
391
        """
392
        Check validation and objective function value of "2periods_new_build" example
393
        """
394
        scenario_name = "2periods_new_build"
1✔
395
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
396

397
    def test_example_2periods_new_build_2zones(self):
1✔
398
        """
399
        Check validation and objective function value of
400
        "2periods_new_build_2zones" example
401
        :return:
402
        """
403
        scenario_name = "2periods_new_build_2zones"
1✔
404
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
405

406
    def test_example_2periods_new_build_2zones_new_build_transmission(self):
1✔
407
        """
408
        Check validation and objective function value of
409
        "2periods_new_build_2zones_new_build_transmission" example
410
        :return:
411
        """
412
        scenario_name = "2periods_new_build_2zones_new_build_transmission"
1✔
413
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
414

415
    def test_example_2periods_new_build_2zones_singleBA(self):
1✔
416
        """
417
        Check validation and objective function value of
418
        "2periods_new_build_2zones_singleBA"
419
        example
420
        :return:
421
        """
422
        scenario_name = "2periods_new_build_2zones_singleBA"
1✔
423
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
424

425
    def test_example_2periods_new_build_2zones_transmission(self):
1✔
426
        """
427
        Check validation and objective function value of
428
        "2periods_new_build_2zones_transmission" example
429
        :return:
430
        """
431
        scenario_name = "2periods_new_build_2zones_transmission"
1✔
432
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
433

434
    def test_example_2periods_new_build_2zones_transmission_w_losses(self):
1✔
435
        """
436
        Check validation and objective function value of
437
        "2periods_new_build_2zones_transmission_w_losses" example
438
        :return:
439
        """
440
        scenario_name = "2periods_new_build_2zones_transmission_w_losses"
1✔
441
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
442

443
    def test_example_2periods_new_build_2zones_transmission_w_losses_opp_dir(self):
1✔
444
        """
445
        Check validation and objective function value of
446
        "2periods_new_build_2zones_transmission_w_losses_opp_dir" example
447

448
        Note: this should be the same as the objective function for
449
        2periods_new_build_2zones_transmission_w_losses
450
        :return:
451
        """
452
        scenario_name = "2periods_new_build_2zones_transmission_w_losses_opp_dir"
1✔
453
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
454

455
    def test_example_2periods_new_build_rps(self):
1✔
456
        """
457
        Check validation and objective function value of
458
        "2periods_new_build_rps" example
459
        :return:
460
        """
461
        scenario_name = "2periods_new_build_rps"
1✔
462
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
463

464
    def test_example_2periods_new_build_rps_percent_target(self):
1✔
465
        """
466
        Check objective function value of
467
        "2periods_new_build_rps_percent_target" example
468
        This example should have the same objective function as
469
        test_example_2periods_new_build_rps, as its target is the same,
470
        but specified as percentage of load.
471
        :return:
472
        """
473
        scenario_name = "2periods_new_build_rps_percent_target"
1✔
474
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
475

476
    def test_example_2periods_new_build_cumulative_min_max(self):
1✔
477
        """
478
        Check validation and objective function value of
479
        "2periods_new_build_cumulative_min_max" example
480
        :return:
481
        """
482
        scenario_name = "2periods_new_build_cumulative_min_max"
1✔
483
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
484

485
    def test_example_single_stage_prod_cost(self):
1✔
486
        """
487
        Check validation and objective function values of
488
        "single_stage_prod_cost" example
489
        :return:
490
        """
491
        scenario_name = "single_stage_prod_cost"
1✔
492
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
493

494
    def test_example_single_stage_prod_cost_linked_subproblems(self):
1✔
495
        """
496
        Check objective function values of
497
        "single_stage_prod_cost_linked_subproblems" example
498
        :return:
499
        """
500
        scenario_name = "single_stage_prod_cost_linked_subproblems"
1✔
501
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
502

503
    def test_example_single_stage_prod_cost_linked_subproblems_w_hydro(self):
1✔
504
        """
505
        Check objective function values of
506
        "single_stage_prod_cost_linked_subproblems" example
507
        :return:
508
        """
509
        scenario_name = "single_stage_prod_cost_linked_subproblems_w_hydro"
1✔
510
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
511

512
    def test_example_multi_stage_prod_cost(self):
1✔
513
        """
514
        Check validation and objective function values of
515
        "multi_stage_prod_cost" example
516
        :return:
517
        """
518
        scenario_name = "multi_stage_prod_cost"
1✔
519
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
520

521
    def test_example_single_stage_prod_cost_cycle_select(self):
1✔
522
        """
523
        Check validation and objective function values of
524
        "single_stage_prod_cost_cycle_select" example. This example is the same as
525
        single_stage_prod_cost but the Coal and Gas_CCGT plants have mutually
526
        exclusive commitment in this example.
527
        """
528
        scenario_name = "single_stage_prod_cost_cycle_select"
1✔
529
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
530

531
    def test_example_multi_stage_prod_cost_parallel(self):
1✔
532
        """
533
        Check "multi_stage_prod_cost" example running subproblems in parallel
534
        (getting inputs and optimization)
535
        :return:
536
        """
537
        run_end_to_end.main(
1✔
538
            [
539
                "--database",
540
                DB_PATH,
541
                "--scenario",
542
                "multi_stage_prod_cost",
543
                "--scenario_location",
544
                EXAMPLES_DIRECTORY,
545
                # "--log",
546
                # "--write_solver_files_to_logs_dir",
547
                # "--keepfiles",
548
                # "--symbolic",
549
                "--n_parallel_get_inputs",
550
                "3",
551
                "--n_parallel_solve",
552
                "3",
553
                "--quiet",
554
                "--mute_solver_output",
555
                "--testing",
556
            ]
557
        )
558

559
    def test_example_multi_stage_prod_cost_w_hydro(self):
1✔
560
        """
561
        Check validation and objective function values of
562
        "multi_stage_prod_cost_w_hydro"
563
        example
564
        :return:
565
        """
566
        scenario_name = "multi_stage_prod_cost_w_hydro"
1✔
567
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
568

569
    def test_example_multi_stage_prod_cost_linked_subproblems(self):
1✔
570
        """
571
        Check validation and objective function values of
572
        "multi_stage_prod_cost_linked_subproblems" example
573
        :return:
574
        """
575
        scenario_name = "multi_stage_prod_cost_linked_subproblems"
1✔
576
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
577

578
    def test_example_2periods_gen_lin_econ_retirement(self):
1✔
579
        """
580
        Check validation and objective function value of
581
        "2periods_gen_lin_econ_retirement"
582
        example
583
        :return:
584
        """
585
        scenario_name = "2periods_gen_lin_econ_retirement"
1✔
586
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
587

588
    def test_example_2periods_gen_bin_econ_retirement(self):
1✔
589
        """
590
        Check validation and objective function value of
591
        "2periods_gen_bin_econ_retirement"
592
        example
593
        :return:
594
        """
595
        scenario_name = "2periods_gen_bin_econ_retirement"
1✔
596
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
597

598
    def test_example_variable_gen_reserves(self):
1✔
599
        """
600
        Check validation and objective function value of
601
        "variable_gen_reserves"
602
        example; this example requires a non-linear solver
603
        :return:
604
        """
605
        scenario_name = "test_variable_gen_reserves"
1✔
606
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
607

608
    def test_example_2periods_new_build_rps_variable_reserves(self):
1✔
609
        """
610
        Check validation and objective function value of
611
        "2periods_new_build_rps_variable_reserves" example
612
        :return:
613
        """
614
        scenario_name = "2periods_new_build_rps_variable_reserves"
1✔
615
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
616

617
    def test_example_2periods_new_build_rps_variable_reserves_subhourly_adj(self):
1✔
618
        """
619
        Check validation and objective function value of
620
        "2periods_new_build_rps_variable_reserves_subhourly_adj" example
621
        :return:
622
        """
623
        scenario_name = "2periods_new_build_rps_variable_reserves_subhourly_adj"
1✔
624
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
625

626
    def test_example_test_ramp_up_constraints(self):
1✔
627
        """
628
        Check validation and objective function value of
629
        "test_ramp_up_constraints" example
630
        :return:
631
        """
632
        scenario_name = "test_ramp_up_constraints"
1✔
633
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
634

635
    def test_example_test_ramp_up_and_down_constraints(self):
1✔
636
        """
637
        Check validation and objective function value of
638
        "test_ramp_up_and_down_constraints"
639
        example;
640
        :return:
641
        """
642
        scenario_name = "test_ramp_up_and_down_constraints"
1✔
643
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
644

645
    def test_example_2periods_new_build_rps_w_rps_ineligible_storage(self):
1✔
646
        """
647
        Check validation and objective function value of
648
        "2periods_new_build_rps_w_rps_ineligible_storage" example
649
        :return:
650
        """
651
        scenario_name = "2periods_new_build_rps_w_rps_ineligible_storage"
1✔
652
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
653

654
    def test_example_2periods_new_build_rps_w_rps_eligible_storage(self):
1✔
655
        """
656
        Check validation and objective function value of
657
        "2periods_new_build_rps_w_rps_eligible_storage" example
658
        :return:
659
        """
660
        scenario_name = "2periods_new_build_rps_w_rps_eligible_storage"
1✔
661
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
662

663
    def test_example_test_new_solar(self):
1✔
664
        """
665
        Check validation and objective function value of
666
        "test_new_solar" example
667
        :return:
668
        """
669
        scenario_name = "test_new_solar"
1✔
670
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
671

672
    def test_example_test_new_binary_solar(self):
1✔
673
        """
674
        Check validation and objective function value of
675
        "test_new_binary_solar" example
676
        :return:
677
        """
678
        scenario_name = "test_new_binary_solar"
1✔
679
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
680

681
    def test_example_test_new_solar_carbon_cap(self):
1✔
682
        """
683
        Check validation and objective function value of
684
        "test_new_solar_carbon_cap" example
685
        :return:
686
        """
687
        scenario_name = "test_new_solar_carbon_cap"
1✔
688
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
689

690
    def test_example_test_new_solar_carbon_cap_2zones_tx(self):
1✔
691
        """
692
        Check validation and objective function value of
693
        "test_new_solar_carbon_cap_2zones_tx" example
694
        :return:
695
        """
696
        scenario_name = "test_new_solar_carbon_cap_2zones_tx"
1✔
697
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
698

699
    def test_example_test_new_solar_carbon_cap_2zones_dont_count_tx(self):
1✔
700
        """
701
        Check validation and objective function value of
702
        "test_new_solar_carbon_cap_2zones_dont_count_tx" example
703
        :return:
704
        """
705
        scenario_name = "test_new_solar_carbon_cap_2zones_dont_count_tx"
1✔
706
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
707

708
    def test_example_test_new_solar_carbon_tax(self):
1✔
709
        """
710
        Check validation and objective function value of
711
        "test_new_solar_carbon_tax" example
712
        :return:
713
        """
714
        scenario_name = "test_new_solar_carbon_tax"
1✔
715
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
716

717
    def test_example_2periods_new_build_simple_prm(self):
1✔
718
        """
719
        Check validation and objective function value of
720
        "2periods_new_build_simple_prm"
721
        example
722
        :return:
723
        """
724
        scenario_name = "2periods_new_build_simple_prm"
1✔
725
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
726

727
    def test_example_2periods_new_build_simple_prm_w_energy_only(self):
1✔
728
        """
729
        Check validation and objective function value of
730
        "2periods_new_build_simple_prm"
731
        example
732
        :return:
733
        """
734
        scenario_name = "2periods_new_build_simple_prm_w_energy_only"
1✔
735
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
736

737
    def test_example_2periods_new_build_simple_prm_w_energy_only_deliv_cap_limit(self):
1✔
738
        """
739
        Check validation and objective function value of
740
        "2periods_new_build_simple_prm"
741
        example
742
        :return:
743
        """
744
        scenario_name = "2periods_new_build_simple_prm_w_energy_only_deliv_cap_limit"
1✔
745
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
746

747
    def test_example_2periods_new_build_local_capacity(self):
1✔
748
        """
749
        Check validation and objective function value of
750
        "2periods_new_build_local_capacity"
751
        example
752
        :return:
753
        """
754
        scenario_name = "2periods_new_build_local_capacity"
1✔
755
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
756

757
    def test_example_test_tx_dcopf(self):
1✔
758
        """
759
        Check validation and objective function value of
760
        "test_tx_dcopf" example
761
        :return:
762
        """
763
        scenario_name = "test_tx_dcopf"
1✔
764
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
765

766
    def test_example_test_tx_simple(self):
1✔
767
        """
768
        Check validation and objective function value of
769
        "test_tx_simple" example
770
        :return:
771
        """
772
        scenario_name = "test_tx_simple"
1✔
773
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
774

775
    def test_example_test_tx_simple_tmp_emissions(self):
1✔
776
        """
777
        Check validation and objective function value of
778
        "test_tx_simple_tmp_emissions" example
779
        :return:
780
        """
781
        scenario_name = "test_tx_simple_tmp_emissions"
1✔
782
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
783

784
    def test_example_test_tx_simple_additive(self):
1✔
785
        """
786
        Check validation and objective function value of
787
        "test_tx_simple_additive" example
788
        :return:
789
        """
790
        scenario_name = "test_tx_simple_additive"
1✔
791
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
792

793
    def test_example_test_startup_shutdown_rates(self):
1✔
794
        """
795
        Check validation and objective function value of
796
        "test_startup_shutdown_rates"
797
        example
798
        :return:
799
        """
800
        scenario_name = "test_startup_shutdown_rates"
1✔
801
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
802

803
    def test_no_fuels(self):
1✔
804
        """
805
        Check validation and objective function value of "test_no_fuels"
806
        example
807
        :return:
808
        """
809
        scenario_name = "test_no_fuels"
1✔
810
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
811

812
    def test_variable_om_curves(self):
1✔
813
        """
814
        Check validation and objective function value of
815
        "test_variable_om_curves"
816
        example
817
        :return:
818
        """
819
        scenario_name = "test_variable_om_curves"
1✔
820
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
821

822
    def test_aux_cons(self):
1✔
823
        """
824
        Check validation and objective function value of
825
        "test_aux_cons" example
826

827
        Note: the objective function value is lower than that for the "test"
828
        example because the auxiliary consumption results in less
829
        overgeneration and therefore lower overgeneration penalty.
830
        """
831
        scenario_name = "test_aux_cons"
1✔
832
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
833

834
    def test_example_test_w_lf_down_percent_req(self):
1✔
835
        """
836
        Check validation and objective function value of
837
        "test_w_lf_down_percent_req" example
838
        :return:
839
        """
840
        scenario_name = "test_w_lf_down_percent_req"
1✔
841
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
842

843
    def test_example_2periods_new_build_capgroups(self):
1✔
844
        """
845
        Check validation and objective function value of
846
        "test_example_2periods_new_build_capgroups" example
847
        """
848
        scenario_name = "2periods_new_build_capgroups"
1✔
849
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
850

851
    def test_example_test_markets(self):
1✔
852
        """
853
        Check validation and objective function value of "test" example
854
        :return:
855
        """
856
        scenario_name = "test_markets"
1✔
857
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
858

859
    def test_example_2periods_new_build_horizon_energy_target(self):
1✔
860
        """
861
        Check validation and objective function value of
862
        "test_example_2periods_new_build_horizon_energy_target" example
863
        :return:
864
        """
865
        scenario_name = "2periods_new_build_horizon_energy_target"
1✔
866
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
867

868
    def test_example_2periods_new_build_horizon_energy_target_halfyear(self):
1✔
869
        """
870
        Check validation and objective function value of
871
        "2periods_new_build_horizon_energy_target_halfyear" example
872
        :return:
873
        """
874
        scenario_name = "2periods_new_build_horizon_energy_target_halfyear"
1✔
875
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
876

877
    def test_example_test_new_build_gen_var_stor_hyb(self):
1✔
878
        """
879
        Check validation and objective function value of
880
        "test_new_build_gen_var_stor_hyb" example
881
        :return:
882
        """
883
        scenario_name = "test_new_build_gen_var_stor_hyb"
1✔
884
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
885

886
    def test_example_test_carbon_tax_allowance(self):
1✔
887
        """
888
        Check validation and objective function value of
889
        "test_carbon_tax_allowance" example
890
        :return:
891
        """
892
        scenario_name = "test_carbon_tax_allowance"
1✔
893
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
894

895
    def test_example_test_min_max_build_trans(self):
1✔
896
        """
897
        Check validation and objective function value of
898
        "test_min_max_build_trans" example
899
        :return:
900
        """
901
        scenario_name = "test_min_max_build_trans"
1✔
902
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
903

904
    def test_example_2periods_new_build_2zones_transmission_Tx1halfavail(self):
1✔
905
        """
906
        Check validation and objective function value of
907
        "2periods_new_build_2zones_transmission_Tx1halfavail" example
908
        :return:
909
        """
910
        scenario_name = "2periods_new_build_2zones_transmission_Tx1halfavail"
1✔
911
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
912

913
    def test_example_2periods_new_build_2zones_transmission_Tx1halfavailmonthly(self):
1✔
914
        """
915
        Check validation and objective function value of
916
        "2periods_new_build_2zones_transmission_Tx1halfavail" example
917
        :return:
918
        """
919
        scenario_name = "2periods_new_build_2zones_transmission_Tx1halfavailmonthly"
1✔
920
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
921

922
    def test_example_test_cheap_fuel_blend(self):
1✔
923
        """
924
        Check validation and objective function value of "test_cheap_fuel_blend" example
925
        :return:
926
        """
927
        scenario_name = "test_cheap_fuel_blend"
1✔
928
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
929

930
    def test_example_test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend(self):
1✔
931
        """
932
        Check validation and objective function value of
933
        "test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend" example
934
        :return:
935
        """
936
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_low_carbon_fuel_blend"
1✔
937
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
938

939
    def test_example_test_cheap_fuel_blend_w_limit(self):
1✔
940
        """
941
        Check validation and objective function value of
942
        "test_cheap_fuel_blend_w_limit" example
943
        :return:
944
        """
945
        scenario_name = "test_cheap_fuel_blend_w_limit"
1✔
946
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
947

948
    def test_example_test_new_solar_fuel_burn_limit(self):
1✔
949
        """
950
        Check validation and objective function value of
951
        "test_new_solar_fuel_burn_limit" example. Inputs set up so that this should
952
        be the same as the "test_new_solar_carbon_cap" example.
953
        :return:
954
        """
955
        scenario_name = "test_new_solar_fuel_burn_limit"
1✔
956
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
957

958
    def test_example_test_new_solar_fuel_burn_limit_relative(self):
1✔
959
        """
960
        Check validation and objective function value of
961
        "test_new_solar_fuel_burn_limit_relative" example. Inputs set up so that this
962
        should be the same as the "test_new_solar_fuel_burn_limit" example.
963
        :return:
964
        """
965
        scenario_name = "test_new_solar_fuel_burn_limit_relative"
1✔
966
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
967

968
    def test_test_w_solver_options(self):
1✔
969
        """
970
        Check validation and objective function value of "test_w_solver_options" example
971
        :return:
972
        """
973
        scenario_name = "test_w_solver_options"
1✔
974
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
975

976
    def test_example_test_carbon_tax_allowance_with_different_fuel_groups(self):
1✔
977
        """
978
        Check validation and objective function value of
979
        "test_carbon_tax_allowance_with_different_fuel_groups" example
980
        :return:
981
        """
982
        scenario_name = "test_carbon_tax_allowance_with_different_fuel_groups"
1✔
983
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
984

985
    def test_performance_standard(self):
1✔
986
        """
987
        Check validation and objective function value of "test_performance_standard" example
988
        :return:
989
        """
990
        scenario_name = "test_performance_standard"
1✔
991
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
992

993
    def test_tx_flow(self):
1✔
994
        """
995
        Check validation and objective function value of
996
        "test_tx_flow" example
997
        :return:
998
        """
999
        scenario_name = "test_tx_flow"
1✔
1000
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1001

1002
    def test_example_test_new_solar_reserve_prj_contribution(self):
1✔
1003
        """
1004
        Check validation and objective function value of
1005
        "test_reserve_prj_contribution" example.
1006
        This example is based on "test_new_solar" with the only difference, the LF UP
1007
        requirement ID
1008
        :return:
1009
        """
1010
        scenario_name = "test_new_solar_reserve_prj_contribution"
1✔
1011
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1012

1013
    def test_test_new_solar_carbon_cap_2zones_tx_hydrogen_prod(self):
1✔
1014
        """
1015
        Check validation and objective function value of
1016
        "test_reserve_prj_contribution" example.
1017
        This example is based on "test_new_solar" with the only difference, the LF UP
1018
        requirement ID
1019
        :return:
1020
        """
1021
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_hydrogen_prod"
1✔
1022
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1023

1024
    def test_test_new_solar_carbon_cap_2zones_tx_hydrogen_prod_new(self):
1✔
1025
        """
1026
        Check validation and objective function value of
1027
        "test_reserve_prj_contribution" example.
1028
        This example is based on "test_new_solar" with the only difference, the LF UP
1029
        requirement ID
1030
        :return:
1031
        """
1032
        scenario_name = "test_new_solar_carbon_cap_2zones_tx_hydrogen_prod_new"
1✔
1033
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1034

1035
    def test_example_test_new_solar_carbon_cap_dac(self):
1✔
1036
        """
1037
        Check validation and objective function value of
1038
        "test_new_solar_carbon_cap_dac" example.
1039

1040
        Note that the same version of Cbc (v2.10.12) produces a slightly
1041
        different objective function for this problem on Windows/Linux than on
1042
        Mac as of Python v3.12.
1043
        :return:
1044
        """
1045
        scenario_name = "test_new_solar_carbon_cap_dac"
1✔
1046
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1047

1048
    def test_example_test_cap_factor_limits(self):
1✔
1049
        """
1050
        Check validation and objective function value of "test" example
1051
        :return:
1052
        """
1053
        scenario_name = "test_cap_factor_limits"
1✔
1054
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1055

1056
    def test_example_multi_stage_prod_cost_w_markets(self):
1✔
1057
        """
1058
        Check validation and objective function values of
1059
        "multi_stage_prod_cost_w_markets" example
1060
        :return:
1061
        """
1062
        scenario_name = "multi_stage_prod_cost_w_markets"
1✔
1063
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1064

1065
    def test_example_test_supplemental_firing(self):
1✔
1066
        """
1067
        Check validation and objective function value of "test_supplemental_firing" example
1068
        :return:
1069
        """
1070
        scenario_name = "test_supplemental_firing"
1✔
1071
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1072

1073
    def test_example_test_tx_capacity_groups(self):
1✔
1074
        """
1075
        Check validation and objective function value of
1076
        "test_tx_capacity_groups" example
1077
        :return:
1078
        """
1079
        scenario_name = "test_tx_capacity_groups"
1✔
1080
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1081

1082
    def test_example_2periods_new_build_fin_lifetime(self):
1✔
1083
        """
1084
        Check validation and objective function value of
1085
        "2periods_new_build_fin_lifetime" example. Same as "2periods_new_build" but
1086
        with shorter financial lifetimes and some fixed costs. Cost is lower because
1087
        the same payment is made fewer times.
1088
        """
1089
        scenario_name = "2periods_new_build_fin_lifetime"
1✔
1090
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1091

1092
    def test_example_2periods_new_build_cumulative_and_vintage_min_max(self):
1✔
1093
        """
1094
        Check validation and objective function value of
1095
        "2periods_new_build_cumulative_and_vintage_min_max" example. It is the same
1096
        as 2periods_new_build_cumulative_and_min_max but with a max in 2020 for the
1097
        CCGT to force early build and a min on the CT in 2030 to force more build.
1098

1099
        :return:
1100
        """
1101
        scenario_name = "2periods_new_build_cumulative_and_vintage_min_max"
1✔
1102
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1103

1104
    def test_example_test_w_storage_w_soc_penalty(self):
1✔
1105
        """
1106
        Check validation and objective function value of "test_w_storage_w_soc_penalty"
1107
        example
1108
        :return:
1109
        """
1110
        scenario_name = "test_w_storage_w_soc_penalty"
1✔
1111
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1112

1113
    def test_example_test_w_storage_w_soc_last_tmp_penalty(self):
1✔
1114
        """
1115
        Check validation and objective function value of "test_w_storage_w_soc_penalty"
1116
        example
1117
        :return:
1118
        """
1119
        scenario_name = "test_w_storage_w_soc_last_tmp_penalty"
1✔
1120
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1121

1122
    def test_example_test_new_solar_itc(self):
1✔
1123
        """
1124
        Check validation and objective function value of
1125
        "test_new_solar_itc" example
1126
        :return:
1127
        """
1128
        scenario_name = "test_new_solar_itc"
1✔
1129
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1130

1131
    def test_example_test_new_build_storage_itc(self):
1✔
1132
        """
1133
        Check validation and objective function value of
1134
        "test_new_build_storage" example
1135
        :return:
1136
        """
1137
        scenario_name = "test_new_build_storage_itc"
1✔
1138
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1139

1140
    def test_example_2periods_new_build_simple_prm_2loadzones(self):
1✔
1141
        """
1142
        Check validation and objective function value of
1143
        "2periods_new_build_simple_prm_2loadzones"
1144
        example
1145
        :return:
1146
        """
1147
        scenario_name = "2periods_new_build_simple_prm_2loadzones"
1✔
1148
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1149

1150
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers(self):
1✔
1151
        """
1152
        Check validation and objective function value of
1153
        "2periods_new_build_simple_prm_w_transfers"
1154
        example
1155
        :return:
1156
        """
1157
        scenario_name = "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers"
1✔
1158
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1159

1160
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs(
1✔
1161
        self,
1162
    ):
1163
        """
1164
        Check validation and objective function value of
1165
        "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs"
1166
        example
1167
        :return:
1168
        """
1169
        scenario_name = (
1✔
1170
            "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_costs"
1171
        )
1172
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1173

1174
    def test_example_test_w_flex_load(self):
1✔
1175
        """
1176
        Check validation and objective function value of "test_w_storage" example
1177
        :return:
1178
        """
1179
        scenario_name = "test_w_flex_load"
1✔
1180
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1181

1182
    def test_example_test_new_solar_w_relative_capacity_instead_of_potential(self):
1✔
1183
        """
1184
        Check validation and objective function value of
1185
        "test_new_solar" example
1186
        :return:
1187
        """
1188
        scenario_name = "test_new_solar_w_relative_capacity_instead_of_potential"
1✔
1189
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1190

1191
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates(self):
1✔
1192
        """
1193
        Check validation and objective function value of
1194
        "2periods_new_build_2zones_transmission_w_hurdle_rates" example
1195
        :return:
1196
        """
1197
        scenario_name = "2periods_new_build_2zones_transmission_w_hurdle_rates"
1✔
1198
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1199

1200
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint(
1✔
1201
        self,
1202
    ):
1203
        """
1204
        Check validation and objective function value of
1205
        "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint" example
1206
        :return:
1207
        """
1208
        scenario_name = (
1✔
1209
            "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint"
1210
        )
1211
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1212

1213
    def test_example_2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period(
1✔
1214
        self,
1215
    ):
1216
        """
1217
        Check validation and objective function value of
1218
        "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period" example
1219
        :return:
1220
        """
1221
        scenario_name = "2periods_new_build_2zones_transmission_w_hurdle_rates_by_timepoint_and_period"
1✔
1222
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1223

1224
    def test_example_2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_subsidies(
1✔
1225
        self,
1226
    ):
1227
        """
1228
        Check validation and objective function value of
1229
        "test_new_solar" example
1230
        :return:
1231
        """
1232
        scenario_name = (
1✔
1233
            "2periods_new_build_simple_prm_2loadzones_newtx_w_transfers_w_subsidies"
1234
        )
1235
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1236

1237
    def test_example_test_new_build_storage_itc_single_superperiod(self):
1✔
1238
        """
1239
        Check validation and objective function value of
1240
        "test_new_build_storage_itc_single_superperiodself" example
1241
        :return:
1242
        """
1243
        scenario_name = "test_new_build_storage_itc_single_superperiod"
1✔
1244
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1245

1246
    def test_incomplete_only(self):
1✔
1247
        """
1248
        Check that the "incomplete only" functionality works with no errors.
1249
        :return:
1250
        """
1251
        actual_objective = run_scenario.main(
1✔
1252
            [
1253
                "--scenario",
1254
                "test",
1255
                "--scenario_location",
1256
                EXAMPLES_DIRECTORY,
1257
                "--quiet",
1258
                "--mute_solver_output",
1259
                "--incomplete_only",
1260
            ]
1261
        )
1262

1263
    def test_example_test_w_storage_starting_soc(self):
1✔
1264
        """
1265
        Check validation and objective function value of
1266
        "test_w_storage_starting_soc" example
1267
        :return:
1268
        """
1269
        scenario_name = "test_w_storage_starting_soc"
1✔
1270
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1271

1272
    def test_example_test_w_nonfuel_emissions(self):
1✔
1273
        """
1274
        Check validation and objective function value of "test" example
1275
        :return:
1276
        """
1277
        scenario_name = "test_w_nonfuel_emissions"
1✔
1278
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1279

1280
    def test_example_test_new_solar_carbon_credits(self):
1✔
1281
        """
1282
        Check validation and objective function value of
1283
        "test_new_solar_carbon_credits" example
1284
        :return:
1285
        """
1286
        scenario_name = "test_new_solar_carbon_credits"
1✔
1287
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1288

1289
    def test_performance_standard_carbon_credits(self):
1✔
1290
        """
1291
        Check validation and objective function value of "test_performance_standard" example
1292
        :return:
1293
        """
1294
        scenario_name = "test_performance_standard_carbon_credits"
1✔
1295
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1296

1297
    def test_example_test_new_solar_carbon_tax_w_carbon_credits(self):
1✔
1298
        """
1299
        Check validation and objective function value of
1300
        "test_new_solar_carbon_tax_w_carbon_credits" example
1301
        :return:
1302
        """
1303
        scenario_name = "test_new_solar_carbon_tax_w_carbon_credits"
1✔
1304
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1305

1306
    def test_example_test_new_solar_carbon_credits_w_sell(self):
1✔
1307
        """
1308
        Check validation and objective function value of
1309
        "test_new_solar_carbon_credits_w_sell" example
1310
        The carbon credit price must be set higher than the cost of USE in this
1311
        example to incentivize the project to not run and generate credits.
1312
        :return:
1313
        """
1314
        scenario_name = "test_new_solar_carbon_credits_w_sell"
1✔
1315
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1316

1317
    def test_test_performance_standard_carbon_credits_w_cap_no_credits_mapping(self):
1✔
1318
        """
1319
        Check validation and objective function value of
1320
        "test_performance_standard_carbon_credits_w_cap_no_credits_mapping" example
1321
        :return:
1322
        """
1323
        scenario_name = (
1✔
1324
            "test_performance_standard_carbon_credits_w_cap_no_credits_mapping"
1325
        )
1326
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1327

1328
    def test_test_new_solar_carbon_credits_w_buy(self):
1✔
1329
        """
1330
        Check validation and objective function value of "test_new_solar_carbon_credits_w_buy" example
1331
        :return:
1332
        """
1333
        scenario_name = "test_new_solar_carbon_credits_w_buy"
1✔
1334
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1335

1336
    def test_test_new_solar_carbon_credits_w_buy_and_sell(self):
1✔
1337
        """
1338
        Check validation and objective function value of "test_new_solar_carbon_credits_w_buy_and_sell" example
1339
        :return:
1340
        """
1341
        scenario_name = "test_new_solar_carbon_credits_w_buy_and_sell"
1✔
1342
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1343

1344
    def test_example_single_stage_prod_cost_w_spinup_lookahead(self):
1✔
1345
        """
1346
        Check validation and objective function values of
1347
        "single_stage_prod_cost_w_spinup_lookahead" example
1348
        :return:
1349
        """
1350
        scenario_name = "single_stage_prod_cost_w_spinup_lookahead"
1✔
1351
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1352

1353
    def test_example_test_tx_targets_max(self):
1✔
1354
        """
1355
        Check validation and objective function value of
1356
        "test_example_test_tx_targets_max"
1357
        example
1358
        :return:
1359
        """
1360
        scenario_name = "test_tx_targets_max"
1✔
1361
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1362

1363
    def test_example_ra_toolkit_monte_carlo(self):
1✔
1364
        """
1365
        Check validation and objective function values of
1366
        "ra_toolkit_monte_carlo" example
1367
        :return:
1368
        """
1369
        scenario_name = "ra_toolkit_monte_carlo"
1✔
1370
        self.validate_and_test_example_generic(
1✔
1371
            scenario_name=scenario_name, skip_validation=True
1372
        )
1373

1374
    def test_example_ra_toolkit_sync(self):
1✔
1375
        """
1376
        Check validation and objective function values of
1377
        "ra_toolkit_sync" example
1378
        :return:
1379
        """
1380
        scenario_name = "ra_toolkit_sync"
1✔
1381
        self.validate_and_test_example_generic(
1✔
1382
            scenario_name=scenario_name, skip_validation=True
1383
        )
1384

1385
    def test_example_2periods_nuclear_var_cost_by_period_same(self):
1✔
1386
        """
1387
        Check validation and objective function value of "2periods_nuclear_var_cost_by_period_same" example
1388
        :return:
1389
        """
1390
        scenario_name = "2periods_nuclear_var_cost_by_period_same"
1✔
1391
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1392

1393
    def test_example_2periods_nuclear_var_cost_by_period_diff(self):
1✔
1394
        """
1395
        Check validation and objective function value of
1396
        "2periods_nuclear_var_cost_by_period_diff" example
1397
        :return:
1398
        """
1399
        scenario_name = "2periods_nuclear_var_cost_by_period_diff"
1✔
1400
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1401

1402
    def test_example_ra_toolkit_sync_single_year(self):
1✔
1403
        """
1404
        Check validation and objective function values of
1405
        "ra_toolkit_sync_single_year" example
1406
        :return:
1407
        """
1408
        scenario_name = "ra_toolkit_sync_single_year"
1✔
1409
        self.validate_and_test_example_generic(
1✔
1410
            scenario_name=scenario_name, skip_validation=True
1411
        )
1412

1413
    def test_test_performance_standard_power(self):
1✔
1414
        """
1415
        Check validation and objective function values of "test_performance_standard_power" example
1416
        :return:
1417
        """
1418
        scenario_name = "test_performance_standard_power"
1✔
1419
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1420

1421
    def test_test_performance_standard_both(self):
1✔
1422
        """
1423
        Check validation and objective function values of "test_performance_standard_both" example
1424
        :return:
1425
        """
1426
        scenario_name = "test_performance_standard_both"
1✔
1427
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1428

1429
    def test_test_new_instantaneous_penetration(self):
1✔
1430
        """
1431
        Check validation and objective function value of "test_new_instantaneous_penetration" example
1432
        :return:
1433
        """
1434

1435
        scenario_name = "test_new_instantaneous_penetration"
1✔
1436
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1437

1438
    def test_hydro_system_exog_elev(self):
1✔
1439
        """
1440
        Check validation and objective function value of "hydro_system" example
1441
        :return:
1442
        """
1443

1444
        scenario_name = "hydro_system_exog_elev"
1✔
1445
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1446

1447
    def test_hydro_system_exog_elev_w_travel_time(self):
1✔
1448
        """
1449
        Check validation and objective function value of "hydro_system" example
1450
        :return:
1451
        """
1452

1453
        scenario_name = "hydro_system_exog_elev_w_travel_time"
1✔
1454
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1455

1456
    def test_test_tx_flow_w_simflow(self):
1✔
1457
        """
1458
        Check validation and objective function value of "test_tx_flow_w_simflow" example
1459
        :return:
1460
        """
1461

1462
        scenario_name = "test_tx_flow_w_simflow"
1✔
1463
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1464

1465
    def test_example_ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile(
1✔
1466
        self,
1467
    ):
1468
        """
1469
        Check validation and objective function values of
1470
        "ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile" example
1471
        :return:
1472
        """
1473
        scenario_name = "ra_toolkit_sync_single_year_w_hydro_instead_of_weather_profile"
1✔
1474
        self.validate_and_test_example_generic(
1✔
1475
            scenario_name=scenario_name, skip_validation=True
1476
        )
1477

1478
    def test_example_2periods_new_build_2zones_loadcomponents(self):
1✔
1479
        """
1480
        Check validation and objective function value of
1481
        "2periods_new_build_2zones_loadcomponents" example
1482
        :return:
1483
        """
1484
        scenario_name = "2periods_new_build_2zones_loadcomponents"
1✔
1485
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1486

1487
    def test_example_2periods_nuclear_var_cost_by_timepoint_same(self):
1✔
1488
        """
1489
        Check validation and objective function value of
1490
        "2periods_nuclear_var_cost_by_timepoint_same" example
1491
        :return:
1492
        """
1493
        scenario_name = "2periods_nuclear_var_cost_by_timepoint_same"
1✔
1494
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1495

1496
    def test_example_2periods_nuclear_var_cost_by_timepoint_diff(self):
1✔
1497
        """
1498
        Check validation and objective function value of
1499
        "2periods_nuclear_var_cost_by_timepoint_diff" example
1500
        :return:
1501
        """
1502
        scenario_name = "2periods_nuclear_var_cost_by_timepoint_diff"
1✔
1503
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1504

1505
    def test_example_test_w_storage_wind_as_energy(self):
1✔
1506
        """
1507
        Check validation and objective function value of
1508
        "test_w_storage_wind_as_energy" example
1509
        :return:
1510
        """
1511
        scenario_name = "test_w_storage_wind_as_energy"
1✔
1512
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1513

1514
    def test_example_test_w_hydro_no_reserves(self):
1✔
1515
        """
1516
        Check validation and objective function value of
1517
        "test_w_hydro_no_reserves"
1518
        example
1519
        :return:
1520
        """
1521
        scenario_name = "test_w_hydro_no_reserves"
1✔
1522
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1523

1524
    def test_example_test_w_hydro_as_energy_no_reserves(self):
1✔
1525
        """
1526
        Check validation and objective function value of
1527
        "test_w_hydro_as_energy_no_reserves"
1528
        example
1529
        :return:
1530
        """
1531
        scenario_name = "test_w_hydro_as_energy_no_reserves"
1✔
1532
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1533

1534
    def test_example_test_w_lf(self):
1✔
1535
        """
1536
        Check validation and objective function value of
1537
        "test_w_lf" example
1538
        :return:
1539
        """
1540
        scenario_name = "test_w_lf"
1✔
1541
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1542

1543
    def test_example_test_w_lf_w_demand_charges(self):
1✔
1544
        """
1545
        Check validation and objective function value of
1546
        "test_w_lf_w_demand_charges" example
1547
        :return:
1548
        """
1549
        scenario_name = "test_w_lf_w_demand_charges"
1✔
1550
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1551

1552
    def test_example_test_w_lf_only(self):
1✔
1553
        """
1554
        Check validation and objective function value of
1555
        "test_w_lf_only" example
1556
        :return:
1557
        """
1558
        scenario_name = "test_w_lf_only"
1✔
1559
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1560

1561
    def test_example_test_w_lf_only_and_prices(self):
1✔
1562
        """
1563
        Check validation and objective function value of
1564
        "test_w_lf_only_and_prices" example
1565
        :return:
1566
        """
1567
        scenario_name = "test_w_lf_only_and_prices"
1✔
1568
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1569

1570
    def test_example_test_w_lf_only_energy_potential_limit(self):
1✔
1571
        """
1572
        Check validation and objective function value of
1573
        "test_w_lf_only_energy_potential_limit" example
1574
        :return:
1575
        """
1576
        scenario_name = "test_w_lf_only_energy_potential_limit"
1✔
1577
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1578

1579
    def test_example_test_w_hydro_as_slice_candidate(self):
1✔
1580
        """
1581
        Check validation and objective function value of
1582
        "test_w_hydro_as_slice_candidate"
1583
        example
1584
        :return:
1585
        """
1586
        scenario_name = "test_w_hydro_as_slice_candidate"
1✔
1587
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1588

1589
    def test_example_test_w_energy_products(self):
1✔
1590
        """
1591
        Check validation and objective function value of
1592
        "test_w_lf_only_and_prices" example
1593
        :return:
1594
        """
1595
        scenario_name = "test_w_energy_products"
1✔
1596
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1597

1598
    def test_example_test_w_energy_products_group_limits(self):
1✔
1599
        """
1600
        Check validation and objective function value of
1601
        "test_w_lf_only_and_prices" example
1602
        :return:
1603
        """
1604
        scenario_name = "test_w_energy_products_group_limits"
1✔
1605
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1606

1607
    def test_example_2periods_new_build_generic_policy(self):
1✔
1608
        """
1609
        Check validation and objective function value of
1610
        "2periods_new_build_generic_policy" example
1611
        :return:
1612
        """
1613
        scenario_name = "2periods_new_build_generic_policy"
1✔
1614
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1615

1616
    def test_open_data(self):
1✔
1617
        """
1618
        Check validation and objective function value of "open_data" example
1619
        :return:
1620
        """
1621

1622
        scenario_name = "open_data"
1✔
1623
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1624

1625
    def test_hydro_system_exog_elev_w_travel_time_and_max_halfday_flows(self):
1✔
1626
        """
1627
        :return:
1628
        """
1629

1630
        scenario_name = "hydro_system_exog_elev_w_travel_time_and_max_halfday_flows"
1✔
1631
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1632

1633
    def test_hydro_system_w_ramp_limits(self):
1✔
1634
        """
1635
        :return:
1636
        """
1637

1638
        scenario_name = "hydro_system_w_ramp_limits"
1✔
1639
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1640

1641
    def test_test_w_bt_hrz_avl(self):
1✔
1642
        """
1643
        :return:
1644
        """
1645

1646
        scenario_name = "test_w_bt_hrz_avl"
1✔
1647
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1648

1649
    def test_hydro_system_exog_elev_w_gen_ramp_limits(self):
1✔
1650
        """ """
1651
        scenario_name = "hydro_system_exog_elev_w_gen_ramp_limits"
1✔
1652
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1653

1654
    def test_dsm_examples(self):
1✔
1655
        scenario_name = "dsm_examples"
1✔
1656
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1657

1658
    def test_example_test_w_hydro_ramp_limits(self):
1✔
1659
        """
1660
        Check validation and objective function value of
1661
        "test_w_hydro_ramp_limits" example
1662
        :return:
1663
        """
1664
        scenario_name = "test_w_hydro_ramp_limits"
1✔
1665
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1666

1667
    def test_example_2periods_new_build_generic_policy_recs(self):
1✔
1668
        """
1669
        Check validation and objective function value of
1670
        "2periods_new_build_rps_recs" example
1671
        :return:
1672
        """
1673
        scenario_name = "2periods_new_build_generic_policy_recs"
1✔
1674
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1675

1676
    def test_example_test_markets_w_tmp_total_limits(self):
1✔
1677
        """
1678
        Check validation and objective function value of "test" example
1679
        :return:
1680
        """
1681
        scenario_name = "test_markets_w_tmp_total_limits"
1✔
1682
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1683

1684
    def test_example_test_markets_w_prd_total_limits(self):
1✔
1685
        """
1686
        Check validation and objective function value of "test" example
1687
        :return:
1688
        """
1689
        scenario_name = "test_markets_w_prd_total_limits"
1✔
1690
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1691

1692
    def test_example_test_new_build_storage_losses_limit(self):
1✔
1693
        """
1694
        Check validation and objective function value of
1695
        "test_new_build_storage_losses_limit" example
1696
        :return:
1697
        """
1698

1699
        scenario_name = "test_new_build_storage_losses_limit"
1✔
1700
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1701

1702
    def test_example_test_carbon_credits_purchase_limits(self):
1✔
1703
        """
1704
        Check validation and objective function value of
1705
        "test_carbon_credits_purchase_limits" example
1706
        :return:
1707
        """
1708

1709
        scenario_name = "test_carbon_credits_purchase_limits"
1✔
1710
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1711

1712
    def test_example_test_inertia_reserves(self):
1✔
1713
        """
1714
        Check validation and objective function value of
1715
        "test_new_build_storage_losses_limit" example
1716
        :return:
1717
        """
1718

1719
        scenario_name = "test_inertia_reserves"
1✔
1720
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1721

1722
    def test_test_w_no_prj_av_sid_specified(self):
1✔
1723
        """
1724
        Check validation and objective function value of
1725
        "test_w_no_prj_av_sid_specified" example
1726
        :return:
1727
        """
1728

1729
        scenario_name = "test_w_no_prj_av_sid_specified"
1✔
1730
        self.validate_and_test_example_generic(scenario_name=scenario_name)
1✔
1731

1732
    @classmethod
1✔
1733
    def tearDownClass(cls):
1✔
1734
        os.remove(DB_PATH)
1✔
1735
        for temp_file_ext in ["-shm", "-wal"]:
1✔
1736
            temp_file = "{}{}".format(DB_PATH, temp_file_ext)
1✔
1737
            if os.path.exists(temp_file):
1✔
1738
                os.remove(temp_file)
×
1739

1740

1741
def objective_function_overwrite(scenario_name, starting_objective):
1✔
1742

1743
    objective = starting_objective
1✔
1744
    # On Python <3.12, we have one example with a slightly different
1745
    # objective function value; set it here
1746
    # TODO: remove this when we stop supporting Python <3.12
1747
    if (
1✔
1748
        PYTHON_VERSION < "3.12"
1749
        and scenario_name == "test_new_solar_carbon_credits_w_sell"
1750
    ):
1751
        print(
×
1752
            f"GridPath: overriding objective function for "
1753
            f"test_new_solar_carbon_credits_w_sell on Python v{PYTHON_VERSION}."
1754
        )
1755
        objective = ast.literal_eval("{('', '', '', 1): {1: 978964234435709.4}}")
×
1756

1757
    return objective
1✔
1758

1759

1760
if __name__ == "__main__":
1✔
1761
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc