Skip to content

Commit

Permalink
Pre-commit and format markdown (#682)
Browse files Browse the repository at this point in the history
* initial formatting

* fix issues, general cleanup

* un-indent code blocks, fix changelog header

* e.g., and i.e.,
  • Loading branch information
nllong authored Dec 17, 2024
1 parent 900532c commit c3ace89
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 212 deletions.
21 changes: 20 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
"version": "0.2",
"language": "en",
"words": [
"ambr",
"armhf",
"autoload",
"blackbox",
"borefield",
"buildingslibrary",
"buildingspy",
"buildx",
"Combi",
Expand All @@ -19,31 +22,47 @@
"HVAC",
"IBPSA",
"interconnectivity",
"IWEC",
"Jing",
"levelname",
"libfortran",
"linecount",
"markdownlint",
"massflow",
"maxdepth",
"mfrt",
"microgrid",
"miniconda",
"mkdocs",
"mkdocstrings",
"Modelica",
"MODELICAPATH",
"mofile",
"mopt",
"nllong",
"nrel",
"openstudio",
"Optimica",
"oversizing",
"pycache",
"pyenv",
"pylint",
"pyproject",
"pytest",
"redeclarations",
"Reparse",
"searchpath",
"setpoint",
"tanushree",
"Templatized",
"timeseries",
"timestep",
"timesteps",
"urbanopt",
"vtnate"
"venv",
"virtualenv",
"vtnate",
"weatherfile"
],
"flagWords": [
"hte"
Expand Down
4 changes: 4 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#### Any background context you want to provide?

#### What does this PR accomplish?

#### How should this be manually tested?

#### What are the relevant tickets?

#### Screenshots (if appropriate)
9 changes: 9 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"default": true,
"MD013": false,
"MD003": {
"style": "atx"
},
"MD041": false,
"MD024": false
}
13 changes: 12 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,22 @@ repos:
pass_filenames: false
# https://docs.astral.sh/ruff/integrations/#pre-commit
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
rev: v0.8.3
hooks:
# Run the linter
- id: ruff
# unsafe fixes: https://docs.astral.sh/ruff/linter/#fixes
args: [--fix, --exit-non-zero-on-fix, --output-format=full, --unsafe-fixes]
# Run the formatter
- id: ruff-format
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.43.0
hooks:
- id: markdownlint
name: markdownlint
entry: markdownlint --fix
language: node
types: [markdown]
args: [
"--config", ".markdownlint.json"
]
280 changes: 142 additions & 138 deletions CHANGELOG.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

The GeoJSON Modelica Translator (GMT) is a one-way trip from GeoJSON in combination with a well-defined instance of the system parameters schema to a Modelica package with multiple buildings loads, energy transfer stations, distribution networks, and central plants. The project will eventually allow multiple paths to build up different district heating and cooling system topologies; however, the initial implementation is limited to 4GDHC and 5GDHC.

Documentation can be found at [https://nrel.github.io/geojson-modelica-translator]()
Documentation can be found at [https://nrel.github.io/geojson-modelica-translator](https://nrel.github.io/geojson-modelica-translator)

The project is motivated by the need to easily evaluate district energy systems. The goal is to eventually cover the various generations of heating and cooling systems as shown in the figure below. The need to move towards 5GDHC systems results in higher efficiencies and greater access to additional waste-heat sources.

Expand Down Expand Up @@ -59,12 +59,12 @@ The building loads can be defined multiple ways depending on the fidelity of the

1. Create a branch named `Release 0.x.`
1. Update version in pyproject.toml
2. Update CHANGELOG using GitHub's "Autogenerate Change Log" feature, using `develop` as the target
3. After tests pass, merge branch into develop
4. From local command line, merge develop into main with: `git checkout main; git pull; git merge --ff-only origin develop; git push`
5. In GitHub, tag the release against main. Copy and paste the changelog entry into the notes. Verify the release is posted to PyPI.
1. Update CHANGELOG using GitHub's "Autogenerate Change Log" feature, using `develop` as the target
1. After tests pass, merge branch into develop
1. From local command line, merge develop into main with: `git checkout main; git pull; git merge --ff-only origin develop; git push`
1. In GitHub, tag the release against main. Copy and paste the changelog entry into the notes. Verify the release is posted to PyPI.

### Build and release the documentation:
### Build and release the documentation

During development we can [serve docs locally](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write) and view updates as they are made.

Expand Down
2 changes: 0 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
# Changelog

{!CHANGELOG.md!}
66 changes: 32 additions & 34 deletions docs/developer_resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,37 @@

## Tests

Tests are run with pytest, e.g.
Tests are run with pytest, e.g.,

```bash
poetry run pytest
poetry run pytest
```


## Snapshot Testing

Some tests use [syrupy](https://github.com/tophat/syrupy) to compare generated modelica models to saved "snapshots" of the models (saved as .ambr files).

Snapshots should only be updated if we have changed how a model is generated, and we *know* the new version of the model is the correct version. To update all snapshots, you can run the following and commit the new snapshot files.

```bash
poetry run pytest --snapshot-update
poetry run pytest --snapshot-update
```


## Design Overview

The GMT is designed to create an arbitrary number of user-configured models attached to other user-configured models to represent a district energy system.
GMT has "building blocks" that it uses to define and attach models, which currently include: Energy Transfer Stations (ETSs), Loads, Networks, and Plants.

Each block type is a collection of models, e.g. the Loads includes time series and spawn models. A model in GMT refers to an abstracted Modelica model. It generates Modelica code (the Modelica model) and is used to define attachments to other models.
Each block type is a collection of models, e.g., the Loads includes time series and spawn models. A model in GMT refers to an abstracted Modelica model. It generates Modelica code (the Modelica model) and is used to define attachments to other models.

Each block type can attach to other specific block types. For example, you can attach a load to an ETS, but you cannot attach a load to a network. However, some models (i.e. 5G) have an ETS embedded in them.
Each block type can attach to other specific block types. For example, you can attach a load to an ETS, but you cannot attach a load to a network. However, some models (i.e., 5G) have an ETS embedded in them.

Each block type has a corresponding directory inside of `geojson_modelica_translator/model_connectors`, which contains its different model types (e.g. for Loads it contains the Time Series model and others).
Each block type has a corresponding directory inside of `geojson_modelica_translator/model_connectors`, which contains its different model types (e.g., for Loads it contains the Time Series model and others).

Because models are different, even within a block type (e.g., different properties and maybe even ports), the GMT uses the concept of couplings for attaching models. Couplings define how two *specific* models attach in modelica.
For example, a coupling could define how the time series load actually attaches to the heating indirect ETS.

As an aside, if the GMT reached a point where all models within a block type implemented the same interface then couplings would not be necessary.
As an aside, if the GMT reached a point where all models within a block type implemented the same interface then couplings would not be necessary.

## Getting Started as a Developer

Expand All @@ -46,20 +44,20 @@ Follow the instructions below in order to configure your local environment:
- Get the Modelica Buildings Library. See the documentation at [MBL Installation](getting_started.md#mbl-installation)

- Clone [the GMT repo](https://github.com/urbanopt/geojson-modelica-translator) into a working directory
- (optional/as-needed) Add Python 3 to the environment variables
- As general guidance, we recommend using virtual environments to avoid dependencies colliding between your Python projects. [venv](https://docs.python.org/3/library/venv.html) is the Python native solution that will work everywhere, though other options may be more user-friendly:
- [pyenv](https://github.com/pyenv/pyenv) and [the virtualenv plugin](https://github.com/pyenv/pyenv-virtualenv) work together nicely for Linux/Mac machines
- [virtualenv](https://virtualenv.pypa.io/en/latest/)
- [miniconda](https://docs.conda.io/projects/miniconda/en/latest/)
- (optional/as-needed) Add Python 3 to the environment variables
- As general guidance, we recommend using virtual environments to avoid dependencies colliding between your Python projects. [venv](https://docs.python.org/3/library/venv.html) is the Python native solution that will work everywhere, though other options may be more user-friendly:
- [pyenv](https://github.com/pyenv/pyenv) and [the virtualenv plugin](https://github.com/pyenv/pyenv-virtualenv) work together nicely for Linux/Mac machines
- [virtualenv](https://virtualenv.pypa.io/en/latest/)
- [miniconda](https://docs.conda.io/projects/miniconda/en/latest/)
- For developers, dependency management is through [Poetry](https://python-poetry.org/docs/). Poetry can be acquired by running `pip install poetry`.
- If you haven't already installed a virtual environment, Poetry will automatically create a simplified environment for your project.
- If you haven't already installed a virtual environment, Poetry will automatically create a simplified environment for your project.
- Move to the GMT root directory and run `poetry install` to install the dependencies.
- Verify that everything is installed correctly by running `poetry run pytest -m 'not compilation and not simulation and not dymola'`. This will run all the unit and integration tests.
- Follow the instructions below to install pre-commit.
- To confirm that models will build and simulate, you can run

```bash
poetry run pytest -m 'not dymola' --cov-report term-missing --cov .
poetry run pytest -m 'not dymola' --cov-report term-missing --cov .
```

The tests should all pass assuming the libraries, Docker, and all dependencies are installed correctly on your computer. Also, there will be a set
Expand All @@ -73,13 +71,13 @@ To enable pre-commit for your local development process, run the following from
GMT:

```bash
pre-commit install
pre-commit install
```

To run pre-commit against the files without calling git commit, then run the following. This is useful when cleaning up the repo before committing. CI will fail if pre-commit hasn't been run locally.

```bash
pre-commit run --all-files
pre-commit run --all-files
```

## Adding New Models
Expand All @@ -88,22 +86,22 @@ To add a new model you have to do the following:

1. Define the model's python class: First, create a new python file and class under its respective directory in model_connectors. Follow the patterns of existing classes.

2. Create coupling files: For every model that can be linked to, create a <ModelA>_<ModelB> directory in the couplings directory. The two files ComponentDefinitions.mopt and ConnectStatements.mopt must exist in this directory. See more information on the content of the coupling files below in the *Couplings* sections.
1. Create coupling files: For every model that can be linked to, create a `<ModelA>_<ModelB>` directory in the couplings directory. The two files ComponentDefinitions.mopt and ConnectStatements.mopt must exist in this directory. See more information on the content of the coupling files below in the *Couplings* sections.

3. Create the instance file: In the templates directory, you must define <ModelName>_Instance.mopt which is the template that instantiates the system in the district model.
1. Create the instance file: In the templates directory, you must define `<ModelName>_Instance.mopt` which is the template that instantiates the system in the district model.

See the notes below for more information.

### Couplings

A coupling defines the Modelica code necessary for interfacing two specific models, e.g. a time series load and heating indirect ETS.
A coupling defines the Modelica code necessary for interfacing two specific models, e.g., a time series load and heating indirect ETS.
Each coupling is unique in its requirements:

- What additional components are necessary, for example there might be some sensor between system A and B, or maybe B requires a pump when A is a specific model type
- What ports are connected, for example connecting ports of model A and model B

Thus each coupling must define two template files, ComponentDefinitions.mopt and ConnectStatements.mopt, respectively. These files must be placed in the directory `couplings/templates/<model A>_<model B>/`.
In general, the **order of the names** should **follow the order of system types** if you laid out the district system starting with loads on the far left and plants on the far right (e.g. load before ETS, ETS before network, network before plant).
Thus each coupling must define two template files, `ComponentDefinitions.mopt` and `ConnectStatements.mopt`, respectively. These files must be placed in the directory `couplings/templates/<model A>_<model B>/`.
In general, the **order of the names** should **follow the order of system types** if you laid out the district system starting with loads on the far left and plants on the far right (e.g., load before ETS, ETS before network, network before plant).

### District system

Expand All @@ -130,18 +128,18 @@ Each model generates one or more Modelica files to define its model. The templat

### Coupling Component Definitions

This is the template which defines new components/variables necessary for a coupling. More specifically, these are the partial template files at model_connectors/couplings/templates/<coupling name>/ComponentDefinitions.mopt. These templates have access to:
This is the template which defines new components/variables necessary for a coupling. More specifically, these are the partial template files at `model_connectors/couplings/templates/<coupling name>/ComponentDefinitions.mopt`. These templates have access to:

- `globals`: global variables (those defined in the district.py, such as medium_w = MediumW)
- `coupling`: contains the coupling id, as well as references to the coupled models under their respective types (e.g. coupling.load.id or coupling.network.id). You should append `coupling.id` to any variable identifiers to prevent name collisions. For example, instead of just writing `parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal` you should do `parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal_{{ coupling.id }}` as well as any place where you would reference that variable.
- `coupling`: contains the coupling id, as well as references to the coupled models under their respective types (e.g., coupling.load.id or coupling.network.id). You should append `coupling.id` to any variable identifiers to prevent name collisions. For example, instead of just writing `parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal` you should do `parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal_{{ coupling.id }}` as well as any place where you would reference that variable.
- `graph`: an instance of the CouplingGraph class, where all couplings are located. It can provide useful methods for accessing couplings throughout the entire system. Refer to the python class to see what it can do.
- `sys_params`: an object containing data from the system parameters file
- `district_system`: contains the data from the district_system portion of the system parameters file
- `building`: if the coupling includes a load, this object will be included as well -- if there's no as part of the coupling this object will NOT be present. It contains the building-specific system parameters pulled from the system parameters JSON file.

### Coupling Connect Statements

This is the template which defines connect statements to be inserted into the equation section. More specifically, these are the partial template files at model_connectors/couplings/templates/<coupling name>/ConnectStatements.mopt. These templates have access to:
This is the template which defines connect statements to be inserted into the equation section. More specifically, these are the partial template files at `model_connectors/couplings/templates/<coupling name>/ConnectStatements.mopt`. These templates have access to:

- `globals`: same as Coupling Component Definitions context
- `coupling`: same as Coupling Component Definitions context. Just like with the component definitions template, you should use the coupling.id to avoid variable name collisions.
Expand All @@ -164,9 +162,9 @@ The Simulation Mapper Class can operate at multiple levels:

1. The GeoJSON level -- input: geojson, output: geojson+
2. The Load Model Attachment -- input: geojson+, output: multiple files related to building load models (spawn, rom, csv)
3. The Translation to Modelica -- input: custom format, output: .mo (example inputs: geojson+, system design parameters). The translators are implicit to the load model connectors as each load model requires different paramters to calculate the loads.
3. The Translation to Modelica -- input: custom format, output: .mo (example inputs: geojson+, system design parameters). The translators are implicit to the load model connectors as each load model requires different parameters to calculate the loads.

In some cases, the Level 3 case (translation to Modelica) is a blackbox method (e.g. TEASER) which prevents a
In some cases, the Level 3 case (translation to Modelica) is a blackbox method (e.g., TEASER) which prevents a
simulation mapper class from existing at that level.

## Running Simulations
Expand All @@ -176,13 +174,13 @@ The GeoJSON to Modelica Translator contains a `ModelicaRunner.run_in_docker(...)
## Release Instructions

1. Create a branch named `Release 0.x.`
1. Update version in pyproject.toml
2. Update CHANGELOG using GitHub's "Autogenerate Change Log" feature, using `develop` as the target
3. After tests pass, merge branch into develop
4. From local command line, merge develop into main with: `git checkout main; git pull; git merge --ff-only origin develop; git push`
5. In GitHub, tag the release against main. Copy and paste the changelog entry into the notes. Verify the release is posted to PyPI.
1. Update version in `pyproject.toml`
1. Update CHANGELOG using GitHub's "Autogenerate Change Log" feature, using `develop` as the target
1. After tests pass, merge branch into develop
1. From local command line, merge develop into main with: `git checkout main; git pull; git merge --ff-only origin develop; git push`
1. In GitHub, tag the release against main. Copy and paste the changelog entry into the notes. Verify the release is posted to PyPI.

### Build and release the documentation:
### Build and release the documentation

During development we can [serve docs locally](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write) and view updates as they are made.

Expand Down
Loading

0 comments on commit c3ace89

Please sign in to comment.