From a7af9782a8bf20faf032555d2cff662fda2f0319 Mon Sep 17 00:00:00 2001 From: Jeremy L <5149279+lymereJ@users.noreply.github.com> Date: Fri, 27 Oct 2023 08:57:21 -0700 Subject: [PATCH] Input schema (#72) * Fix typos. * Add schema and change kw to be kW. * Add schema tests. * Update CLI and tests. * Update reqs. * Test. * Fix path issue. --- copper/__init__.py | 1 + copper/chiller.py | 22 +-- copper/cli.py | 22 ++- copper/constants.py | 10 ++ copper/generator.py | 2 +- copper/schema.py | 43 ++++++ copper/units.py | 8 +- docs/source/Additional Examples.rst | 16 +- docs/source/Quickstart Guide.rst | 8 +- requirements.txt | Bin 196 -> 220 bytes schema/copper.chiller.action.schema.json | 26 ++++ ...chiller.generate_set_of_curves.schema.json | 50 +++++++ schema/copper.chiller.schema.json | 138 ++++++++++++++++++ schema/copper.schema.json | 18 +++ tests/data/cli_input_file.json | 53 +++---- tests/test_benchmark.py | 4 +- tests/test_chiller.py | 8 +- tests/test_cli.py | 3 +- tests/test_curves.py | 10 +- tests/test_generator.py | 40 ++--- tests/test_logging.py | 2 +- tests/test_schema.py | 16 ++ tests/test_units.py | 8 +- 23 files changed, 409 insertions(+), 99 deletions(-) create mode 100644 copper/schema.py create mode 100644 schema/copper.chiller.action.schema.json create mode 100644 schema/copper.chiller.generate_set_of_curves.schema.json create mode 100644 schema/copper.chiller.schema.json create mode 100644 schema/copper.schema.json create mode 100644 tests/test_schema.py diff --git a/copper/__init__.py b/copper/__init__.py index 536e512..502be3a 100644 --- a/copper/__init__.py +++ b/copper/__init__.py @@ -1,4 +1,5 @@ from copper.chiller import * +from copper.schema import * from copper.constants import LOGGING_FORMAT import sys diff --git a/copper/chiller.py b/copper/chiller.py index f2e09bd..cc764c4 100644 --- a/copper/chiller.py +++ b/copper/chiller.py @@ -190,17 +190,17 @@ def get_ref_cond_flow_rate(self): else: evap_power = self.ref_cap - if self.ref_cap_unit != "kw/ton": + if self.ref_cap_unit != "kW/ton": ref_cap = Units(value=self.ref_cap, unit=self.ref_cap_unit) - ref_cap = ref_cap.conversion(new_unit="kw/ton") + ref_cap = ref_cap.conversion(new_unit="kW/ton") else: ref_cap = self.ref_cap # Convert reference efficiency if needed - if self.full_eff_unit != "kw/ton": + if self.full_eff_unit != "kW/ton": full_eff_unit = Units(value=self.full_eff, unit=self.full_eff_unit) full_eff = full_eff_unit.conversion( - new_unit="kw/ton" + new_unit="kW/ton" ) # full eff needs to be in kW/ton else: full_eff = self.full_eff @@ -329,9 +329,9 @@ def get_eir_ref(self, alt): kwpton_ref_unit = self.full_eff_unit # Convert to kWpton if necessary - if self.full_eff_unit != "kw/ton": + if self.full_eff_unit != "kW/ton": kwpton_ref_unit = Units(kwpton_ref, kwpton_ref_unit) - kwpton_ref = kwpton_ref_unit.conversion("kw/ton") + kwpton_ref = kwpton_ref_unit.conversion("kW/ton") # Conversion factors # TODO: remove these and use the unit class @@ -372,7 +372,7 @@ def calc_eff_ect(self, cap_f_t, eir_f_t, eir_f_plr, eir_ref, ect, lwt, load): return eir - def calc_rated_eff(self, eff_type, unit="kw/ton", output_report=False, alt=False): + def calc_rated_eff(self, eff_type, unit="kW/ton", output_report=False, alt=False): """Calculate chiller efficiency. :param str eff_type: Chiller efficiency type, currently supported `full` (full load rating) @@ -505,8 +505,8 @@ def calc_rated_eff(self, eff_type, unit="kw/ton", output_report=False, alt=False # Stop here for full load calculations if eff_type == "full" and idx == 0: - if unit != "kw/ton": - kwpton = Units(kwpton, "kw/ton").conversion(unit) + if unit != "kW/ton": + kwpton = Units(kwpton, "kW/ton").conversion(unit) return kwpton # Coefficients from AHRI Std 551/591 @@ -523,8 +523,8 @@ def calc_rated_eff(self, eff_type, unit="kw/ton", output_report=False, alt=False return -999 # Convert IPLV to desired unit - if unit != "kw/ton": - iplv_org = Units(iplv, "kw/ton") + if unit != "kW/ton": + iplv_org = Units(iplv, "kW/ton") iplv = iplv_org.conversion(unit) return iplv diff --git a/copper/cli.py b/copper/cli.py index 009a115..48b7033 100644 --- a/copper/cli.py +++ b/copper/cli.py @@ -6,8 +6,8 @@ import click, json, inspect -# import copper.Chiller as chiller from copper.chiller import Chiller +import copper.schema @click.group() @@ -23,18 +23,23 @@ def cli(): @click.argument("input_file", type=click.File("rb"), required=True) def run(input_file): """Run a set of Copper instructions through a JSON input file. See 'Using Copper's command line interface in the Quickstart Guide section of the documenation for more information.""" + try: f = json.load(input_file) + + # Validate input file + assert copper.Schema(f).validate() == True except: raise ValueError("Could not read the input file. A JSON file is expected.") - for eqp, eqp_props in f.items(): + for action in f["actions"]: + eqp_props = action["equipment"] # Make sure that the equipment is supported by Copper - assert eqp_props["eqp_type"].lower() in [ + assert eqp_props["type"].lower() in [ "chiller" ], "Equipment type not currently supported by Copper." # Get properties for equipment type - eqp_type_props = inspect.getfullargspec(eval(eqp_props["eqp_type"]).__init__)[0] + eqp_type_props = inspect.getfullargspec(eval(eqp_props["type"]).__init__)[0] # Set the equipment properties from input file obj_args = {} @@ -43,12 +48,13 @@ def run(input_file): obj_args[p] = eqp_props[p] # Create instance of the equipment - obj = eval(eqp_props["eqp_type"])(**obj_args) + obj = eval(eqp_props["type"])(**obj_args) # Perform actions defined in input file - if "do" in list(eqp_props.keys()): - for action in eqp_props["do"]: - getattr(obj, action)(**eqp_props["do"][action]) + func = action["function_call"]["function"] + del action["function_call"]["function"] + args = action["function_call"] + getattr(obj, func)(**args) if __name__ == "__main__": diff --git a/copper/constants.py b/copper/constants.py index 2b8c1bf..a391d45 100644 --- a/copper/constants.py +++ b/copper/constants.py @@ -3,4 +3,14 @@ ==================================== Holds all the constants referenced in copper. """ + +import os + LOGGING_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" +ROOT_DIR = os.path.dirname(__file__) +CHILLER_SCHEMA_PATH = f"{ROOT_DIR}/../schema/copper.chiller.schema.json" +CHILLER_GENE_SCHEMA_PATH = ( + f"{ROOT_DIR}/../schema/copper.chiller.generate_set_of_curves.schema.json" +) +CHILLER_ACTION_SCHEMA_PATH = f"{ROOT_DIR}/../schema/copper.chiller.action.schema.json" +SCHEMA_PATH = f"{ROOT_DIR}/../schema/copper.schema.json" diff --git a/copper/generator.py b/copper/generator.py index c118380..c333a90 100644 --- a/copper/generator.py +++ b/copper/generator.py @@ -197,7 +197,7 @@ def run_ga(self, curves, verbose=False): restart += 1 logging.info( - "GEN: {}, IPLV: {}, KW/TON: {}".format( + "GEN: {}, IPLV: {}, kW/ton: {}".format( gen, round( self.equipment.calc_rated_eff( diff --git a/copper/schema.py b/copper/schema.py new file mode 100644 index 0000000..bc08a58 --- /dev/null +++ b/copper/schema.py @@ -0,0 +1,43 @@ +""" +schema.py +==================================== +Validation of the CLI input files. +""" + +import json, jsonschema, logging +from copper.constants import SCHEMA_PATH +from copper.constants import CHILLER_SCHEMA_PATH +from copper.constants import CHILLER_GENE_SCHEMA_PATH +from copper.constants import CHILLER_ACTION_SCHEMA_PATH + +# Load schemas +schema_chiller = json.load(open(CHILLER_SCHEMA_PATH, "r")) +schema_chiller_gene = json.load(open(CHILLER_GENE_SCHEMA_PATH, "r")) +schema_chiller_action = json.load(open(CHILLER_ACTION_SCHEMA_PATH, "r")) +schema = json.load(open(SCHEMA_PATH, "r")) + +# Define schema store for the validator +schema_store = { + "copper.chiller.schema.json": schema_chiller, + "copper.chiller.generate_set_of_curves.schema.json": schema_chiller_gene, + "copper.chiller.action.schema.json": schema_chiller_action, + "copper.schema.json": schema, +} + + +class Schema: + def __init__(self, input): + self.input = input + self.schema = schema + self.schema_store = schema_store + self.resolver = jsonschema.RefResolver.from_schema(schema, store=schema_store) + Validator = jsonschema.validators.validator_for(schema) + self.validator = Validator(self.schema, resolver=self.resolver) + + def validate(self): + try: + self.validator.validate(self.input) + return True + except: + logging.critical("Input file is not valid.") + return diff --git a/copper/units.py b/copper/units.py index 71c1383..abe5f5f 100644 --- a/copper/units.py +++ b/copper/units.py @@ -18,17 +18,17 @@ def conversion(self, new_unit): :rtype: float """ - if new_unit == "kw/ton": + if new_unit == "kW/ton": if self.unit == "cop": return 12.0 / (self.value * 3.412) - elif self.unit == "kw/ton": + elif self.unit == "kW/ton": return self.value elif self.unit == "eer": return 12.0 / self.value else: return self.value elif new_unit == "cop": - if self.unit == "kw/ton": + if self.unit == "kW/ton": return 12.0 / self.value / 3.412 elif self.unit == "cop": return self.value @@ -37,7 +37,7 @@ def conversion(self, new_unit): else: return self.value elif new_unit == "eer": - if self.unit == "kw/ton": + if self.unit == "kW/ton": return 12.0 / self.value elif self.unit == "eer": return self.value diff --git a/docs/source/Additional Examples.rst b/docs/source/Additional Examples.rst index e7b6b66..64a49d8 100644 --- a/docs/source/Additional Examples.rst +++ b/docs/source/Additional Examples.rst @@ -17,9 +17,9 @@ Most building energy modeling software use an entering condenser temperature (EC ref_cap=100, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", model="lct_lwt", sim_engine="energyplus", @@ -52,14 +52,14 @@ The rating conditions in AHRI Standards 550/590 and 551/591 are different. **Cop ref_cap=100, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", full_eff_alt=full_eff_target_alt, - full_eff_unit_alt="kw/ton", + full_eff_unit_alt="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", part_eff_alt=part_eff_target_alt, - part_eff_unit_alt="kw/ton", + part_eff_unit_alt="kW/ton", part_eff_ref_std_alt="ahri_551/591", model="ect_lwt", sim_engine="energyplus", @@ -83,9 +83,9 @@ Because **Copper** is used to find a solution to an underdetermined system of eq ref_cap=300, ref_cap_unit="ton", full_eff=0.610, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=0.520, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="screw", diff --git a/docs/source/Quickstart Guide.rst b/docs/source/Quickstart Guide.rst index 9ff7d00..80543bb 100644 --- a/docs/source/Quickstart Guide.rst +++ b/docs/source/Quickstart Guide.rst @@ -30,9 +30,9 @@ Next, we define the chiller. In this example, the chiller is a 300 ton constant ref_cap=300, ref_cap_unit="ton", full_eff=0.610, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=0.520, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="screw", @@ -106,9 +106,9 @@ First, we create the JSON input file. "ref_cap":300, "ref_cap_unit":"ton", "full_eff":0.61, - "full_eff_unit":"kw/ton", + "full_eff_unit":"kW/ton", "part_eff":0.52, - "part_eff_unit":"kw/ton", + "part_eff_unit":"kW/ton", "sim_engine":"energyplus", "model":"ect_lwt", "do":{ diff --git a/requirements.txt b/requirements.txt index 43402d9117a0282519d66010221835c39a77a09f..e0e83636327c2fc6602dac31296f71bb9938900a 100644 GIT binary patch delta 31 lcmX@Yc!zPq5eZ%fE`}_IVupN%JRq6Okin43kjs$B004(A2T=e3 delta 6 Ncmcb^c!Y7n5daD*0`~v_ diff --git a/schema/copper.chiller.action.schema.json b/schema/copper.chiller.action.schema.json new file mode 100644 index 0000000..781e8e7 --- /dev/null +++ b/schema/copper.chiller.action.schema.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "title": "Chiller functions", + "description": "Run a function for a chiller", + "definitions": { + "action": { + "type": "object", + "properties": { + "equipment": { + "description": "Chiller definition", + "$ref": "copper.chiller.schema.json#/definitions/chiller" + }, + "function_call": { + "description": "Chiller-specific function call", + "oneOf": [ + { + "$ref": "copper.chiller.generate_set_of_curves.schema.json#/definitions/generate_set_of_curves" + } + ] + } + }, + "required": ["equipment", "function_call"] + } + }, + "$ref": "copper.chiller.action.schema.json#/definitions/action" +} diff --git a/schema/copper.chiller.generate_set_of_curves.schema.json b/schema/copper.chiller.generate_set_of_curves.schema.json new file mode 100644 index 0000000..f52eed0 --- /dev/null +++ b/schema/copper.chiller.generate_set_of_curves.schema.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "title": "Generate set of curves", + "description": "Generate set of curves for chillers", + "definitions": { + "generate_set_of_curves": { + "type": "object", + "properties": { + "function": { + "description": "Function to be called", + "type": "string", + "enum": ["generate_set_of_curves"], + "minLength": 1 + }, + "vars": { + "description": "Curve modifier that will be modified to target full and part load efficiencies", + "type": "array", + "items": { + "type": "string", + "enum": ["eir-f-t", "cap-f-t", "eir-f-plr"] + } + }, + "method": { + "description": "Aggregation method used to generate the typical curve", + "type": "string", + "enum": ["nearest_neighbor", "average", "median"] + }, + "tol": { + "description": "Tolerance for the optimization process", + "type": "number" + }, + "export_path": { + "description": "Path to export the generated performance curves", + "type": "string" + }, + "export_format": { + "description": "File format of the generated performance curves", + "type": "string", + "enum": ["idf", "json", "csv"] + }, + "export_name": { + "description": "Name of the generated set of performance curves", + "type": "string", + "minLength": 1 + } + } + } + }, + "$ref": "copper.chiller.generate_set_of_curves.schema.json#/definitions/generate_set_of_curves" +} diff --git a/schema/copper.chiller.schema.json b/schema/copper.chiller.schema.json new file mode 100644 index 0000000..4b74077 --- /dev/null +++ b/schema/copper.chiller.schema.json @@ -0,0 +1,138 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "title": "Chiller Inputs", + "description": "Set of inputs for a chiller", + "definitions": { + "chiller": { + "type": "object", + "properties": { + "type": { + "description": "Type of equipment", + "type": "string", + "enum": ["Chiller"], + "minLength": 1 + }, + "ref_cap": { + "description": "Reference capacity of the chiller", + "type": "number", + "exclusiveMinimum": 0 + }, + "ref_cap_unit": { + "description": "Unit of the reference capacity of the chiller", + "type": "string", + "enum": ["ton", "kW", "W"], + "minLength": 1 + }, + "full_eff": { + "description": "Full load efficiency of the chiller", + "type": "number", + "exclusiveMinimum": 0 + }, + "full_eff_unit": { + "description": "Full load efficiency units of the chiller", + "type": "string", + "enum": ["kW/ton", "cop", "eer"], + "minLength": 1 + }, + "full_eff_alt": { + "description": "Alternative full load efficiency of the chiller (only used when alternative reference standard is used)", + "type": "number", + "exclusiveMinimum": 0 + }, + "full_eff_unit_alt": { + "description": "Alternative full load efficiency units of the chiller (only used when alternative reference standard is used)", + "type": "string", + "enum": ["kW/ton", "cop", "eer"], + "minLength": 1 + }, + "part_eff": { + "description": "Part load efficiency of the chiller", + "type": "number", + "exclusiveMinimum": 0 + }, + "part_eff_unit": { + "description": "Part load efficiency units of the chiller", + "type": "string", + "enum": ["kW/ton", "cop", "eer"], + "minLength": 1 + }, + "part_eff_alt": { + "description": "Alternative part load efficiency of the chiller (only used when alternative reference standard is used)", + "type": "number", + "exclusiveMinimum": 0 + }, + "part_eff_unit_alt": { + "description": "Alternative part load efficiency units of the chiller (only used when alternative reference standard is used)", + "type": "string", + "enum": ["kW/ton", "cop", "eer"], + "minLength": 1 + }, + "compressor_type": { + "description": "Type of compressor used by the chiller", + "type": "string", + "enum": [ + "positive_displacement", + "screw", + "scroll", + "reciprocating", + "centrifugal" + ], + "minLength": 1 + }, + "condenser_type": { + "description": "Type of condenser used by the chiller", + "type": "string", + "enum": ["water", "air"], + "minLength": 1 + }, + "part_eff_ref_std": { + "description": "Standard for rated conditions", + "type": "string", + "enum": ["ahri_550/590", "ahri_551/591"], + "minLength": 1 + }, + "part_eff_ref_std_alt": { + "description": "Alternate standard for rated conditions", + "type": "string", + "enum": ["ahri_550/590", "ahri_551/591"], + "minLength": 1 + }, + "model": { + "description": "Chiller model corresponding to the set of performance curves", + "type": "string", + "enum": ["ect_lwt", "lct_lwt"], + "minLength": 1 + }, + "sim_engine": { + "description": "Simulation engine used for simulation of the performance curves", + "type": "string", + "enum": ["energyplus"], + "minLength": 1 + }, + "min_unloading": { + "description": "Minimum unloading ratio of the chiller", + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "min_plr": { + "description": "Minimum part load ratio of the chiller", + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + } + }, + "required": [ + "type", + "ref_cap", + "ref_cap_unit", + "full_eff", + "full_eff_unit", + "part_eff", + "part_eff_unit", + "model" + ] + } + }, + "$ref": "copper.chiller.schema.json#/definitions/chiller" +} diff --git a/schema/copper.schema.json b/schema/copper.schema.json new file mode 100644 index 0000000..d12ab8c --- /dev/null +++ b/schema/copper.schema.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "title": "Inputs", + "description": "Inputs to Copper", + "properties": { + "actions": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "copper.chiller.action.schema.json#/definitions/action" + } + ] + } + } + }, + "required": ["actions"] +} diff --git a/tests/data/cli_input_file.json b/tests/data/cli_input_file.json index 282fe52..1b58161 100644 --- a/tests/data/cli_input_file.json +++ b/tests/data/cli_input_file.json @@ -1,29 +1,30 @@ { - "Quickstart_Guide_Chiller":{ - "eqp_type":"Chiller", - "compressor_type":"screw", - "condenser_type":"water", - "compressor_speed":"constant", - "ref_cap":300, - "ref_cap_unit":"ton", - "full_eff":0.61, - "full_eff_unit":"kw/ton", - "part_eff":0.52, - "part_eff_unit":"kw/ton", - "sim_engine":"energyplus", - "model":"ect_lwt", - "do":{ - "generate_set_of_curves":{ - "vars":[ - "eir-f-plr" - ], - "method":"nearest_neighbor", - "tol":0.05, - "export_path":"./", - "export_format":"json", - "export_name":"Quickstart_Guide_Chiller", - "random_seed":1 + "actions": [ + { + "equipment": { + "type": "Chiller", + "compressor_type": "screw", + "condenser_type": "water", + "compressor_speed": "constant", + "ref_cap": 300, + "ref_cap_unit": "ton", + "full_eff": 0.61, + "full_eff_unit": "kW/ton", + "part_eff": 0.52, + "part_eff_unit": "kW/ton", + "sim_engine": "energyplus", + "model": "ect_lwt" + }, + "function_call": { + "function": "generate_set_of_curves", + "vars": ["eir-f-plr"], + "method": "nearest_neighbor", + "tol": 0.05, + "export_path": "./", + "export_format": "json", + "export_name": "Quickstart_Guide_Chiller", + "random_seed": 1 } } - } -} \ No newline at end of file + ] +} diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index 9cd31e2..b2169d3 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -14,9 +14,9 @@ def test_benchmark(self): # ref_cap=300, # ref_cap_unit="ton", # full_eff=0.650, -# full_eff_unit="kw/ton", +# full_eff_unit="kW/ton", # part_eff=0.48, -# part_eff_unit="kw/ton", +# part_eff_unit="kW/ton", # sim_engine="energyplus", # model="ect_lwt", # compressor_type="centrifugal", diff --git a/tests/test_chiller.py b/tests/test_chiller.py index 3912800..c005d33 100644 --- a/tests/test_chiller.py +++ b/tests/test_chiller.py @@ -168,9 +168,9 @@ def test_get_lct(self): ref_cap=75.0, ref_cap_unit="ton", full_eff=0.79, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=0.676, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", min_unloading=0.1, model="lct_lwt", @@ -266,9 +266,9 @@ def test_curves_fromm_lib(self): ref_cap=400, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="centrifugal", diff --git a/tests/test_cli.py b/tests/test_cli.py index 18ab855..b2fcd27 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -7,10 +7,11 @@ def test_cli_incorrect_file(): runner = CliRunner() result = runner.invoke(run, ["test"]) assert "'test': No such file or directory" in result.output + assert result.exit_code == 2 def test_cli_correct(caplog): caplog.set_level(logging.INFO) runner = CliRunner() result = runner.invoke(run, ["./tests/data/cli_input_file.json"]) - assert "Target met after 13 generations." + assert result.exit_code == 0 diff --git a/tests/test_curves.py b/tests/test_curves.py index 44f70b6..f25fa62 100644 --- a/tests/test_curves.py +++ b/tests/test_curves.py @@ -251,14 +251,14 @@ def test_flow_calcs_after_agg(self): ref_cap=150, ref_cap_unit="ton", full_eff=0.75, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", full_eff_alt=0.719, - full_eff_unit_alt="kw/ton", + full_eff_unit_alt="kW/ton", part_eff=0.56, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", part_eff_alt=0.559, - part_eff_unit_alt="kw/ton", + part_eff_unit_alt="kW/ton", part_eff_ref_std_alt="ahri_551/591", model="lct_lwt", sim_engine="energyplus", @@ -303,7 +303,7 @@ def test_flow_calcs_after_agg(self): / 1000 ) - cop = cp.Units(chlr.full_eff, "kw/ton").conversion("cop") + cop = cp.Units(chlr.full_eff, "kW/ton").conversion("cop") # Determine the density of water [kg/m3] rho = CP.PropsSI( diff --git a/tests/test_generator.py b/tests/test_generator.py index 4fc4d19..6614a9e 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -8,9 +8,9 @@ def test_quickstart_guide(self): ref_cap=300, ref_cap_unit="ton", full_eff=0.610, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=0.520, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="screw", @@ -100,9 +100,9 @@ def test_random_init(self): ref_cap=300, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="centrifugal", @@ -127,9 +127,9 @@ def test_gradients(self): ref_cap=300, ref_cap_unit="ton", full_eff=0.650, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=0.48, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", sim_engine="energyplus", model="ect_lwt", compressor_type="centrifugal", @@ -156,14 +156,14 @@ def test_double_targets(self): ref_cap=100, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", full_eff_alt=full_eff_target_alt, - full_eff_unit_alt="kw/ton", + full_eff_unit_alt="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", part_eff_alt=part_eff_target_alt, - part_eff_unit_alt="kw/ton", + part_eff_unit_alt="kW/ton", part_eff_ref_std_alt="ahri_551/591", model="ect_lwt", sim_engine="energyplus", @@ -200,9 +200,9 @@ def test_single_target_lct(self): ref_cap=100, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", model="lct_lwt", sim_engine="energyplus", @@ -235,14 +235,14 @@ def test_double_targets_lct(self): ref_cap=100, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", full_eff_alt=full_eff_target_alt, - full_eff_unit_alt="kw/ton", + full_eff_unit_alt="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std="ahri_550/590", part_eff_alt=part_eff_target_alt, - part_eff_unit_alt="kw/ton", + part_eff_unit_alt="kW/ton", part_eff_ref_std_alt="ahri_551/591", model="lct_lwt", sim_engine="energyplus", @@ -287,14 +287,14 @@ def test_generator_nn(self): ref_cap=225, ref_cap_unit="ton", full_eff=full_eff_target, - full_eff_unit="kw/ton", + full_eff_unit="kW/ton", full_eff_alt=full_eff_target_alt, - full_eff_unit_alt="kw/ton", + full_eff_unit_alt="kW/ton", part_eff=part_eff_target, - part_eff_unit="kw/ton", + part_eff_unit="kW/ton", part_eff_ref_std=primary_std, part_eff_alt=part_eff_target_alt, - part_eff_unit_alt="kw/ton", + part_eff_unit_alt="kW/ton", part_eff_ref_std_alt=secondary_std, model="ect_lwt", sim_engine="energyplus", diff --git a/tests/test_logging.py b/tests/test_logging.py index 14ba8b0..fb7f9c4 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -35,7 +35,7 @@ def test_logging(self): == "Target not met after 1 generations; Restarting the generator." ) self.assertTrue(captured[0][0].levelname == "WARNING") - self.assertTrue("GEN: 0, IPLV: 5.56, KW/TON: 5" in captured[0][1].msg) + self.assertTrue("GEN: 0, IPLV: 5.56, kW/ton: 5" in captured[0][1].msg) self.assertTrue(captured[0][1].levelname == "INFO") self.assertTrue( captured[0][2].msg diff --git a/tests/test_schema.py b/tests/test_schema.py new file mode 100644 index 0000000..3164560 --- /dev/null +++ b/tests/test_schema.py @@ -0,0 +1,16 @@ +import json, jsonschema, os +import copper as cp +from unittest import TestCase + + +class TestCurves(TestCase): + def test_good_schema(self): + input_file = json.load(open("./tests/data/cli_input_file.json", "r")) + assert cp.Schema(input=input_file).validate() + + def test_bad_schema(self): + input_file = json.load(open("./tests/data/cli_input_file.json", "r")) + input_file["actions"][0]["function_call"]["vars"] = 42.0 + with self.assertLogs() as captured: + assert cp.Schema(input=input_file).validate() is None + self.assertTrue(captured[0][0].msg == "Input file is not valid.") diff --git a/tests/test_units.py b/tests/test_units.py index 2f9c371..b1073e5 100644 --- a/tests/test_units.py +++ b/tests/test_units.py @@ -7,16 +7,16 @@ class TestRating(TestCase): def test_conversion(self): # Efficiency conversion kWpton_ = cp.Units(14.0, "eer") - self.assertTrue(round(kWpton_.conversion("kw/ton"), 3) == 0.857) + self.assertTrue(round(kWpton_.conversion("kW/ton"), 3) == 0.857) kWpton_ = cp.Units(3.5, "cop") - self.assertTrue(round(kWpton_.conversion("kw/ton"), 3) == 1.005) + self.assertTrue(round(kWpton_.conversion("kW/ton"), 3) == 1.005) - eer_ = cp.Units(0.75, "kw/ton") + eer_ = cp.Units(0.75, "kW/ton") self.assertTrue(round(eer_.conversion("eer"), 3) == 16.0) eer_ = cp.Units(3.5, "cop") self.assertTrue(round(eer_.conversion("eer"), 3) == 11.942) - COP_ = cp.Units(0.75, "kw/ton") + COP_ = cp.Units(0.75, "kW/ton") self.assertTrue(round(COP_.conversion("cop"), 3) == 4.689) COP_ = cp.Units(14.0, "eer") self.assertTrue(round(COP_.conversion("cop"), 3) == 4.103)