Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Lattice to published version of Standard 232 #50

Draft
wants to merge 52 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6afa26b
Add skeleton (generated; untested) code for Courier library.
tanaya-mankad May 27, 2024
74e5f53
Convert string concatenation to f-strings where reasonable.
tanaya-mankad May 27, 2024
dae6bb3
Clean formatting.
tanaya-mankad May 27, 2024
53ca56b
Fix parenthesis bug.
tanaya-mankad May 28, 2024
42a5a28
Fix typing and linting.
nealkruis Jun 14, 2024
5ee1b65
Add basic CMake support files to cpp generation.
tanaya-mankad Jun 17, 2024
d1f9ebb
Black formatting.
tanaya-mankad Jun 17, 2024
53159b1
Add core.h to includes when a core type is referenced.
tanaya-mankad Jun 19, 2024
2e44da1
Update Metadata and array length constraint.
nealkruis Jun 21, 2024
8a24d19
Handle ID.
nealkruis Jun 22, 2024
e832b58
Replace SchemaFile class with Schema class. Fix IDs and Referneces.
nealkruis Jun 22, 2024
0009701
Add vendor submodules, build scripts, and a bit of extra documentation.
tanaya-mankad Jul 10, 2024
4616cb9
Format python.
tanaya-mankad Jul 10, 2024
2da8ffc
Black formatting.
tanaya-mankad Jul 10, 2024
4ead9c6
Clean up template-rendering code.
tanaya-mankad Jul 10, 2024
34921f5
Add code to look for necessary base classes and generate file stubs i…
tanaya-mankad Jul 12, 2024
f3f7f7d
Update readme.
tanaya-mankad Jul 12, 2024
05f551b
Reformat.
tanaya-mankad Jul 12, 2024
9a3399d
Add header to core.h when there's a forward-declared type.
tanaya-mankad Jul 18, 2024
dc5a89d
Clarify functions and inputs.
tanaya-mankad Oct 1, 2024
07f682b
Add ability to find a selector constraint's Data Type class in a refe…
tanaya-mankad Oct 2, 2024
5fb7479
Use pathlib Paths; generate necessary base class files within header …
tanaya-mankad Oct 4, 2024
fdce7f7
Black formatting.
tanaya-mankad Oct 4, 2024
e93f078
Add virtual destructor to base class files; remove initialize functions.
tanaya-mankad Oct 22, 2024
4754b47
Make destructor default.
tanaya-mankad Oct 22, 2024
a814edb
Update readme.
tanaya-mankad Oct 23, 2024
c383d66
Format code.
tanaya-mankad Oct 23, 2024
cdeab8d
Move CPP generation modules into cpp directory.
tanaya-mankad Nov 20, 2024
03cf61b
Remove deprecated copy_tree.
tanaya-mankad Nov 21, 2024
2247aa3
Fix paths to header_entries.
tanaya-mankad Nov 21, 2024
0822e71
Begin adding plugin infrastructure.
tanaya-mankad Nov 22, 2024
7f40f6f
Load module by path.
tanaya-mankad Nov 23, 2024
d911c07
Fix module name.
tanaya-mankad Nov 23, 2024
7281a5e
Debug spec path.
tanaya-mankad Nov 23, 2024
02eae2e
Plugins must end in .py.
tanaya-mankad Nov 23, 2024
90bc252
Cleanup.
tanaya-mankad Nov 23, 2024
047e1f7
Add data-element plugin section.
tanaya-mankad Nov 25, 2024
3ba2073
Merge branch 'main' into add-plugin-support
tanaya-mankad Nov 25, 2024
fa83684
Fix formatting and type hinting.
tanaya-mankad Nov 25, 2024
807387f
Restructure header entries; clean up unnecessary collections of refer…
tanaya-mankad Dec 3, 2024
376784d
Fix formatting.
tanaya-mankad Dec 3, 2024
a6fa98b
Add plugin support files directly to lattice examples.
tanaya-mankad Dec 4, 2024
f407428
Black.
tanaya-mankad Dec 4, 2024
9d76338
Merge from 232-update.
tanaya-mankad Dec 5, 2024
518b848
Major cleanup of classes and added logging.
tanaya-mankad Dec 16, 2024
8625c1d
Change plugin architecture; implement 205 header additions.
tanaya-mankad Dec 18, 2024
ef80fec
Fix errant extension duplication.
tanaya-mankad Dec 24, 2024
6deedaa
Clean up header and namespace naming and inclusion.
tanaya-mankad Jan 6, 2025
b673249
Add extensions for fan_spec code generation. Rewrite ImplementationEn…
tanaya-mankad Jan 16, 2025
ea3c259
Black formatting.
tanaya-mankad Jan 16, 2025
a812a34
Finish formatting.
tanaya-mankad Jan 17, 2025
df8e283
Merge from main.
tanaya-mankad Jan 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,51 @@ More complete examples of projects using the ASHRAE Standard 232P framework incl
- [ASHRAE Standard 205](https://github.com/open205/schema-205) (transitioning to lattice)
- [ASHRAE Standard 229](https://github.com/open229/ruleset-model-description-schema) (does not use lattice...yet)

### C++ Library Code Generation

Lattice's C++ code generation is achieved by calling the function `generate_cpp_project()`. Its only parameter is a list of submodule URLs.

#### Translations

Schema can be converted into C++ classes with the following mappings:

| Object Type | C++ type |
|------------------- | -------- |
| Data Group | `struct` |
| Data Element | public data member |
| Enumerator | `enum` |
| Data Group Template | base class*|
|

*with optional methods, including initialize()

| Data Type | C++ type |
|------------------- | -------- |
| Integer | `int` |
| Numeric | `float` |
| String | `std::string` |
| {} | `struct` |
| <> | `enum` |
| [] | `std::vector` |
| list "(A,B)" | `std::unique_ptr<BaseOfAB>`|
|

#### Inheritance

The code generator will assume that *Data Group* schema elements with a *Data Group Template* parameter use that template as the element's superclass. An `#include` statement for the expected superclass file is listed at the top of the schema's implemenation (cpp) file (note: see Big Ladder file naming conventions). If the superclass file is not found, the C++ generator will create a stub file for the class. If it is found, any virtual functions in the superclass will appear as overridden function stubs in the subclassed *Data Group*'s struct. Any additional code (members, methods) for the superclass itself must be provided by the **lattice** user.

In the event that the source schema contains a *Data Element* with a "selector constraint" (i.e. a list of possible *Data Type*s combined with an associated list of possible enumerator values for the selector *Data Element*), the C++ generated code will assume that the *Data Type*s in the list all derive from a common base class, named by the *Data Group Template* of the first *Data Type* in the list. (The *Data Group Template* may be defined in a different schema than the *Data Type*.) An `#include` statement for the base class will be generated, as above. The code that populates the *Data Group* (the struct's `from_json` function) will use a conditional statement to create a new object of the correct subclass and assign it to a member `unique_ptr`, calling directly the derived class' auto-generated `from_json` functions.

Note: If the first *Data Type* in a selector constraint list does not have a *Data Group Template* tag in its schema, the `unique_ptr`'s base class will default to "MissingType."

#### Build information

In addition to `.h` and `.cpp` files containing translated schema data, the code generator adds Git repository and CMake build support to the schema code, creating most of the structure necessary to test-build the schema code as a library. Necessary submodules are also downloaded: [fmt](https://github.com/fmtlib/fmt.git), [json](https://github.com/nlohmann/json), and [courier](https://github.com/bigladder/courier.git). To build a generated project, navigate to your **lattice** project's build directory, cpp subdirectory (e.g. /.lattice/cpp), and use a standard cmake build sequence:

> cmake -B build
>
> cmake --build build --config release




46 changes: 33 additions & 13 deletions dodo.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
from lattice import Lattice
import logging
from pathlib import Path
from lattice import Lattice
from lattice.cpp.header_entry_extension_loader import load_extensions

from doit import task_params
from doit.tools import create_folder

logging.basicConfig(level=logging.CRITICAL,
format='%(asctime)s: [%(levelname)s] %(message)s',
handlers=[logging.FileHandler("lattice.log", mode='w')])

SOURCE_PATH = "lattice"
EXAMPLES_PATH = "examples"
BUILD_PATH = "build"
Expand All @@ -29,7 +36,7 @@ def task_generate_meta_schemas():
name = Path(example.root_directory).name
yield {
"name": name,
"file_dep": [schema.path for schema in example.schemas]
"file_dep": [schema.file_path for schema in example.schemas]
+ [BASE_META_SCHEMA_PATH, CORE_SCHEMA_PATH, Path(SOURCE_PATH, "meta_schema.py")],
"targets": [schema.meta_schema_path for schema in example.schemas],
"actions": [(example.generate_meta_schemas, [])],
Expand All @@ -44,7 +51,7 @@ def task_validate_schemas():
yield {
"name": name,
"task_dep": [f"generate_meta_schemas:{name}"],
"file_dep": [schema.path for schema in example.schemas]
"file_dep": [schema.file_path for schema in example.schemas]
+ [schema.meta_schema_path for schema in example.schemas]
+ [BASE_META_SCHEMA_PATH, CORE_SCHEMA_PATH, Path(SOURCE_PATH, "meta_schema.py")],
"actions": [(example.validate_schemas, [])],
Expand All @@ -58,7 +65,7 @@ def task_generate_json_schemas():
yield {
"name": name,
"task_dep": [f"validate_schemas:{name}"],
"file_dep": [schema.path for schema in example.schemas]
"file_dep": [schema.file_path for schema in example.schemas]
+ [schema.meta_schema_path for schema in example.schemas]
+ [CORE_SCHEMA_PATH, BASE_META_SCHEMA_PATH, Path(SOURCE_PATH, "schema_to_json.py")],
"targets": [schema.json_schema_path for schema in example.schemas],
Expand Down Expand Up @@ -88,7 +95,7 @@ def task_generate_markdown():
yield {
"name": name,
"targets": [template.markdown_output_path for template in example.doc_templates],
"file_dep": [schema.path for schema in example.schemas]
"file_dep": [schema.file_path for schema in example.schemas]
+ [template.path for template in example.doc_templates]
+ [Path(SOURCE_PATH, "docs", "grid_table.py")],
"task_dep": [f"validate_schemas:{name}"],
Expand All @@ -97,20 +104,33 @@ def task_generate_markdown():
}


def task_generate_cpp_code():
@task_params([{'name':'level',
'short':'l',
'long': 'level',
'type': str,
'default': "CRITICAL",
'choices': (("DEBUG",""),("INFO",""),("WARNING",""),("ERROR",""),("CRITICAL","")),
'help': 'Set the logger level.'}]
)
def task_generate_cpp_code(level):
"""Generate CPP headers and source for example schema."""
def set_log_level(level):
logging.getLogger().setLevel(level)

for example in examples:
name = Path(example.root_directory).name
yield {
"name": name,
"task_dep": [f"validate_schemas:{name}"],
"file_dep": [schema.path for schema in example.cpp_schemas]
"file_dep": [schema.file_path for schema in example.cpp_schemas]
+ [schema.meta_schema_path for schema in example.schemas]
+ [CORE_SCHEMA_PATH, BASE_META_SCHEMA_PATH, Path(SOURCE_PATH, "header_entries.py")],
"targets": [schema.cpp_header_path for schema in example.cpp_schemas]
+ [schema.cpp_source_path for schema in example.cpp_schemas]
+ example.cpp_support_headers(),
"actions": [(example.generate_cpp_headers, [])],
+ [CORE_SCHEMA_PATH, BASE_META_SCHEMA_PATH, Path(SOURCE_PATH, "cpp", "header_entries.py"), Path(SOURCE_PATH, "cpp", "cpp_entries.py")],
"targets": [schema.cpp_header_file_path for schema in example.cpp_schemas]
+ [schema.cpp_source_file_path for schema in example.cpp_schemas]
+ example.cpp_support_headers + [example.cpp_output_dir / "CMakeLists.txt", example.cpp_output_dir / "src" / "CMakeLists.txt"],
"actions": [(set_log_level, [level]),
(load_extensions, [Path(example.root_directory, "cpp", "extensions")]),
(example.generate_cpp_project, [["https://github.com/nlohmann/json.git", "https://github.com/bigladder/btwxt.git", "https://github.com/bigladder/courier.git", "https://github.com/fmtlib/fmt.git"]])],
"clean": True,
}

Expand All @@ -122,7 +142,7 @@ def task_generate_web_docs():
yield {
"name": name,
"task_dep": [f"validate_schemas:{name}", f"generate_json_schemas:{name}", f"validate_example_files:{name}"],
"file_dep": [schema.path for schema in example.schemas]
"file_dep": [schema.file_path for schema in example.schemas]
+ [template.path for template in example.doc_templates]
+ [Path(SOURCE_PATH, "docs", "mkdocs_web.py")],
"targets": [Path(example.web_docs_directory_path, "public")],
Expand Down
170 changes: 170 additions & 0 deletions examples/aosmith/schema/ASHRAE205.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# ASHRAE205.schema.yaml
# The purpose of this "open205 schema" is to provide a single source generator format from which
# all open205 standard materials, both normative and informative, will be created.

# YAML single-source files will be created in accordance with the open205 schema.

# Meta

Schema:
Object Type: "Meta"
Title: "ASHRAE 205"
Description: "Base schema for ASHRAE 205 representations"
Version: "0.2.0"

#Data Group Templates

RepresentationSpecificationTemplate:
Object Type: "Data Group Template"
Required Data Elements:
metadata:
Required: True
performance:
Required: True
description:
Required: False

HeatSourceTemplate:
Object Type: "Data Group Template"
Required Data Elements:
metadata:
Required: True
performance:
Required: True
description:
Required: False

# Common Enumerations

SchemaType:
Object Type: "Enumeration"
Enumerators:
RS0001:
Description: "Liquid-Cooled Chiller"
RS0002:
Description: "Unitary Cooling Air-Conditioning Equipment"
RS0003:
Description: "Fan Assembly"
RS0004:
Description: "Air-to-Air Direct Expansion Refrigerant Coil System"
RS0005:
Description: "Motor"
RS0006:
Description: "Electronic Motor Drive"
RS0007:
Description: "Mechanical Drive"
RSINTEGRATEDWATERHEATER:
Description: "Integrated Heat-Pump Water Heater"
RSTANK:
Description: "Water Tank"
RSRESISTANCEWATERHEATSOURCE:
Description: "Resistance Water Heat Source"
RSCONDENSERWATERHEATSOURCE:
Description: "Condenser Water Heat Source"
HPWHSIMINPUT:
Description: "Input required to describe a heat pump water heating system in HPWHsim"

CompressorType:
Object Type: "Enumeration"
Enumerators:
RECIPROCATING:
Description: "Reciprocating compressor"
Display Text: "Reciprocating"
SCREW:
Description: "Screw compressor"
Display Text: "Screw"
CENTRIFUGAL:
Description: "Centrifugal compressor"
Display Text: "Centrifugal"
ROTARY:
Description: "Rotary compressor"
Display Text: "Rotary"
SCROLL:
Description: "Scroll compressor"
Display Text: "Scroll"

CompressorSpeedControlType:
Object Type: "Enumeration"
Enumerators:
DISCRETE:
Description: "Compressor loading is controlled by cycling between one or more discrete stages"
Display Text: "Discrete"
CONTINUOUS:
Description: "Compressor loading is controlled by continuously varying the speed of the compressor"
Display Text: "Continuous"

CondenserType:
Object Type: "Enumeration"
Enumerators:
AIR:
Description: "Air-cooled condenser"
Display Text: "Air"
LIQUID:
Description: "Liquid-cooled condenser"
Display Text: "Liquid"
EVAPORATIVE:
Description: "Evaporative condenser"
Display Text: "Evaporative"

LiquidConstituent:
Object Type: "Enumeration"
Enumerators:
WATER:
Description: "Water"
Display Text: "Water"
PROPYLENE_GLYCOL:
Description: "Propylene glycol"
Display Text: "Propylene Glycol"
ETHYLENE_GLYCOL:
Description: "Ethylene glycol"
Display Text: "Ethylene Glycol"
SODIUM_CHLORIDE:
Description: "Sodium chloride"
Display Text: "Sodium Chloride"
CALCIUM_CHLORIDE:
Description: "Calcium chloride"
Display Text: "Calcium Chloride"
ETHANOL:
Description: "Ethanol"
Display Text: "Ethanol"
METHANOL:
Description: "Methanol"
Display Text: "Methanol"

ConcentrationType:
Object Type: "Enumeration"
Enumerators:
BY_VOLUME:
Description: "Concentration is defined as a fraction of total liquid mixture volume"
Display Text: "By Volume"
BY_MASS:
Description: "Concentration is defined as a fraction of total liquid mixture mass"
Display Text: "By Mass"

# Reusable Data Groups
LiquidMixture:
Object Type: "Data Group"
Data Elements:
liquid_components:
Description: "An array of all liquid components within the liquid mixture"
Data Type: "[{LiquidComponent}]"
Required: True
Notes: "Array may contain a single component"
concentration_type:
Description: "Defines whether concentration is defined on a volume or mass basis"
Data Type: "<ConcentrationType>"
Required: True

LiquidComponent:
Object Type: "Data Group"
Data Elements:
liquid_constituent:
Description: "Substance of this component of the mixture"
Data Type: "<LiquidConstituent>"
Required: True
concentration:
Description: "Concentration of this component of the mixture"
Data Type: "Numeric"
Constraints: [">=0.0", "<=1.0"]
Notes: "If omitted, assume equal distribution with any other component with no defined concentration (e.g., can be left blank for the primary component)"

28 changes: 28 additions & 0 deletions examples/aosmith/schema/CentralWaterHeatingSystem.schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Schema:
Object Type: "Meta"
References:
- "RSTANK"
- "HeatSourceConfiguration"
# - "RSAIRTOWATERHEATPUMP" # TODO: Add
Title: "Central Water Heating System"
Description: "Components that make up a central water heating system"
Version: "0.1.0"
Root Data Group: CentralWaterHeatingSystem

CentralWaterHeatingSystem:
Object Type: "Data Group"
Data Elements:
tank:
Description: "The corresponding Standard 205 tank representation"
Data Type: "{RSTANK}"
Required: True
heat_source_configurations:
Description: "Describes how the heat sources are configured within the tank"
Data Type: "[{HeatSourceConfiguration}]"
primary_heat_source_id:
Description: "Turns on independently of other heat sources"
Data Type: "String" # TODO: Make an actual reference type (need to use 232 compliant Lattice)
standby_power:
Description: "Power drawn when system is in standby mode"
Data Type: "Numeric"
Constraints: ">0"
Loading
Loading