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

Merged plugins 232 #63

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 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
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




25 changes: 13 additions & 12 deletions dodo.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from lattice import Lattice
from pathlib import Path
from lattice import Lattice
from lattice.cpp.header_entry_extension_loader import load_extensions

from doit.tools import create_folder

Expand Down Expand Up @@ -29,7 +30,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 +45,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 +59,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 +89,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 @@ -104,13 +105,13 @@ def task_generate_cpp_code():
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": [(load_extensions, [Path(example.root_directory, "cpp", "extensions")]), (example.generate_cpp_project, [["https://github.com/nlohmann/json.git", "https://github.com/bigladder/courier.git", "https://github.com/fmtlib/fmt.git"]])],
"clean": True,
}

Expand All @@ -122,7 +123,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
28 changes: 28 additions & 0 deletions examples/fan_spec/cpp/extensions/grid_var_enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from dataclasses import dataclass
from lattice.cpp.header_entries import HeaderEntry
from lattice.cpp.header_entries import register_data_element_operation

@dataclass
class GridVarCounterEnum(HeaderEntry):
elements_dict: dict

def __post_init__(self):
super().__post_init__()
self.type = "enum"
self._closure = "};"
self._enumerants = list()

for element in self.elements_dict:
self._enumerants.append(f"{element}_index")
self._enumerants.append("index_count");

def __str__(self):
enums = self._enumerants
tab = "\t"
entry = f"{self._level * tab}{self.type} {self._opener}\n"
entry += ",\n".join([f"{(self._level + 1) * tab}{e}" for e in enums])
entry += f"\n{self._level * tab}{self._closure}"
return entry

def register():
register_data_element_operation("GridVariablesTemplate", GridVarCounterEnum)
29 changes: 29 additions & 0 deletions examples/fan_spec/cpp/extensions/lookup_struct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import re
from dataclasses import dataclass
from lattice.cpp.header_entries import DataElement, Struct
from lattice.cpp.header_entries import register_data_group_operation

@dataclass
class LookupStruct(Struct):
"""
Special case struct for Lookup Variables. Its str overload adds a LookupStruct declaration.
"""

def __str__(self):
"""Two C++ entries share the schema child-entries, so one HeaderEntry subclass creates both."""
struct = super().__str__()

# Add a LookupStruct that offers a SOA access rather than AOS
tab = "\t"
struct += "\n"
struct += f"{self._level * tab}{self.type} {self.name}Struct {self._opener}\n"
for c in [ch for ch in self.child_entries if isinstance(ch, DataElement)]:
m = re.match(r'std::vector\<(.*)\>', c.type)
assert m is not None
struct += f"{(self._level+1) * tab}{m.group(1)} {c.name};\n"
struct += f"{self._level * tab}{self._closure}"

return struct

def register():
register_data_group_operation("LookupVariablesTemplate", LookupStruct)
7 changes: 4 additions & 3 deletions examples/fan_spec/examples/Fan-Continuous.RS0003.a205.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"metadata": {
"schema_author": "ASHRAE_205",
"schema": "RS0003",
"schema_name": "RS0003",
"schema_version": "0.2.0",
"author": "SSPC 205 Working Group",
"description": "Continuous Fan",
"id": "123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2020-05-11T00:00Z",
"version": 1,
"time_of_creation": "2020-05-11T00:00Z",
"version": "1.0.0",
"disclaimer": "Example data not to be used for simulation"
},
"description": {
Expand Down
8 changes: 4 additions & 4 deletions examples/fan_spec/schema/ASHRAE205.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ PerformanceMapTemplate:
GridVariablesTemplate:
Object Type: "Data Group Template"
Required Data Types:
- "[Numeric][1..]"
- "[Integer][1..]"
- "[Numeric]"
- "[Integer]"
Data Elements Required: True

LookupVariablesTemplate:
Object Type: "Data Group Template"
Required Data Types:
- "[Numeric][1..]"
- "[Integer][1..]"
- "[Numeric]"
- "[Integer]"
Data Elements Required: True

RepresentationSpecificationTemplate:
Expand Down
66 changes: 44 additions & 22 deletions examples/fan_spec/schema/RS0003.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,18 @@ SystemCurve:
Data Elements:
standard_air_volumetric_flow_rate:
Description: "Volumetric air flow rate through an air distribution system at standard air conditions"
Data Type: "[Numeric][2..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[2..]"
Units: "m3/s"
Required: True
static_pressure_difference:
Description: "Static pressure difference of an air distribution system"
Data Type: "[Numeric][2..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[2..]"
Units: "Pa"
Required: True

Expand All @@ -247,14 +251,18 @@ GridVariablesContinuous:
Data Elements:
standard_air_volumetric_flow_rate:
Description: "Volumetric air flow rate through fan assembly at standard air conditions"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "m3/s"
Required: True
static_pressure_difference:
Description: "External static pressure across fan assembly at dry coil conditions"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "Pa"
Notes: "Any static pressure deduction (or addition) for wet coil is specified by `wet_pressure_difference` in 'assembly_components' data group"
Required: True
Expand All @@ -265,14 +273,18 @@ LookupVariablesContinuous:
Data Elements:
impeller_rotational_speed:
Description: "Rotational speed of fan impeller"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "rev/s"
Required: True
shaft_power:
Description: "Mechanical shaft power input to fan assembly"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "W"
Notes: "Does not include the mechanical efficiency of any mechanical drive used to modify rotational speed between the motor and impeller"
Required: True
Expand All @@ -296,15 +308,19 @@ GridVariablesDiscrete:
Data Elements:
speed_number:
Description: "Number indicating discrete speed of fan impeller in rank order (with 1 being the lowest speed)"
Data Type: "[Integer][1..]"
Constraints: ">=0"
Data Type: "[Integer]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "-"
Notes: "Data shall be provided for all allowable discrete speeds or settings"
Required: True
static_pressure_difference:
Description: "External static pressure across fan assembly at dry coil conditions"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "Pa"
Notes: "Any static pressure deduction (or addition) for wet coil is specified by `wet_pressure_difference` in 'assembly_components' data group"
Required: True
Expand All @@ -315,20 +331,26 @@ LookupVariablesDiscrete:
Data Elements:
standard_air_volumetric_flow_rate:
Description: "Volumetric air flow rate through fan assembly at standard air conditions"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "m3/s"
Required: True
shaft_power:
Description: "Mechanical shaft power input to fan assembly"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "W"
Notes: "Does not include the mechanical efficiency of any mechanical drive used to modify rotational speed between the motor and impeller"
Required: True
impeller_rotational_speed:
Description: "Rotational speed of fan impeller"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "rev/s"
Required: True
26 changes: 18 additions & 8 deletions examples/fan_spec/schema/RS0005.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,18 @@ GridVariables:
Data Elements:
shaft_power:
Description: "Delivered rotational shaft power"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "W"
Required: True
shaft_rotational_speed:
Description: "Rotational speed of shaft"
Data Type: "[Numeric][1..]"
Constraints: ">=0.0"
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "[1..]"
Units: "rev/s"
Required: True

Expand All @@ -120,14 +124,20 @@ LookupVariables:
Data Elements:
efficiency:
Description: "Efficiency of motor"
Data Type: "[Numeric][1..]"
Constraints: [">=0.0", "<=1.0"]
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "<=1.0"
- "[1..]"
Units: "-"
Notes: "Defined as the ratio of mechanical shaft power to electrical input power of the motor"
Required: True
power_factor:
Description: "Power factor of the motor"
Data Type: "[Numeric][1..]"
Constraints: [">=0.0", "<=1.0"]
Data Type: "[Numeric]"
Constraints:
- ">=0.0"
- "<=1.0"
- "[1..]"
Units: "-"
Required: True
Loading
Loading