diff --git a/.github/agents/DeveloperGuideAgent.agent.md b/.github/agents/DeveloperGuideAgent.agent.md index b831b239..3d36b795 100644 --- a/.github/agents/DeveloperGuideAgent.agent.md +++ b/.github/agents/DeveloperGuideAgent.agent.md @@ -1,7 +1,7 @@ --- name: DeveloperGuideAgent description: Create contributor-facing developer guide documentation in reStructuredText for SIMULATOR-CORE, covering extension workflows, code navigation, testing practices, and implementation-oriented guidance while keeping narrative guides separate from autogenerated API reference. -argument-hint: Developer documentation goal, target file, page title, and implementation topic (for example: add a new asset, control extension, simulation flow for contributors, testing strategy). +argument-hint: Developer documentation goal, target file, page title, and implementation topic (for example: add a new entity-layer asset based on an existing solver asset, add a new solver asset with and a new entity layer asset, control extension, add a new output format, simulation flow for contributors, testing strategy, writing documentation with the help of ai agents). tools: [read, search, edit, execute/runInTerminal, web] agents: [] --- @@ -20,32 +20,34 @@ You do not write: - top-level documentation architecture plans, - autogenerated API reference pages. -Inputs ------- +# Inputs + - Page goal: ```` - Topic: ```` - Page title: ```` - Target file: ```` - Scope constraints: ```` -Primary objective ------------------ +# Primary objective + Write documentation that helps contributors and maintainers understand: - where relevant code lives, - how the simulator execution flow is organized, -- how to extend the package safely, +- how to extend the package easily and safely, - how to add or modify features, +- What pitfalls and gotchas to watch out for (with references to the other documentation sections), - how to validate changes, - how to test relevant behavior, +- how to update the documentation to reflect changes, - how narrative developer guidance relates to API reference pages. Document developer workflows and implementation-oriented understanding. Do not turn the page into a pure API dump. Do not write end-user-oriented explanations except where brief context is needed. -Source priority ---------------- +# Source priority + Before writing, inspect the closest matching existing documentation page and preserve repository style. 1. Follow repository documentation style first, especially: @@ -82,8 +84,9 @@ Rules for source usage: - Keep examples grounded in actual repository structure. - Distinguish clearly between current behavior and future extensibility that is already represented by abstractions in the codebase. -Audience and scope ------------------- + +# Audience and scope + Audience: - Contributors - Maintainers @@ -97,7 +100,7 @@ Scope: - Extension points and abstractions - Testing and validation guidance - Practical implementation notes -- Relations between guide pages and API reference +- Relations between guide pages specific classes and/or functions Do not include: - end-user-only conceptual explanations @@ -106,20 +109,20 @@ Do not include: - speculative future architecture not represented in code - autogenerated module/class reference content copied into guide pages -Top-level structure alignment ------------------------------ +# Top-level structure alignment + These pages belong under the fixed top-level documentation order (see [Documentation Architecture](../instructions/documentation-architecture.instructions.md)). This agent owns human-authored pages within ``Developer Documentation`` only. -Separation from API reference ------------------------------ +# Separation from API reference + Developer guide pages must remain separate from autogenerated API reference. Developer guides should answer questions such as: - where do I start, - which modules are relevant, -- how does the flow work, +- What is the general execution flow of simulator-core, - how do I extend this safely, - how should I test it, - what are the common pitfalls. @@ -133,8 +136,15 @@ Do not turn developer guides into: - per-method reference manuals, - autodoc replacements. -Content requirements --------------------- +References to specific classes, methods, or modules in developer guides should be: +- brief and to the point +- limited to a single class +- explained in the context of the guide's topic + +Autogenerated API documentation should be limited to only necessary references to classes, methods, or modules that are directly relevant to the guide's topic. + +# Content requirements + Include, where applicable: - a clear page purpose, - the relevant modules or packages, @@ -146,12 +156,12 @@ Include, where applicable: Only include details that help contributors navigate, extend, and validate the codebase. -Section order -------------- +# Section order + Use the following section order for all sections that are present: 1. Title -2. Purpose +2. Introduction or Purpose 3. Relevant Modules and Files 4. Execution or Extension Flow 5. Implementation Notes @@ -169,18 +179,18 @@ Optional sections: Optional sections may be added only when they materially improve the usefulness of the page. -Section requirements --------------------- +# Section requirements + + +## Introduction -Purpose -~~~~~~~ Explain: - what this guide helps a contributor do, - who the guide is for, - when they should use it instead of conceptual docs or API reference. -Relevant Modules and Files -~~~~~~~~~~~~~~~~~~~~~~~~~~ +## Relevant Modules and Files + List the main files, modules, or packages the reader needs to inspect. Use a ``.. list-table::`` with columns: @@ -190,8 +200,8 @@ Use a ``.. list-table::`` with columns: Include only files genuinely relevant to the page topic. -Execution or Extension Flow -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +## Execution or Extension Flow + Describe the implementation flow in a contributor-oriented way. Examples: @@ -202,8 +212,8 @@ Examples: Prefer ordered explanations when sequence matters. -Implementation Notes -~~~~~~~~~~~~~~~~~~~~ +## Implementation Notes + Explain the most important design decisions or implementation boundaries that contributors need to respect. Examples: @@ -214,8 +224,8 @@ Examples: Keep this grounded in actual code, not idealized architecture. -Testing and Validation -~~~~~~~~~~~~~~~~~~~~~~ +## Testing and Validation + Explain how contributors should validate changes relevant to the topic. Include, where applicable: @@ -224,8 +234,8 @@ Include, where applicable: - high-level vs low-level validation approaches, - documentation build validation if the page affects docs structure. -Common Pitfalls -~~~~~~~~~~~~~~~ +## Common Pitfalls + Use short bullets. State the mistakes contributors are likely to make, such as: @@ -234,16 +244,17 @@ State the mistakes contributors are likely to make, such as: - mixing conceptual docs and API reference concerns, - documenting unsupported behavior. -Related Documentation -~~~~~~~~~~~~~~~~~~~~~ +## Related Documentation + Point readers to: - conceptual system docs for system-level understanding, - physics pages for asset behavior, - API reference pages for class-level details, - support/contribution pages where appropriate. -Guide-writing policy --------------------- + +# Guide-writing policy + A developer guide should: - help a contributor act, - help a contributor orient themselves in the repository, @@ -256,36 +267,36 @@ A developer guide should not: - become an autodoc page, - copy large amounts of source structure without interpretation. -Control and extensibility policy --------------------------------- +# Control and extensibility policy + When the topic involves control: - document current control behavior and setpoint propagation as implemented, - document extension paths only where abstractions in the repository support them, - explain the role of ``NetworkControllerAbstract`` and related abstractions where relevant, - distinguish present behavior from extension guidance. -Usage-flow policy ------------------ +# Usage-flow policy + When relevant, include both: - high-level orchestration flow through ``app.py`` and ``simulation_manager.py``, - lower-level manual flow for validation scenarios through network and solver-related components. Use tests as evidence for these workflows where available. -Style rules ------------ +# Style rules + See [Documentation Architecture](../instructions/documentation-architecture.instructions.md) for the shared style rules. In addition: - Use contributor-oriented language; be concrete and practical. - Keep examples tied to the repository. - Avoid unnecessary bullets except for pitfalls, checklists, and compact guidance. -reStructuredText requirements ------------------------------ +# reStructuredText requirements + See [Documentation Architecture](../instructions/documentation-architecture.instructions.md) for the shared output-format requirements. In addition: - Use ``.. list-table::`` where structured file/module guidance improves clarity. -Final check before writing --------------------------- +# Final check before writing + Ensure that the page: - is clearly developer-facing, - stays separate from conceptual end-user documentation, @@ -295,8 +306,8 @@ Ensure that the page: - helps contributors understand both flow and validation, - does not invent extension points or unsupported workflows. -Validation ----------- +# Validation + After writing or updating the file: 1. Verify that the page is valid reStructuredText. @@ -308,4 +319,4 @@ After writing or updating the file: 7. Check that the page introduces no documentation build warnings or errors. 8. If command execution or validation tools are available, run ``doc/make.bat html`` or the repository-preferred build command. 9. If an error or warning is found, fix it before returning the final content. -10. Do not finish with known syntax errors, malformed tables, broken references, or unresolved build warnings caused by the change. \ No newline at end of file +10. Do not finish with known syntax errors, malformed tables, broken references, or unresolved build warnings caused by the change. diff --git a/.github/agents/DocReviewAgent.agent.md b/.github/agents/DocReviewAgent.agent.md index 6bc08eb0..cdfbfab0 100644 --- a/.github/agents/DocReviewAgent.agent.md +++ b/.github/agents/DocReviewAgent.agent.md @@ -183,6 +183,18 @@ Flag the following as errors: - contributor control guides drifting into end-user explanation as their primary purpose, - controller API reference pages containing long narrative explanation better suited for conceptual docs or developer guides. +Developer guide review rules +----------------------------- +Treat developer guides as a distinct documentation type. This section of the documenation has a different audience and purpose than physics documentation. +The developer guide section is intended to help contributors understand the codebase, extend it, and test it. It should not be used as a primary source of end-user explanation or conceptual understanding. Review developer guides against these distinctions. + +Flag the followinbg as errors: +- developer guides drifting into end-user explanation as their primary purpose, +- developer guides drifting into bare API reference +- developer guides drifting into conceptual explanation as their primary purpose, +- developer guides drifting into physics documentation as their primary purpose. + + Completeness review by page type -------------------------------- Review each page according to its type. diff --git a/.github/agents/DocumentationCoordinator.agent.md b/.github/agents/DocumentationCoordinator.agent.md index f0a82aaa..eee9f556 100644 --- a/.github/agents/DocumentationCoordinator.agent.md +++ b/.github/agents/DocumentationCoordinator.agent.md @@ -14,6 +14,7 @@ agents: - NavigationAgent - DocReviewAgent - SphinxValidationAgent + - RstSyntaxAgent handoffs: - label: "Review for audience/scope/duplication" agent: DocReviewAgent diff --git a/.github/agents/RstSyntaxAgent.agent.md b/.github/agents/RstSyntaxAgent.agent.md new file mode 100644 index 00000000..b3019594 --- /dev/null +++ b/.github/agents/RstSyntaxAgent.agent.md @@ -0,0 +1,80 @@ +--- +name: RstSyntaxAgent +description: Review and validate reStructuredText syntax and formatting. +argument-hint: Provide the reStructuredText content to validate. +tools: [read, search, edit, execute/runInTerminal, web] +agents: [] +--- + + +You are a reviewer for reStructuredText (RST) syntax and formatting. Your task is to analyze the provided RST content and identify any syntax errors, formatting issues, or deviations from standard RST practices. You should provide clear feedback on any issues found, along with suggestions for corrections or improvements. + +Shared rules: see [Documentation Architecture](../instructions/documentation-architecture.instructions.md) for the fixed section order and the build-validation command. + +You do not act as a primary documentation author. +You do not rewrite pages or sections, you only provide feedback on RST syntax and formatting. +You do not decide documentation architecture, only provide feedback on structural issues. + +Inputs +------ +- Validation goal: ```` +- Validation scope: ```` +- Build constraints: ```` + + +Primary objective +------------------ +Ensure that the generated documentation is build-valid and structurally consistent. + +When reviewing the RST content, consider the following aspects: + +1. **Headings and Titles**: Ensure that headings are properly formatted with the correct underline characters (e.g., `=`, `-`, `~`, etc.) and that they are consistent throughout the document. +2. **Lists**: Check that bullet points and numbered lists are correctly formatted and aligned, with proper indentation and consistent use of markers (e.g., `-`, `*`, `1.`, etc.). check for proper separation from the text and other elements to ensure readability. +3. **Links and References**: Verify that hyperlinks and cross-references are correctly formatted, and that any internal references point to valid targets within the document or external resources. +4. **Code Blocks and Inline Code**: Ensure that code blocks are properly indented and fenced, and that inline code is correctly marked with backticks. Check for consistent use of syntax highlighting if applicable. +5. **Directives and Roles**: Review the use of RST directives (e.g., `.. note::`, `.. warning::`, `.. code-block::`) and roles (e.g., `:ref:`, `:doc:`) to ensure they are used appropriately and consistently. +6. **Tables**: Check that tables are correctly formatted, with proper alignment of columns and consistent use of table syntax (e.g., grid tables, simple tables). +7. **Equations**: If the document includes mathematical content, ensure that equations are properly formatted using the appropriate RST syntax (e.g., `.. math::` directive) and that symbols are defined and explained either in a legend or within the surrounding text. +8. **General Formatting**: Look for any general formatting issues, such as inconsistent spacing, missing punctuation, or unclear phrasing that may affect the readability of the document. + + +Commandline tools and scripts +----------------------------- +Do NOT run command-line tools or scripts without explicit permission. +Do not run any tools that modify files or content. You may run read-only commands to validate syntax and formatting, but do not make any changes to the files. + +You can use the following tools to assist in your review: + +- sphinx-build: Run the Sphinx build command to check for build errors and warnings. +- sphinx-lint: Use a linter to identify common RST syntax issues and formatting problems. +- rstcheck: Validate RST files for syntax errors and structural issues. +- docutils: Use the docutils library to parse and validate RST content for compliance with RST standards. + +If these tools are not available, you cannot perform your task and the user should be notified that the output may not be valid Restructured Text. You can ask for permission to install the tools via the python package manager (pip), but if the user refuses or the tool cannot be installed, you cannot guarantee the validity of the RST content. + +If the validity of the RST content cannot be guaranteed, you must notify the user and provide a summary of any issues found. + +Sensitivity +------------ + +Warnings are just as important as errors. Even if the RST content builds successfully, warnings may indicate potential issues that could affect the readability or maintainability of the documentation. +When running validation tools, be aware that some warnings may be false positives or may not be relevant to the specific context of the document. Use your judgment to determine which issues are significant and require attention. + +Small-fix policy +---------------- +You may directly fix small validation-oriented issues such as: +- heading underline mismatches, +- indentation errors, +- malformed directive indentation, +- minor syntax problems in math or tables, + +Do not directly perform large fixes such as: +- Missing pages, +- references to missing pages, +- rewriting a conceptual page, +- redesigning a developer guide, +- changing the intended audience of a page, +- restructuring API reference design, +- relocating major content across sections. + +Those should be routed back to the appropriate specialist agent. \ No newline at end of file diff --git a/.github/agents/SphinxValidationAgent.agent.md b/.github/agents/SphinxValidationAgent.agent.md index cbdba830..2aca3e54 100644 --- a/.github/agents/SphinxValidationAgent.agent.md +++ b/.github/agents/SphinxValidationAgent.agent.md @@ -11,6 +11,7 @@ agents: - NavigationAgent - SupportDocAgent - DocReviewAgent + - RstSyntaxAgent --- You are a documentation build validation agent. @@ -67,13 +68,11 @@ Scope ----- This agent validates: - documentation build commands, -- ``.rst`` syntax, +- ``.rst`` syntax via the ``RstSyntaxAgent``, - toctrees, - autodoc pages, - cross-references, - labels, -- math directives, -- list-tables, - landing pages, - generated API reference wiring, - navigation consistency insofar as it affects build and discoverability. @@ -124,6 +123,7 @@ Examples of issues this agent should detect: - malformed ``.. list-table::`` directives, - missing included documents, - orphaned pages where that matters to navigation. +- linux/windows specific command notations in code examples Small-fix policy ---------------- @@ -230,9 +230,11 @@ Before concluding validation, verify that: - the chosen build command is appropriate for the repository, - the relevant documentation files are syntactically valid, - toctrees resolve correctly, +- references to labels and targets are valid, - autodoc targets resolve correctly where applicable, - no introduced warnings or errors remain unresolved, - larger content problems are routed back to the correct specialist agent. +- check rst syntax and formatting via the ``RstSyntaxAgent``. Validation ---------- @@ -243,8 +245,10 @@ After running validation and any small repairs: 3. Verify that recently edited pages do not introduce malformed directives, broken references, duplicate labels, or toctree failures. 4. Verify that autodoc imports and targets resolve for API reference pages. 5. Verify that navigation changes do not create missing documents or unreachable sections. -6. Apply only small validation-oriented fixes directly. -7. Route larger issues to the correct specialist agent. -8. If the build still fails, report the concrete remaining causes and the correct owner for each. -9. Do not finish with known syntax errors, broken toctrees, unresolved autodoc failures, duplicate labels, or unresolved build warnings caused by the changes under validation. -10. Do not approve documentation merely because the prose looks correct; the build must also be structurally sound. \ No newline at end of file +6. Verify that all warnings and errors are either fixed or routed to the correct specialist agent. +7. Verify that the build passes without errors or warnings after small fixes and routing. +8. Apply only small validation-oriented fixes directly. +9. Route larger issues to the correct specialist agent. +10. If the build still fails, report the concrete remaining causes and the correct owner for each. +11. Do not finish with known syntax errors, broken toctrees, unresolved autodoc failures, duplicate labels, or unresolved build warnings caused by the changes under validation. +12. Do not approve documentation merely because the prose looks correct; the build must also be structurally sound. \ No newline at end of file diff --git a/.github/instructions/documentation-architecture.instructions.md b/.github/instructions/documentation-architecture.instructions.md index c69fa60a..85da9411 100644 --- a/.github/instructions/documentation-architecture.instructions.md +++ b/.github/instructions/documentation-architecture.instructions.md @@ -54,6 +54,15 @@ Use instead: - parentheses, for example ``Q = m (h_out - h_in)``, - simple fractions/division where clearer. +Code examples and snippets +-------------------------- +When including code examples or snippets: +- Use the repository's actual code and file structure where possible. +- Use the repository's actual class and function names where possible. +- Use the repository's actual variable names where possible. + +When using a code block to show a commandline invocation, ensure that the command is valid for both Windows and Linux shells. Use a single code block with a single command, and do not include separate Windows/Linux blocks unless the command is actually different between platforms. Use the simplest form of the command possible, and do not include extra flags or options that are not required for the example to work. If the command is different between platforms, explain the difference in text instead of using separate code blocks. + Introduction requirements -------------------------- For the introductory page and top-level overview: diff --git a/.vscode/settings.json b/.vscode/settings.json index 79ab30ca..4158865e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,22 +21,7 @@ "chat.tools.terminal.autoApprove": { "doc\\make.bat": true, ".\\doc\\make.bat": true, - "/^cmd /c \"c:\\\\repositories\\\\NWN\\\\simulator-core\\\\doc\\\\make\\.bat html\"$/": { - "approve": true, - "matchCommandLine": true - }, - "/^& \\.\\\\doc\\\\run_spinx\\.bat$/": { - "approve": true, - "matchCommandLine": true - }, - "/^doc\\\\venv\\\\Scripts\\\\sphinx-build -b html doc doc\\\\_build\\\\html$/": { - "approve": true, - "matchCommandLine": true - }, ".\\doc\\run_spinx.bat": true, - "/^& \\.\\\\venv\\\\Scripts\\\\python\\.exe -m sphinx -b html doc doc\\\\_build\\\\html$/": { - "approve": true, - "matchCommandLine": true - } }, -} + "python-envs.defaultEnvManager": "ms-python.python:system", +} \ No newline at end of file diff --git a/doc/architecture/architecture.rst b/doc/architecture/architecture.rst deleted file mode 100644 index 907710ba..00000000 --- a/doc/architecture/architecture.rst +++ /dev/null @@ -1,29 +0,0 @@ -General architecture -========================= - -In this section we will describe the general architecture of the simulator. - -The simulation manager manages model configuration and simulation execution, see section :ref:`simulation manager`. -The simulation manager uses ESDL as input. -The project contains a wrapper class around pyesdl, see :ref:`esdl_object`. - -In addtion, a configuration object is required, that contains the configuration for the simulation, see section :ref:`configuration_class`. - -When the simulation is executed it creates a heat network class and a heat network controller class. -Both of these classes use factories methods to create the assets needed, see :ref:`asset_factory`. -Both the heat network object and the controller object are used to create a network simulation object, -which runs the simulation and passes back the results. - -Related pages: - -- :doc:`asset_factories` -- :doc:`configuration` -- :doc:`esdl_asset_object` -- :doc:`esdl_object` -- :doc:`network_simulation` -- :doc:`simulation_manager` - - - - - diff --git a/doc/architecture/asset_factories.rst b/doc/architecture/asset_factories.rst deleted file mode 100644 index f217caeb..00000000 --- a/doc/architecture/asset_factories.rst +++ /dev/null @@ -1,293 +0,0 @@ -.. _asset_factory: - -Asset factories -=============== - -Overview --------- - -This page is a contributor-facing map of the ESDL asset factory layer. Use it when you need to see -what each concrete mapper adds on top of ``EsdlMapperAbstract`` during ESDL-to-entity conversion. - -The key distinction is small but important: the abstract contract only declares the conversion -methods, while each concrete mapper implements simulator-specific construction logic in -``to_entity``. In the current codebase, every mapper on this page leaves ``to_esdl`` -unimplemented and raises ``NotImplementedError``. - -For the broader orchestration path that uses these mappers, see :doc:`architecture`. - -Abstract mapper contract ------------------------- - -``EsdlMapperAbstract`` defines exactly two abstract methods: - -* ``to_esdl(entity)`` for mapping a simulator entity back to an ESDL asset object. -* ``to_entity(model)`` for mapping an ESDL asset object into a simulator entity. - -The base class does not provide shared field extraction, defaults, validation, or branching -behavior. Those responsibilities are entirely delegated to each concrete mapper. In the current -implementation, the concrete mappers on this page only specialize ``to_entity`` and intentionally -leave ``to_esdl`` unavailable. - -Concrete mapper comparison --------------------------- - -.. list-table:: - :header-rows: 1 - - * - Mapper - - Entity returned - - ESDL data read - - Defaults, branching, or validation - * - ``EsdlAssetProducerMapper`` - - ``ProductionCluster`` - - Asset ``name``, ``id``, and port ids - - No extra defaults or validation - * - ``EsdlAssetConsumerMapper`` - - ``DemandCluster`` - - Asset ``name``, ``id``, and port ids - - No extra defaults or validation - * - ``EsdlAssetAtesMapper`` - - ``AtesCluster`` - - Asset ``name``, ``id``, port ids, aquifer and well properties - - Falls back to ``ATES_DEFAULTS`` for every ATES-specific property it reads - * - ``EsdlAssetHeatPumpMapper`` - - ``HeatPump`` or ``AirToWaterHeatPump`` - - Asset ``name``, ``id``, port ids, ``COP``, and optional ``power`` - - Branches on port count and raises on unsupported counts - * - ``EsdlAssetHeatExchangerMapper`` - - ``HeatExchanger`` - - Asset ``name``, ``id``, port ids, and ``Efficiency`` - - Falls back to ``HeatExchangerDefaults`` when ``Efficiency`` is absent - * - ``EsdlIdealHeatStorageMapper`` - - ``IdealHeatStorage`` - - Asset ``name``, ``id``, port ids, ``volume``, ``fillLevel``, and port temperatures - - Falls back to ``HeatBufferDefaults`` for ``volume``/``fillLevel``; temperatures have no static default - * - ``EsdlAssetPipeMapper`` - - ``Pipe`` - - Asset ``name``, ``id``, port ids, hydraulic and thermal properties - - Mixes direct properties, defaults, helper-derived values, and EDR fallback logic - -Per-mapper notes ----------------- - -Producer mapper -~~~~~~~~~~~~~~~ - -``EsdlAssetProducerMapper`` is the simplest specialization of the abstract contract. Its -``to_entity`` method constructs a ``ProductionCluster`` from only three inputs: -``esdl_asset.esdl_asset.name``, ``esdl_asset.esdl_asset.id``, and ``esdl_asset.get_port_ids()``. -It does not inspect any producer-specific ESDL properties, apply defaults, or perform validation. - -Consumer mapper -~~~~~~~~~~~~~~~ - -``EsdlAssetConsumerMapper`` mirrors the producer mapper, but returns a ``DemandCluster``. -Its ``to_entity`` method also reads only the asset name, asset id, and port ids. No extra -consumer-specific properties are interpreted, and there is no branching or fallback logic. - -ATES mapper -~~~~~~~~~~~ - -``EsdlAssetAtesMapper`` extends the minimal name/id/ports pattern by reading a larger property set -before constructing an ``AtesCluster``. In addition to the shared asset metadata, it reads these -ESDL properties, each falling back to ``ATES_DEFAULTS`` when absent: - -.. list-table:: - :header-rows: 1 - - * - ESDL property - - Internal field - - Default - - Unit - * - ``aquiferTopDepth`` - - ``aquifer_depth`` - - ``300.0`` - - m - * - ``aquiferThickness`` - - ``aquifer_thickness`` - - ``45.0`` - - m - * - ``aquiferMidTemperature`` - - ``aquifer_mid_temperature`` - - ``17.0`` - - degrees Celsius - * - ``aquiferNetToGross`` - - ``aquifer_net_to_gross`` - - ``1.0`` - - fraction (-) - * - ``aquiferPorosity`` - - ``aquifer_porosity`` - - ``0.3`` - - fraction (-) - * - ``aquiferPermeability`` - - ``aquifer_permeability`` - - ``10000.0`` - - millidarcy (mD) - * - ``aquiferAnisotropy`` - - ``aquifer_anisotropy`` - - ``4.0`` - - dimensionless (-) - * - ``salinity`` - - ``salinity`` - - ``10000.0`` - - parts per million (ppm) - * - ``wellCasingSize`` - - ``well_casing_size`` - - ``13.0`` - - inch - * - ``wellDistance`` - - ``well_distance`` - - ``150.0`` - - m - -The mapper does not add extra branching logic; its specialization is that it always tries to -populate the ATES-specific constructor arguments, even when the ESDL asset omits them. - -``aquiferMidTemperature`` is the one property in this set mapped in degrees Celsius. Every other -temperature-like property mapped elsewhere on this page (for example the pipe mapper's -``external_temperature``) uses Kelvin; this is an existing inconsistency in the source data, noted -here for contributor awareness rather than something this page changes. - -Heat pump mapper -~~~~~~~~~~~~~~~~ - -``EsdlAssetHeatPumpMapper`` adds the first substantive construction branch. It checks -``esdl_asset.get_number_of_ports()`` and chooses the returned entity type from that port count: - -* ``4`` ports produces a ``HeatPump`` for the water-to-water case. -* ``2`` ports produces an ``AirToWaterHeatPump``. - -.. list-table:: - :header-rows: 1 - - * - ESDL property - - Internal field - - Default - - Unit - - Applies to - * - ``COP`` - - ``coefficient_of_performance`` - - ``HeatPumpDefaults.coefficient_of_performance`` = ``4.0`` - - dimensionless (-) - - both branches - * - ``power`` - - ``maximum_electrical_power`` - - ``None`` - - W - - four-port branch only - -Any other port count raises ``NotImplementedError`` with a message that documents the supported -two-port and four-port shapes. - -Heat exchanger mapper -~~~~~~~~~~~~~~~~~~~~~ - -``EsdlAssetHeatExchangerMapper`` reads a single property beyond the shared asset metadata before -constructing a ``HeatExchanger``: - -.. list-table:: - :header-rows: 1 - - * - ESDL property - - Internal field - - Default - - Unit - * - ``Efficiency`` - - ``heat_transfer_efficiency`` - - ``HeatExchangerDefaults.heat_transfer_efficiency`` = ``1.0`` - - dimensionless (-) - -There is no branching or validation beyond this single fallback lookup. - -Ideal heat storage mapper -~~~~~~~~~~~~~~~~~~~~~~~~~ - -``EsdlIdealHeatStorageMapper`` constructs an ``IdealHeatStorage`` from two defaulted properties and -two port-derived temperatures: - -.. list-table:: - :header-rows: 1 - - * - ESDL property - - Internal field - - Default - - Unit - * - ``volume`` - - ``volume`` - - ``HeatBufferDefaults.volume`` = ``1.0`` - - m3 - * - ``fillLevel`` - - ``initial_fill_level`` - - ``HeatBufferDefaults.fill_level`` = ``0.5`` - - fraction, 0-1 (-) - * - port ``In``/``Supply`` profile - - ``temperature_in`` - - none; read via ``esdl_asset.get_temperature("In", "Supply")`` - - K - * - port ``Out``/``Return`` profile - - ``temperature_out`` - - none; read via ``esdl_asset.get_temperature("Out", "Return")`` - - K - -Unlike every other property on this page, the two temperatures have no static default: if the -ESDL port temperature profile does not supply a value, ``get_temperature`` raises rather than -falling back to a constant. - -Pipe mapper -~~~~~~~~~~~ - -``EsdlAssetPipeMapper`` performs the richest property mapping on this page. Its ``to_entity`` -method constructs a ``Pipe`` from direct properties, helper-derived values, and multiple -fallbacks: - -.. list-table:: - :header-rows: 1 - - * - ESDL property - - Internal field - - Default - - Unit - * - ``length`` - - ``length`` - - ``PIPE_DEFAULTS.length`` = ``1.0`` - - m - * - ``roughness`` - - ``roughness`` - - ``PIPE_DEFAULTS.roughness`` = ``1e-3`` - - m - * - ``minor_loss_coefficient`` - - ``minor_loss_coefficient`` - - ``PIPE_DEFAULTS.minor_loss_coefficient`` = ``0.0`` - - dimensionless (-) - * - ``external_temperature`` - - ``external_temperature`` - - ``PIPE_DEFAULTS.external_temperature`` = ``293.15`` - - K - * - ``qheat_external`` - - ``qheat_external`` - - ``PIPE_DEFAULTS.qheat_external`` = ``0.0`` - - W - -Two further fields are derived rather than read with a single direct default: - -* Inner diameter: ``_get_diameter()`` first reads ``innerDiameter`` (m). If that value is - zero, it tries ``diameter`` as a nominal DN value. When a DN value is available, the mapper - looks up the corresponding EDR object with the default schedule from ``PIPE_DEFAULTS`` and - returns its ``innerDiameter`` (m). If neither source is available, it falls back to - ``PIPE_DEFAULTS.diameter`` = ``1.2`` m. -* Heat-transfer coefficient: ``_get_heat_transfer_coefficient()`` uses - ``get_thermal_conductivity_table()`` and ``calculate_inverse_heat_transfer_coefficient()`` to - derive an ``alpha_value`` in W/(m2 K). If no conductivity table can be built, it falls back to - ``PIPE_DEFAULTS.alpha_value`` = ``0.0``. - -This mapper also contains the main failure path in the group. If DN-based diameter lookup requires -EDR access and ``_get_esdl_object_from_edr()`` cannot retrieve the expected object, it raises -``RuntimeError`` rather than silently accepting an invalid diameter. - -Related documentation ---------------------- - -For the broader architecture that instantiates and consumes these factories, see -:doc:`architecture`. For the curated reference index that places this page alongside the other -implementation-oriented architecture pages, see :doc:`../reference/architecture_reference`. \ No newline at end of file diff --git a/doc/architecture/configuration.rst b/doc/architecture/configuration.rst deleted file mode 100644 index 72d06c8b..00000000 --- a/doc/architecture/configuration.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _configuration_class: - -Configuration class -=================== -The configuration class is a dataclass that stores simulation parameters such as: start time, end time, time step, simulation id and name. - -.. autoclass:: omotes_simulator_core.entities.simulation_configuration.SimulationConfiguration - :members: - :no-index: \ No newline at end of file diff --git a/doc/architecture/esdl_asset_object.rst b/doc/architecture/esdl_asset_object.rst deleted file mode 100644 index e20d4f38..00000000 --- a/doc/architecture/esdl_asset_object.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _esdl_asset_object: - -ESDL asset object class -======================= -The ESDL asset object class is used to query the esdl asset object and return values to be used in the simulation. - -.. autoclass:: omotes_simulator_core.entities.assets.esdl_asset_object.EsdlAssetObject - :members: - :no-index: \ No newline at end of file diff --git a/doc/architecture/esdl_object.rst b/doc/architecture/esdl_object.rst deleted file mode 100644 index 2a2fe3c8..00000000 --- a/doc/architecture/esdl_object.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _esdl_object: - -ESDL object class -===================================== -The ESDL object class acts as a wrapper around pyesdl to have a common interface for the simulator. -It can be used to query the esdl object for assets and other information. - -ESDL asets will be returned as an esdlassetobject, see section :ref:`esdl_asset_object`. - -.. autoclass:: omotes_simulator_core.entities.esdl_object.EsdlObject - :members: - :no-index: diff --git a/doc/architecture/network_simulation.rst b/doc/architecture/network_simulation.rst deleted file mode 100644 index 4f581aaa..00000000 --- a/doc/architecture/network_simulation.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _network_simulation: - -Network simulation -===================================== -to be filled - -.. autoclass:: omotes_simulator_core.simulation.networksimulation.NetworkSimulation - :members: - :no-index: \ No newline at end of file diff --git a/doc/architecture/simulation_manager.rst b/doc/architecture/simulation_manager.rst deleted file mode 100644 index d2d5294e..00000000 --- a/doc/architecture/simulation_manager.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _simulation manager: - -Simulation manager -================== -This class manages the simulation processes. Its primary responsibilities include: - -- Creating instances of the network and controller classes -- Initializing and exectuing the network simulation, as detailed in :ref:`network_simulation`. - -.. autoclass:: omotes_simulator_core.infrastructure.simulation_manager.SimulationManager - :members: - :no-index: \ No newline at end of file diff --git a/doc/developer/add_new_asset.rst b/doc/developer/add_new_asset.rst new file mode 100644 index 00000000..02a542ee --- /dev/null +++ b/doc/developer/add_new_asset.rst @@ -0,0 +1,226 @@ +Adding a New Physics Asset +========================== + +Purpose +------- + +Use this guide when you need to implement a new thermo-hydraulic asset type in the simulator — +for example a new heat pump variant, a storage asset, or a pipe variant. The guide walks you +through all four implementation steps: entity layer, solver layer, ESDL mapper, and mapper +registration. It then points you to test patterns and related documentation. + +This page is for contributors who work at the Python implementation level. It assumes you can +already navigate the repository and run the unit test suite. For conceptual asset behavior and +governing relations, consult the Physics section rather than this guide. + +Where Assets Live +----------------- + +The simulator represents each asset in two separate layers, each with a distinct responsibility: + +**Entity layer** — ``src/omotes_simulator_core/entities/assets/`` + High-level Python classes that own per-timestep state, apply setpoints, and collect output. + All entity-layer assets inherit from ``AssetAbstract``. + +**Solver layer** — ``src/omotes_simulator_core/solver/network/assets/`` + Low-level classes that contribute matrix equations to the nonlinear solver. All solver-layer + assets ultimately inherit from ``BaseItem`` (via ``BaseAsset`` for two-port thermo-hydraulic + assets, or via specialized base classes such as ``FallType`` for assets with different + topologies). + +The entity-layer class holds a reference to its corresponding solver-layer instance as +``self.solver_asset``. The entity layer calls into the solver layer to read hydraulic and thermal +results; the solver layer calls ``get_equations()`` to supply the matrix builder. + +Step-by-step Workflow +--------------------- + +1. Create the entity-layer asset class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a new file in ``src/omotes_simulator_core/entities/assets/``, for example +``my_asset.py``. + +Inherit from ``AssetAbstract``: + +.. code-block:: python + + from omotes_simulator_core.entities.assets.asset_abstract import AssetAbstract + + class MyAsset(AssetAbstract): + asset_type = "my_asset" + number_of_con_points: int = 2 # adjust to match port count + + def __init__(self, asset_name: str, asset_id: str, connected_ports: list[str]) -> None: + super().__init__(asset_name, asset_id, connected_ports) + # initialise asset-specific state here + +The following methods **must** be implemented: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Method + - Responsibility + * - ``set_setpoints(self, setpoints: dict)`` + - Accept a dictionary of setpoint names and values and apply them to the asset's internal + state before each solver call. Raise ``KeyError`` if a required setpoint is missing. + * - ``write_to_output(self)`` + - Append asset-specific computed quantities (e.g. heat power, electrical consumption) to + ``self.outputs`` for the current timestep. Call ``self.write_standard_output()`` first to + record the standard mass-flow, pressure, and temperature entries. + +The following methods have default no-op implementations in ``AssetAbstract`` and may be +overridden when the asset carries state that must be exposed: + +- ``get_setpoints(self) -> dict[str, float]`` — return current setpoint values. +- ``get_state(self) -> dict[str, float]`` — return current internal state values. + +Instantiate the matching solver-layer object and assign it to ``self.solver_asset`` before +the asset is connected to the network. See the existing ``ProductionCluster.__init__`` and +``HeatPump.__init__`` for concrete examples. + +2. Create the solver-layer asset class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a new file in ``src/omotes_simulator_core/solver/network/assets/``, for example +``my_solver_asset.py``. + +For a standard two-port thermo-hydraulic asset, inherit from ``BaseAsset``: + +.. code-block:: python + + from omotes_simulator_core.solver.network.assets.base_asset import BaseAsset + from omotes_simulator_core.solver.matrix.equation_object import EquationObject + + class MySolverAsset(BaseAsset): + + def __init__(self, name: str, _id: str) -> None: + super().__init__( + name=name, + _id=_id, + number_of_unknowns=6, # 3 quantities × 2 ports + number_connection_points=2, + ) + + def get_equations(self) -> list[EquationObject]: + # Return the matrix equations that constrain this asset's unknowns. + ... + +``BaseItem`` (the root of the solver hierarchy) declares ``get_equations`` as abstract; +every concrete solver asset must implement it. The method must return one ``EquationObject`` +per unknown so that the matrix builder can assemble the global system. + +For assets with different topologies (for example an asset with four ports, such as a +water-to-water heat pump), examine ``HeatTransferAsset`` and ``FallType`` as starting points +rather than ``BaseAsset`` directly. + +Setter methods for boundary conditions (e.g. supply temperature, prescribed mass flow, +prescribed pressure) are plain attributes or simple methods. Study ``HeatBoundary`` and +``HeatTransferAsset`` for representative patterns before writing new equation logic. + +3. Create the ESDL mapper +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a new file in +``src/omotes_simulator_core/adapter/transforms/esdl_asset_mappers/``, for example +``my_asset_mapper.py``. + +Inherit from ``EsdlMapperAbstract``: + +.. code-block:: python + + from omotes_simulator_core.simulation.mappers.mappers import EsdlMapperAbstract + from omotes_simulator_core.entities.assets.asset_abstract import AssetAbstract + from omotes_simulator_core.entities.assets.esdl_asset_object import EsdlAssetObject + from omotes_simulator_core.entities.assets.my_asset import MyAsset + + + class EsdlMyAssetMapper(EsdlMapperAbstract): + + def to_esdl(self, entity: MyAsset) -> EsdlAssetObject: + raise NotImplementedError("EsdlMyAssetMapper.to_esdl()") + + def to_entity(self, esdl_asset: EsdlAssetObject) -> AssetAbstract: + return MyAsset( + asset_name=esdl_asset.esdl_asset.name, + asset_id=esdl_asset.esdl_asset.id, + connected_ports=esdl_asset.get_port_ids(), + # read additional ESDL properties with esdl_asset.get_property(name, default) + ) + +Use ``esdl_asset.get_property(name, default)`` to read optional ESDL attributes safely. +Use ``esdl_asset.get_port_ids()`` to obtain the ordered list of port identifiers. + +4. Register the mapper +~~~~~~~~~~~~~~~~~~~~~~~ + +Open ``src/omotes_simulator_core/adapter/transforms/esdl_asset_mapper.py`` and add two +changes. + +First, import your new mapper class at the top of the file alongside the existing imports: + +.. code-block:: python + + from omotes_simulator_core.adapter.transforms.esdl_asset_mappers.my_asset_mapper import ( + EsdlMyAssetMapper, + ) + +Second, add one or more entries to ``conversion_dict_mappers``: + +.. code-block:: python + + conversion_dict_mappers: dict[type, type[EsdlMapperAbstract]] = { + ... + esdl.MyEsdlAssetType: EsdlMyAssetMapper, + ... + } + +The ``EsdlAssetMapper.to_entity`` method uses this dictionary to dispatch to the correct +mapper at runtime. A single mapper class may be registered for multiple ESDL types if they +share the same construction logic (see how ``EsdlAssetProducerMapper`` handles several +producer variants). + +5. Test file placement and patterns +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the entity layer belong in ``unit_test/entities/``. Follow the pattern of +``test_heat_pump.py`` or ``test_production_cluster.py``: + +- Construct the asset in ``setUp`` with representative port ids and setpoint values. +- Test ``set_setpoints`` with valid and invalid inputs. +- Mock ``self.solver_asset`` to isolate entity logic from the solver layer. +- Test ``write_to_output`` by calling it and inspecting ``self.outputs``. + +Unit tests for the solver-layer class belong in ``unit_test/solver/network/assets/``. +Follow the pattern of ``test_production_asset.py`` or ``test_heat_transfer_asset.py``: + +- Test that ``get_equations`` returns the correct number of ``EquationObject`` instances. +- Test boundary-condition setters by checking the ``prev_sol`` state after setting values. + +Unit tests for the mapper belong in +``unit_test/adapters/transforms/esdl_asset_mappers/``. +Follow the pattern of ``test_esdl_asset_heat_pump_mapper.py``: + +- Construct a mock ``EsdlAssetObject`` wrapping a representative PyESDL asset. +- Assert that ``to_entity`` returns an instance of the expected entity class. +- Assert that ESDL properties are correctly transferred to entity attributes. + +Running and validating tests +---------------------------- + +After placing test files, verify end-to-end behavior by running the full unit test suite with +``python -m pytest`` from the repository root. If the asset is exercised by any existing ESDL +test-data files in ``testdata/``, run the relevant integration tests under +``unit_test/integration/`` as well. For new ESDL scenarios, add a minimal ``.esdl`` file to +``testdata/`` and write a corresponding integration test that asserts the simulation completes +without error and produces non-trivial output. See the existing integration tests for the +expected structure. + +Cross-links +----------- + +- Asset behavior and physics: :doc:`../physics/physics_main` +- Simulation orchestration and how assets are wired into the runtime: :doc:`simulation_contributor_flow` +- Test layout and test patterns: :doc:`testing` diff --git a/doc/developer/add_new_output_format.rst b/doc/developer/add_new_output_format.rst new file mode 100644 index 00000000..a9492af8 --- /dev/null +++ b/doc/developer/add_new_output_format.rst @@ -0,0 +1,256 @@ +Adding a New Output Format +========================== + +Purpose +------- + +Use this guide when you need to extend the simulator's output — for example, to add a new +computed column to an existing asset's output, add output columns to an asset that currently +emits none, or change how the collected output is assembled and returned. + +This page is for contributors who work at the Python implementation level. It assumes you can +navigate the repository and run the unit test suite. For conceptual system behavior and +governing relations, consult the Physics and Architecture sections instead. + +The output pipeline has three layers: per-asset output accumulation (entity layer), network-wide +collection (``HeatNetwork``), and simulation-level assembly (``NetworkSimulation``). A new output +format always starts in the entity layer and flows automatically through the remaining two. + +Relevant Modules and Files +-------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 40 25 35 + + * - File or Module + - Role + - Why it matters for this topic + * - ``src/omotes_simulator_core/entities/assets/asset_abstract.py`` + - Abstract base class for all entity-layer assets + - Defines ``write_standard_output`` (standard columns) and the abstract + ``write_to_output`` (asset-specific columns); all output columns are written here + * - ``src/omotes_simulator_core/entities/assets/asset_defaults.py`` + - Named property-key constants + - All column names used as dictionary keys must be defined here; avoids hard-coded + string literals scattered across asset files + * - ``src/omotes_simulator_core/entities/assets/pipe.py`` + - Concrete asset — pipe + - Practical reference implementation of ``write_to_output`` with multiple columns + and per-port output + * - ``src/omotes_simulator_core/entities/assets/demand_cluster.py`` + - Concrete asset — heat demand + - Shows the minimal single-port ``write_to_output`` pattern using ``outputs[i][-1].update`` + * - ``src/omotes_simulator_core/entities/heat_network.py`` + - Network container + - Calls ``write_standard_output`` and ``write_to_output`` on every asset each timestep + via ``store_output``; collects results via ``gather_output`` + * - ``src/omotes_simulator_core/simulation/networksimulation.py`` + - Simulation orchestrator + - Drives the per-timestep loop that calls ``store_output`` and exposes + ``gather_output`` to the caller + * - ``src/omotes_simulator_core/infrastructure/simulation_manager.py`` + - Top-level entry point + - Calls ``worker.gather_output()`` and returns the combined ``pandas.DataFrame`` + * - ``unit_test/entities/test_pipe.py`` + - Unit tests for ``Pipe`` output + - Reference test pattern for ``write_standard_output`` then ``write_to_output`` + * - ``unit_test/entities/test_heat_exchanger.py`` + - Unit tests for ``HeatExchanger`` output + - Shows asserting on specific keys in ``outputs[i][-1]`` after both write calls + * - ``unit_test/simulation/test_networksimulation.py`` + - Integration-level simulation test + - Verifies the full pipeline from ``run`` through ``gather_output`` + +Extension Flow +-------------- + +The steps below cover the most common extension: adding one or more new output columns to an +existing or new asset. Steps 1–3 are always required. Step 4 applies only when you add a new +asset. + +1. Define a named property constant +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Open ``src/omotes_simulator_core/entities/assets/asset_defaults.py`` and add a module-level +constant for each new column name: + +.. code-block:: python + + PROPERTY_MY_NEW_QUANTITY = "my_new_quantity" + +Using a named constant prevents mismatched string literals between the writing side and any +downstream code that reads the ``DataFrame`` columns. + +2. Implement or extend ``write_to_output`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the target asset class — for example +``src/omotes_simulator_core/entities/assets/my_asset.py`` — add or extend ``write_to_output``. +The method must: + +- call ``self.write_standard_output()`` first if it has not already been called at this + point in the per-timestep sequence (``HeatNetwork.store_output`` calls it separately, + but individual asset unit tests often call both in order), +- call ``self.outputs[port_index][-1].update({...})`` to append new keys to the *most + recent* output dictionary for the chosen port, +- not replace the entire dictionary; always use ``update`` to preserve the standard + columns written by ``write_standard_output``. + +Example — adding a single extra column to port 1 (the outlet port by convention): + +.. code-block:: python + + from omotes_simulator_core.entities.assets.asset_defaults import PROPERTY_MY_NEW_QUANTITY + + def write_to_output(self) -> None: + output_dict_temp = { + PROPERTY_MY_NEW_QUANTITY: self._compute_my_quantity(), + } + self.outputs[1][-1].update(output_dict_temp) + +For assets with two symmetric connection points — such as ``Pipe`` — iterate over all +ports and update each: + +.. code-block:: python + + def write_to_output(self) -> None: + for i in range(len(self.connected_ports)): + self.outputs[i][-1].update( + {PROPERTY_MY_NEW_QUANTITY: self._compute_my_quantity(i)} + ) + +3. Verify the column appears in ``get_timeseries`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``AssetAbstract.get_timeseries`` converts ``self.outputs`` to a ``pandas.DataFrame`` with +multi-level columns ``(port_id, property_name)``. No changes to this method are required for +new columns; the new key is picked up automatically from the updated dictionary. + +The assembled result flows through ``HeatNetwork.gather_output`` and is returned by +``SimulationManager.execute`` as a flat ``DataFrame`` with all asset timeseries concatenated +along the column axis. + +4. Register new property constants (new asset only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are introducing a completely new asset, also ensure the asset is registered in the ESDL +mapper so that ``HeatNetwork.store_output`` can reach it. See :doc:`add_new_asset` for the +mapper registration workflow; nothing extra is required for output beyond the steps above. + +Implementation Notes +-------------------- + +- ``write_standard_output`` is called by ``HeatNetwork.store_output`` before + ``write_to_output`` for every asset each timestep. It appends a fresh dictionary to + ``self.outputs[i]`` for each port. Because ``write_to_output`` calls + ``self.outputs[i][-1].update``, the standard columns are always present in the same + dictionary as the asset-specific columns. + +- The indexing convention for ``outputs[i]`` follows ``self.connected_ports``: index 0 is + typically the inlet and index 1 is the outlet. Some multi-circuit assets (for example + ``HeatPump`` and ``HeatExchanger`` with four connection points) use indices 0–3. Match + the index to the physical port. + +- ``get_timeseries`` builds ``DataFrame`` columns as ``(port_id, property_name)`` tuples, + where ``port_id`` is the ESDL port identifier string from ``self.connected_ports[i]``. + Downstream consumers must use the same tuple structure when reading specific columns. + +- There is no registry of valid column names. Adding a constant to ``asset_defaults.py`` + is a convention, not a framework requirement; however, it is enforced by code review and + prevents duplicate or diverging string literals. + +- ``write_to_output`` is abstract in ``AssetAbstract``. Every concrete asset must provide + an implementation. If the asset has no asset-specific columns beyond the standard ones, + provide a no-op body: + + .. code-block:: python + + def write_to_output(self) -> None: + pass + +Testing and Validation +---------------------- + +Follow the pattern established in ``unit_test/entities/test_pipe.py`` and +``unit_test/entities/test_heat_exchanger.py``: + +1. Construct the asset under test and prime ``solver_asset.prev_sol`` with representative + values. +2. Call ``asset.write_standard_output()`` to populate the standard columns. +3. Call ``asset.write_to_output()`` to add the asset-specific columns. +4. Assert that the expected keys exist in ``asset.outputs[port_index][-1]`` and that the + computed values match. + +Example assertion pattern: + +.. code-block:: python + + def test_write_to_output(self) -> None: + self.my_asset.write_standard_output() + self.my_asset.write_to_output() + self.assertAlmostEqual( + self.my_asset.outputs[1][-1][PROPERTY_MY_NEW_QUANTITY], + expected_value, + ) + +For end-to-end coverage, refer to ``unit_test/simulation/test_networksimulation.py``, which +verifies that ``gather_output`` returns a non-empty ``DataFrame`` after a complete simulation +run. If your change affects the shape of the returned ``DataFrame`` (for example, adding +columns to every asset), add or update an assertion on the column index. + +To run the unit tests: + +.. code-block:: bash + + python -m pytest unit_test/ + +To validate the documentation build after updating this page: + +.. code-block:: bash + + python -m sphinx -b html doc doc/_build/html + +Common Pitfalls +--------------- + +- **Calling ``update`` on an empty list.** ``write_to_output`` must always be called + *after* ``write_standard_output`` — or after any prior call that appended a dictionary + to ``self.outputs[i]``. Calling ``self.outputs[i][-1].update(...)`` when the list is + empty raises an ``IndexError``. + +- **Replacing instead of updating.** Assigning ``self.outputs[i][-1] = {...}`` overwrites + the standard columns. Always use ``.update``. + +- **Using a raw string literal as a column key.** String literals that differ by a single + character produce silently wrong output. Define every column name as a constant in + ``asset_defaults.py`` and import it. + +- **Writing to the wrong port index.** Confirm which index corresponds to the inlet versus + outlet for the specific asset topology before choosing ``outputs[0]`` or ``outputs[1]``. + Multi-circuit assets have more than two ports; check ``self.connected_ports`` to match + the physical port. + +- **Assuming ``get_timeseries`` produces flat column names.** The method returns a + multi-level ``(port_id, property_name)`` column index. Code that reads specific columns + from the returned ``DataFrame`` must use the tuple form, not a plain string. + +- **Editing generated API pages.** Pages under ``doc/developer/api/`` are autogenerated by + ``sphinx.ext.apidoc`` on every build. Do not hand-edit them to document new constants or + methods; the source docstrings in ``asset_defaults.py`` and the asset files are the + canonical location for that reference material. + +Related Documentation +--------------------- + +- :doc:`add_new_asset` — complete workflow for adding a new asset type, including + entity-layer, solver-layer, ESDL mapper, and mapper registration steps that precede + output implementation for a brand-new asset. +- :doc:`simulation_contributor_flow` — end-to-end code layout and execution flow from + ``app.py`` through ``SimulationManager``, ``NetworkSimulation``, and ``HeatNetwork``. +- :doc:`testing` — test layout, how to run the full test suite, and the contributor + checklist. +- :doc:`../network/network_main` — conceptual overview of how the network + simulation coordinates assets, the solver, and the controller. +- For class-level details on ``AssetAbstract``, ``HeatNetwork``, and related types, consult + the :doc:`api/omotes_simulator_core` root index. diff --git a/doc/developer/api/omotes_simulator_core.adapter.presentation.rst b/doc/developer/api/omotes_simulator_core.adapter.presentation.rst index f9d69415..a34bf977 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.presentation.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.presentation.rst @@ -3,5 +3,5 @@ adapter.presentation .. automodule:: omotes_simulator_core.adapter.presentation :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.rst b/doc/developer/api/omotes_simulator_core.adapter.rst index 171709a6..0b13bb1f 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.rst @@ -3,8 +3,8 @@ adapter .. automodule:: omotes_simulator_core.adapter :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mapper.rst index aa55e3bb..073b1307 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.controller_mapper .. automodule:: omotes_simulator_core.adapter.transforms.controller_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_consumer_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_consumer_mapper.rst index bc1fb95b..2af2617d 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_consumer_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_consumer_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.controller_mappers.controller_consumer_mapper .. automodule:: omotes_simulator_core.adapter.transforms.controller_mappers.controller_consumer_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_heat_transfer_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_heat_transfer_mapper.rst index 5e315727..eee2fb59 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_heat_transfer_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_heat_transfer_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.controller_mappers.controller_heat_transfer_mapper .. automodule:: omotes_simulator_core.adapter.transforms.controller_mappers.controller_heat_transfer_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_producer_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_producer_mapper.rst index d6ef2a25..31190322 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_producer_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_producer_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.controller_mappers.controller_producer_mapper .. automodule:: omotes_simulator_core.adapter.transforms.controller_mappers.controller_producer_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_storage_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_storage_mapper.rst index bd73b5be..301de6ef 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_storage_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.controller_storage_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.controller_mappers.controller_storage_mapper .. automodule:: omotes_simulator_core.adapter.transforms.controller_mappers.controller_storage_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.rst index 3b88665d..f6b11b93 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.controller_mappers.rst @@ -3,8 +3,8 @@ adapter.transforms.controller_mappers .. automodule:: omotes_simulator_core.adapter.transforms.controller_mappers :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mapper.rst index 9d1a314d..6597a48d 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ates_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ates_mapper.rst index 9a35f830..cc200542 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ates_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ates_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.ates_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ates_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.consumer_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.consumer_mapper.rst index 56945b4a..980d67b1 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.consumer_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.consumer_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.consumer_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.consumer_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper.rst index a50facbf..82f367ae 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_exchanger_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_pump_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_pump_mapper.rst index e7c5d837..69e73f84 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_pump_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_pump_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.heat_pump_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.heat_pump_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper.rst index 4a5d5549..0ad4a7bb 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.ideal_heat_storage_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.pipe_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.pipe_mapper.rst index 2b20e28d..88ea3770 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.pipe_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.pipe_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.pipe_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.pipe_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.producer_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.producer_mapper.rst index e9f969d5..23073b85 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.producer_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.producer_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_asset_mappers.producer_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers.producer_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.rst index b64c1ef3..51f077ff 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_asset_mappers.rst @@ -3,8 +3,8 @@ adapter.transforms.esdl_asset_mappers .. automodule:: omotes_simulator_core.adapter.transforms.esdl_asset_mappers :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_graph_mapper.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_graph_mapper.rst index ed9e6e1a..6abc49df 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_graph_mapper.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.esdl_graph_mapper.rst @@ -3,5 +3,5 @@ adapter.transforms.esdl_graph_mapper .. automodule:: omotes_simulator_core.adapter.transforms.esdl_graph_mapper :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.mappers.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.mappers.rst index 02bb9599..ae7bb5df 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.mappers.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.mappers.rst @@ -3,5 +3,5 @@ adapter.transforms.mappers .. automodule:: omotes_simulator_core.adapter.transforms.mappers :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.rst index 4e507c34..c82b659c 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.rst @@ -3,8 +3,8 @@ adapter.transforms .. automodule:: omotes_simulator_core.adapter.transforms :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.string_to_esdl.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.string_to_esdl.rst index 41aeed7c..a3d9f153 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.string_to_esdl.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.string_to_esdl.rst @@ -3,5 +3,5 @@ adapter.transforms.string_to_esdl .. automodule:: omotes_simulator_core.adapter.transforms.string_to_esdl :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.transforms.transform_utils.rst b/doc/developer/api/omotes_simulator_core.adapter.transforms.transform_utils.rst index b9fe9a4e..5108aa86 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.transforms.transform_utils.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.transforms.transform_utils.rst @@ -3,5 +3,5 @@ adapter.transforms.transform_utils .. automodule:: omotes_simulator_core.adapter.transforms.transform_utils :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.utility.graph.rst b/doc/developer/api/omotes_simulator_core.adapter.utility.graph.rst index 4fdd5dd4..9006ef5b 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.utility.graph.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.utility.graph.rst @@ -3,5 +3,5 @@ adapter.utility.graph .. automodule:: omotes_simulator_core.adapter.utility.graph :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.adapter.utility.rst b/doc/developer/api/omotes_simulator_core.adapter.utility.rst index 4f6c6066..66d06c1d 100644 --- a/doc/developer/api/omotes_simulator_core.adapter.utility.rst +++ b/doc/developer/api/omotes_simulator_core.adapter.utility.rst @@ -3,8 +3,8 @@ adapter.utility .. automodule:: omotes_simulator_core.adapter.utility :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.air_to_water_heat_pump.rst b/doc/developer/api/omotes_simulator_core.entities.assets.air_to_water_heat_pump.rst index 34c3db36..da93625e 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.air_to_water_heat_pump.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.air_to_water_heat_pump.rst @@ -3,5 +3,5 @@ entities.assets.air_to_water_heat_pump .. automodule:: omotes_simulator_core.entities.assets.air_to_water_heat_pump :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.asset_abstract.rst b/doc/developer/api/omotes_simulator_core.entities.assets.asset_abstract.rst index 801a483d..332170b5 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.asset_abstract.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.asset_abstract.rst @@ -3,5 +3,5 @@ entities.assets.asset_abstract .. automodule:: omotes_simulator_core.entities.assets.asset_abstract :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.asset_defaults.rst b/doc/developer/api/omotes_simulator_core.entities.assets.asset_defaults.rst index 561400bb..fdbce10f 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.asset_defaults.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.asset_defaults.rst @@ -3,5 +3,5 @@ entities.assets.asset_defaults .. automodule:: omotes_simulator_core.entities.assets.asset_defaults :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.ates_cluster.rst b/doc/developer/api/omotes_simulator_core.entities.assets.ates_cluster.rst index 667ac1c8..799428f4 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.ates_cluster.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.ates_cluster.rst @@ -3,5 +3,5 @@ entities.assets.ates_cluster .. automodule:: omotes_simulator_core.entities.assets.ates_cluster :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.asset_controller_abstract.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.asset_controller_abstract.rst index bfc82e4b..0a7eb06c 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.asset_controller_abstract.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.asset_controller_abstract.rst @@ -3,5 +3,5 @@ entities.assets.controller.asset_controller_abstract .. automodule:: omotes_simulator_core.entities.assets.controller.asset_controller_abstract :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_consumer.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_consumer.rst index 204b8d23..eb1df5ff 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_consumer.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_consumer.rst @@ -3,5 +3,5 @@ entities.assets.controller.controller_consumer .. automodule:: omotes_simulator_core.entities.assets.controller.controller_consumer :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_heat_transfer.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_heat_transfer.rst index 80e2b7e8..80ea5828 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_heat_transfer.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_heat_transfer.rst @@ -3,5 +3,5 @@ entities.assets.controller.controller_heat_transfer .. automodule:: omotes_simulator_core.entities.assets.controller.controller_heat_transfer :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_network.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_network.rst index 149be7e6..8cc41847 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_network.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_network.rst @@ -3,5 +3,5 @@ entities.assets.controller.controller_network .. automodule:: omotes_simulator_core.entities.assets.controller.controller_network :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_producer.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_producer.rst index aeba68ff..7d1ab66c 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_producer.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_producer.rst @@ -3,5 +3,5 @@ entities.assets.controller.controller_producer .. automodule:: omotes_simulator_core.entities.assets.controller.controller_producer :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_storage.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_storage.rst index f568de52..e8ad1740 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_storage.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.controller_storage.rst @@ -3,5 +3,5 @@ entities.assets.controller.controller_storage .. automodule:: omotes_simulator_core.entities.assets.controller.controller_storage :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.profile_interpolation.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.profile_interpolation.rst index 74309b88..69b0d21f 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.profile_interpolation.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.profile_interpolation.rst @@ -3,5 +3,5 @@ entities.assets.controller.profile_interpolation .. automodule:: omotes_simulator_core.entities.assets.controller.profile_interpolation :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.rst index 69cea2ea..5f88d48d 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.rst @@ -3,8 +3,8 @@ entities.assets.controller .. automodule:: omotes_simulator_core.entities.assets.controller :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.controller.temperature_data.rst b/doc/developer/api/omotes_simulator_core.entities.assets.controller.temperature_data.rst index a91242e1..669f5a78 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.controller.temperature_data.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.controller.temperature_data.rst @@ -3,5 +3,5 @@ entities.assets.controller.temperature_data .. automodule:: omotes_simulator_core.entities.assets.controller.temperature_data :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.demand_cluster.rst b/doc/developer/api/omotes_simulator_core.entities.assets.demand_cluster.rst index 1f131a95..4bda6a43 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.demand_cluster.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.demand_cluster.rst @@ -3,5 +3,5 @@ entities.assets.demand_cluster .. automodule:: omotes_simulator_core.entities.assets.demand_cluster :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.esdl_asset_object.rst b/doc/developer/api/omotes_simulator_core.entities.assets.esdl_asset_object.rst index c3a82142..3bdb8d29 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.esdl_asset_object.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.esdl_asset_object.rst @@ -3,5 +3,5 @@ entities.assets.esdl_asset_object .. automodule:: omotes_simulator_core.entities.assets.esdl_asset_object :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.heat_exchanger.rst b/doc/developer/api/omotes_simulator_core.entities.assets.heat_exchanger.rst index bcd3efb1..4f30c4ac 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.heat_exchanger.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.heat_exchanger.rst @@ -3,5 +3,5 @@ entities.assets.heat_exchanger .. automodule:: omotes_simulator_core.entities.assets.heat_exchanger :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.heat_pump.rst b/doc/developer/api/omotes_simulator_core.entities.assets.heat_pump.rst index a1b8d2fb..06fc0f4b 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.heat_pump.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.heat_pump.rst @@ -3,5 +3,5 @@ entities.assets.heat_pump .. automodule:: omotes_simulator_core.entities.assets.heat_pump :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.ideal_heat_storage.rst b/doc/developer/api/omotes_simulator_core.entities.assets.ideal_heat_storage.rst index 708a1b85..b36e18bb 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.ideal_heat_storage.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.ideal_heat_storage.rst @@ -3,5 +3,5 @@ entities.assets.ideal_heat_storage .. automodule:: omotes_simulator_core.entities.assets.ideal_heat_storage :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.junction.rst b/doc/developer/api/omotes_simulator_core.entities.assets.junction.rst index 2cd04b63..8fca6261 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.junction.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.junction.rst @@ -3,5 +3,5 @@ entities.assets.junction .. automodule:: omotes_simulator_core.entities.assets.junction :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.pipe.rst b/doc/developer/api/omotes_simulator_core.entities.assets.pipe.rst index 6663e354..c0169322 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.pipe.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.pipe.rst @@ -3,5 +3,5 @@ entities.assets.pipe .. automodule:: omotes_simulator_core.entities.assets.pipe :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.production_cluster.rst b/doc/developer/api/omotes_simulator_core.entities.assets.production_cluster.rst index 98d6a0bc..e7ec0cf9 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.production_cluster.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.production_cluster.rst @@ -3,5 +3,5 @@ entities.assets.production_cluster .. automodule:: omotes_simulator_core.entities.assets.production_cluster :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.pyjnius_loader.rst b/doc/developer/api/omotes_simulator_core.entities.assets.pyjnius_loader.rst index f60fec00..af5d206d 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.pyjnius_loader.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.pyjnius_loader.rst @@ -3,5 +3,5 @@ entities.assets.pyjnius_loader .. automodule:: omotes_simulator_core.entities.assets.pyjnius_loader :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.rst b/doc/developer/api/omotes_simulator_core.entities.assets.rst index 70549670..e3b85d24 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.rst @@ -3,8 +3,8 @@ entities.assets .. automodule:: omotes_simulator_core.entities.assets :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.entities.assets.utils.rst b/doc/developer/api/omotes_simulator_core.entities.assets.utils.rst index b1b69199..708202d1 100644 --- a/doc/developer/api/omotes_simulator_core.entities.assets.utils.rst +++ b/doc/developer/api/omotes_simulator_core.entities.assets.utils.rst @@ -3,5 +3,5 @@ entities.assets.utils .. automodule:: omotes_simulator_core.entities.assets.utils :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.esdl_object.rst b/doc/developer/api/omotes_simulator_core.entities.esdl_object.rst index b612c709..fe7afb0b 100644 --- a/doc/developer/api/omotes_simulator_core.entities.esdl_object.rst +++ b/doc/developer/api/omotes_simulator_core.entities.esdl_object.rst @@ -3,5 +3,5 @@ entities.esdl_object .. automodule:: omotes_simulator_core.entities.esdl_object :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.heat_network.rst b/doc/developer/api/omotes_simulator_core.entities.heat_network.rst index 521372c1..f01d0604 100644 --- a/doc/developer/api/omotes_simulator_core.entities.heat_network.rst +++ b/doc/developer/api/omotes_simulator_core.entities.heat_network.rst @@ -3,5 +3,5 @@ entities.heat_network .. automodule:: omotes_simulator_core.entities.heat_network :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.network_controller.rst b/doc/developer/api/omotes_simulator_core.entities.network_controller.rst index 79813ee0..90dc0873 100644 --- a/doc/developer/api/omotes_simulator_core.entities.network_controller.rst +++ b/doc/developer/api/omotes_simulator_core.entities.network_controller.rst @@ -3,5 +3,5 @@ entities.network_controller .. automodule:: omotes_simulator_core.entities.network_controller :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.network_controller_abstract.rst b/doc/developer/api/omotes_simulator_core.entities.network_controller_abstract.rst index 4081ab89..ec933a43 100644 --- a/doc/developer/api/omotes_simulator_core.entities.network_controller_abstract.rst +++ b/doc/developer/api/omotes_simulator_core.entities.network_controller_abstract.rst @@ -3,5 +3,5 @@ entities.network_controller_abstract .. automodule:: omotes_simulator_core.entities.network_controller_abstract :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.rst b/doc/developer/api/omotes_simulator_core.entities.rst index 7e48513d..a630e40d 100644 --- a/doc/developer/api/omotes_simulator_core.entities.rst +++ b/doc/developer/api/omotes_simulator_core.entities.rst @@ -3,8 +3,8 @@ entities .. automodule:: omotes_simulator_core.entities :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.entities.simulation_configuration.rst b/doc/developer/api/omotes_simulator_core.entities.simulation_configuration.rst index b62e66c7..9c6a6a7b 100644 --- a/doc/developer/api/omotes_simulator_core.entities.simulation_configuration.rst +++ b/doc/developer/api/omotes_simulator_core.entities.simulation_configuration.rst @@ -3,5 +3,5 @@ entities.simulation_configuration .. automodule:: omotes_simulator_core.entities.simulation_configuration :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.utility.influxdb_reader.rst b/doc/developer/api/omotes_simulator_core.entities.utility.influxdb_reader.rst index ec431a4b..d0df7c21 100644 --- a/doc/developer/api/omotes_simulator_core.entities.utility.influxdb_reader.rst +++ b/doc/developer/api/omotes_simulator_core.entities.utility.influxdb_reader.rst @@ -3,5 +3,5 @@ entities.utility.influxdb_reader .. automodule:: omotes_simulator_core.entities.utility.influxdb_reader :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.entities.utility.rst b/doc/developer/api/omotes_simulator_core.entities.utility.rst index 0636ccc9..4ed31cec 100644 --- a/doc/developer/api/omotes_simulator_core.entities.utility.rst +++ b/doc/developer/api/omotes_simulator_core.entities.utility.rst @@ -3,8 +3,8 @@ entities.utility .. automodule:: omotes_simulator_core.entities.utility :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.app.rst b/doc/developer/api/omotes_simulator_core.infrastructure.app.rst index 4565d73d..9115c266 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.app.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.app.rst @@ -3,5 +3,5 @@ infrastructure.app .. automodule:: omotes_simulator_core.infrastructure.app :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.plotting.rst b/doc/developer/api/omotes_simulator_core.infrastructure.plotting.rst index 71b402f2..f2e29bcc 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.plotting.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.plotting.rst @@ -3,5 +3,5 @@ infrastructure.plotting .. automodule:: omotes_simulator_core.infrastructure.plotting :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.profiling.rst b/doc/developer/api/omotes_simulator_core.infrastructure.profiling.rst index 4d2a7ce0..4275bd99 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.profiling.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.profiling.rst @@ -3,5 +3,5 @@ infrastructure.profiling .. automodule:: omotes_simulator_core.infrastructure.profiling :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.rst b/doc/developer/api/omotes_simulator_core.infrastructure.rst index 391f0ccd..20a80325 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.rst @@ -3,8 +3,8 @@ infrastructure .. automodule:: omotes_simulator_core.infrastructure :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.simulation_manager.rst b/doc/developer/api/omotes_simulator_core.infrastructure.simulation_manager.rst index b7cadd1a..92373e3f 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.simulation_manager.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.simulation_manager.rst @@ -3,5 +3,5 @@ infrastructure.simulation_manager .. automodule:: omotes_simulator_core.infrastructure.simulation_manager :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.infrastructure.utils.rst b/doc/developer/api/omotes_simulator_core.infrastructure.utils.rst index e6acc92a..fec64c0d 100644 --- a/doc/developer/api/omotes_simulator_core.infrastructure.utils.rst +++ b/doc/developer/api/omotes_simulator_core.infrastructure.utils.rst @@ -3,5 +3,5 @@ infrastructure.utils .. automodule:: omotes_simulator_core.infrastructure.utils :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.rst b/doc/developer/api/omotes_simulator_core.rst index 71d42db3..b94c9b43 100644 --- a/doc/developer/api/omotes_simulator_core.rst +++ b/doc/developer/api/omotes_simulator_core.rst @@ -3,8 +3,8 @@ API Root Index .. automodule:: omotes_simulator_core :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.simulation.mappers.mappers.rst b/doc/developer/api/omotes_simulator_core.simulation.mappers.mappers.rst index b5eede19..df3f7798 100644 --- a/doc/developer/api/omotes_simulator_core.simulation.mappers.mappers.rst +++ b/doc/developer/api/omotes_simulator_core.simulation.mappers.mappers.rst @@ -3,5 +3,5 @@ simulation.mappers.mappers .. automodule:: omotes_simulator_core.simulation.mappers.mappers :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.simulation.mappers.rst b/doc/developer/api/omotes_simulator_core.simulation.mappers.rst index 2f2e9aa7..0f9f5a7b 100644 --- a/doc/developer/api/omotes_simulator_core.simulation.mappers.rst +++ b/doc/developer/api/omotes_simulator_core.simulation.mappers.rst @@ -3,8 +3,8 @@ simulation.mappers .. automodule:: omotes_simulator_core.simulation.mappers :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.simulation.networksimulation.rst b/doc/developer/api/omotes_simulator_core.simulation.networksimulation.rst index 4c846971..6da69ffb 100644 --- a/doc/developer/api/omotes_simulator_core.simulation.networksimulation.rst +++ b/doc/developer/api/omotes_simulator_core.simulation.networksimulation.rst @@ -3,5 +3,5 @@ simulation.networksimulation .. automodule:: omotes_simulator_core.simulation.networksimulation :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.simulation.rst b/doc/developer/api/omotes_simulator_core.simulation.rst index 49176eff..84ba9db3 100644 --- a/doc/developer/api/omotes_simulator_core.simulation.rst +++ b/doc/developer/api/omotes_simulator_core.simulation.rst @@ -3,8 +3,8 @@ simulation .. automodule:: omotes_simulator_core.simulation :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.solver.matrix.equation_object.rst b/doc/developer/api/omotes_simulator_core.solver.matrix.equation_object.rst index 117f87e6..7b658bce 100644 --- a/doc/developer/api/omotes_simulator_core.solver.matrix.equation_object.rst +++ b/doc/developer/api/omotes_simulator_core.solver.matrix.equation_object.rst @@ -3,5 +3,5 @@ solver.matrix.equation_object .. automodule:: omotes_simulator_core.solver.matrix.equation_object :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.matrix.index_core_quantity.rst b/doc/developer/api/omotes_simulator_core.solver.matrix.index_core_quantity.rst index 0737f298..eb3672f1 100644 --- a/doc/developer/api/omotes_simulator_core.solver.matrix.index_core_quantity.rst +++ b/doc/developer/api/omotes_simulator_core.solver.matrix.index_core_quantity.rst @@ -3,5 +3,5 @@ solver.matrix.index_core_quantity .. automodule:: omotes_simulator_core.solver.matrix.index_core_quantity :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.matrix.matrix.rst b/doc/developer/api/omotes_simulator_core.solver.matrix.matrix.rst index bc5ec47c..1c340b67 100644 --- a/doc/developer/api/omotes_simulator_core.solver.matrix.matrix.rst +++ b/doc/developer/api/omotes_simulator_core.solver.matrix.matrix.rst @@ -3,5 +3,5 @@ solver.matrix.matrix .. automodule:: omotes_simulator_core.solver.matrix.matrix :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.matrix.rst b/doc/developer/api/omotes_simulator_core.solver.matrix.rst index 41ca3d48..476eb456 100644 --- a/doc/developer/api/omotes_simulator_core.solver.matrix.rst +++ b/doc/developer/api/omotes_simulator_core.solver.matrix.rst @@ -3,8 +3,8 @@ solver.matrix .. automodule:: omotes_simulator_core.solver.matrix :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.air_to_water_heat_pump.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.air_to_water_heat_pump.rst index 908af1c6..d9094e12 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.air_to_water_heat_pump.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.air_to_water_heat_pump.rst @@ -3,5 +3,5 @@ solver.network.assets.air_to_water_heat_pump .. automodule:: omotes_simulator_core.solver.network.assets.air_to_water_heat_pump :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_asset.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_asset.rst index 8cb2d3d6..b856c90f 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_asset.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_asset.rst @@ -3,5 +3,5 @@ solver.network.assets.base_asset .. automodule:: omotes_simulator_core.solver.network.assets.base_asset :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_item.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_item.rst index 24ecd7ea..a93486ca 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_item.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_item.rst @@ -3,5 +3,5 @@ solver.network.assets.base_item .. automodule:: omotes_simulator_core.solver.network.assets.base_item :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_node_item.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_node_item.rst index 5714e483..3cd988b7 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.base_node_item.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.base_node_item.rst @@ -3,5 +3,5 @@ solver.network.assets.base_node_item .. automodule:: omotes_simulator_core.solver.network.assets.base_node_item :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.boundary.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.boundary.rst index 0338db40..77626244 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.boundary.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.boundary.rst @@ -3,5 +3,5 @@ solver.network.assets.boundary .. automodule:: omotes_simulator_core.solver.network.assets.boundary :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.buffer_asset.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.buffer_asset.rst index 37db7636..727bac0d 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.buffer_asset.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.buffer_asset.rst @@ -3,5 +3,5 @@ solver.network.assets.buffer_asset .. automodule:: omotes_simulator_core.solver.network.assets.buffer_asset :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.fall_type.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.fall_type.rst index 6e84f67d..9886ef76 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.fall_type.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.fall_type.rst @@ -3,5 +3,5 @@ solver.network.assets.fall_type .. automodule:: omotes_simulator_core.solver.network.assets.fall_type :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.heat_transfer_asset.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.heat_transfer_asset.rst index 97ca7a82..db8557fb 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.heat_transfer_asset.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.heat_transfer_asset.rst @@ -3,5 +3,5 @@ solver.network.assets.heat_transfer_asset .. automodule:: omotes_simulator_core.solver.network.assets.heat_transfer_asset :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.node.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.node.rst index 05f24c1c..66122eab 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.node.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.node.rst @@ -3,5 +3,5 @@ solver.network.assets.node .. automodule:: omotes_simulator_core.solver.network.assets.node :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.production_asset.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.production_asset.rst index 6fe926d5..74c6b66b 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.production_asset.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.production_asset.rst @@ -3,5 +3,5 @@ solver.network.assets.production_asset .. automodule:: omotes_simulator_core.solver.network.assets.production_asset :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.rst index ccd9bcc7..cd32c42a 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.rst @@ -3,8 +3,8 @@ solver.network.assets .. automodule:: omotes_simulator_core.solver.network.assets :members: - :undoc-members: :show-inheritance: + :undoc-members: Submodules ---------- diff --git a/doc/developer/api/omotes_simulator_core.solver.network.assets.solver_pipe.rst b/doc/developer/api/omotes_simulator_core.solver.network.assets.solver_pipe.rst index f769f0f9..36d6fe89 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.assets.solver_pipe.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.assets.solver_pipe.rst @@ -3,5 +3,5 @@ solver.network.assets.solver_pipe .. automodule:: omotes_simulator_core.solver.network.assets.solver_pipe :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.network.rst b/doc/developer/api/omotes_simulator_core.solver.network.network.rst index b8c0664c..e3b68646 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.network.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.network.rst @@ -3,5 +3,5 @@ solver.network.network .. automodule:: omotes_simulator_core.solver.network.network :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.network.rst b/doc/developer/api/omotes_simulator_core.solver.network.rst index 747490ef..aac311d4 100644 --- a/doc/developer/api/omotes_simulator_core.solver.network.rst +++ b/doc/developer/api/omotes_simulator_core.solver.network.rst @@ -3,8 +3,8 @@ solver.network .. automodule:: omotes_simulator_core.solver.network :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.solver.rst b/doc/developer/api/omotes_simulator_core.solver.rst index b20e9939..e00f9b2d 100644 --- a/doc/developer/api/omotes_simulator_core.solver.rst +++ b/doc/developer/api/omotes_simulator_core.solver.rst @@ -3,8 +3,8 @@ solver .. automodule:: omotes_simulator_core.solver :members: - :undoc-members: :show-inheritance: + :undoc-members: Subpackages ----------- diff --git a/doc/developer/api/omotes_simulator_core.solver.solver.rst b/doc/developer/api/omotes_simulator_core.solver.solver.rst index 76d6b5af..9e30e1ce 100644 --- a/doc/developer/api/omotes_simulator_core.solver.solver.rst +++ b/doc/developer/api/omotes_simulator_core.solver.solver.rst @@ -3,5 +3,5 @@ solver.solver .. automodule:: omotes_simulator_core.solver.solver :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/api/omotes_simulator_core.solver.solver_constants.rst b/doc/developer/api/omotes_simulator_core.solver.solver_constants.rst index 776696d5..ec94dbd9 100644 --- a/doc/developer/api/omotes_simulator_core.solver.solver_constants.rst +++ b/doc/developer/api/omotes_simulator_core.solver.solver_constants.rst @@ -3,5 +3,5 @@ solver.solver_constants .. automodule:: omotes_simulator_core.solver.solver_constants :members: - :undoc-members: :show-inheritance: + :undoc-members: diff --git a/doc/developer/control_extension.rst b/doc/developer/control_extension.rst new file mode 100644 index 00000000..f34af6cb --- /dev/null +++ b/doc/developer/control_extension.rst @@ -0,0 +1,290 @@ +Extending Control Behavior +========================== + +Purpose +------- + +Use this guide when you need to add a new controller type, extend an existing controller, +modify dispatch logic, or change how setpoints are propagated to assets. This is +implementation-oriented, contributor-facing documentation — not a user-facing conceptual +overview of control. + +This page is for contributors who work at the Python implementation level. For conceptual +explanations of what the control system does, consult :doc:`../controller/controller`. For +physical impact and detailed dispatch mechanics, consult :doc:`../controller/controller_behavior`. + +Control Architecture for Contributors +------------------------------------- + +The control layer is split into three tiers: + +**Asset-level controllers** (``entities/assets/controller/``) + Per-asset classes such as ``ControllerProducer``, ``ControllerConsumer``, + ``ControllerAtesStorage``, ``ControllerIdealHeatStorage``, ``ControllerHeatTransferAsset``. + Each inherits from ``AssetControllerAbstract``. They own asset-specific state + (profiles, demand, stored energy, COP) and the logic to compute per-asset setpoints. + +**Network-level controller** (``entities/network_controller.py``) + The ``NetworkController`` class. It owns a list of ``ControllerNetwork`` objects + (one per hydraulically isolated sub-network). Each ``ControllerNetwork`` contains the + asset-level controllers for its sub-network. ``NetworkController`` orchestrates the + dispatch: update network state, calculate per-network totals, distribute demand across + producers, and return the setpoints dict. + +**Abstract contract** (``entities/network_controller_abstract.py``) + The ``NetworkControllerAbstract`` base class defines the minimal interface that + ``NetworkSimulation`` depends on: one abstract method, ``update_setpoints(time)``. + ``NetworkSimulation`` calls ``update_network_state`` and ``update_setpoints`` on the + abstract interface; it does not know about individual asset controllers or the + ``ControllerNetwork`` grouping logic. + +Relevant Modules and Files +-------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 38 22 40 + + * - File or Module + - Role + - Why it matters for this topic + * - ``src/omotes_simulator_core/entities/network_controller_abstract.py`` + - Abstract interface + - Defines the contract that ``NetworkSimulation`` depends on. Any custom controller + must inherit from this and implement ``update_setpoints``. + * - ``src/omotes_simulator_core/entities/network_controller.py`` + - Concrete implementation + - Current dispatch logic. Owns update orchestration, network-level balancing, + and producer priority/curtailment. Study this before modifying dispatch. + * - ``src/omotes_simulator_core/entities/assets/controller/asset_controller_abstract.py`` + - Asset-level base class + - Minimal contract for per-asset controllers. Defines ``set_state`` (receive network + state from entity layer) and ``calculate_setpoints`` (return a dict per timestep). + * - ``src/omotes_simulator_core/entities/assets/controller/controller_network.py`` + - Network grouping + - Groups asset controllers by hydraulic connectivity. Holds producer, consumer, storage, + and heat-transfer asset lists. Study when extending to understand sub-network + isolation and factor adjustment for multi-network systems. + * - ``src/omotes_simulator_core/entities/assets/controller/controller_producer.py`` + - Producer logic + - Example: supply-temperature and demand-based setpoint logic for production assets. + * - ``src/omotes_simulator_core/entities/assets/controller/controller_consumer.py`` + - Consumer logic + - Example: demand profile and return temperature logic for demand assets. + * - ``src/omotes_simulator_core/adapter/transforms/controller_mapper.py`` + - ESDL-to-controller mapper + - ``EsdlControllerMapper.to_entity`` creates the network controller from the ESDL. + Contains the instantiation dispatch. + * - ``src/omotes_simulator_core/adapter/transforms/controller_mappers/`` + - Per-asset controller mappers + - One mapper per asset-level controller type (``controller_producer_mapper.py``, + ``controller_consumer_mapper.py``, etc.). Each inherits from ``EsdlMapperAbstract``. + * - ``unit_test/entities/controller/`` + - Controller unit tests + - Unit tests for all controller classes. Use ``Mock(spec=ControllerNetwork)`` to + isolate asset controllers from network-level logic. + * - ``unit_test/integration/test_communication_controller_network.py`` + - Integration coupling test + - Verifies that ``update_network_state`` correctly propagates entity-layer asset state + to per-asset controller objects. This is the most important integration test for + controller changes. + +Step-by-step Workflow +--------------------- + +1. Create or modify an asset-level controller class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Asset controllers live in ``src/omotes_simulator_core/entities/assets/controller/``. + +Inherit from ``AssetControllerAbstract``: + +.. code-block:: python + + from omotes_simulator_core.entities.assets.controller.asset_controller_abstract import ( + AssetControllerAbstract, + ) + + class ControllerMyAsset(AssetControllerAbstract): + def __init__(self, asset_id: str, time_step: float) -> None: + super().__init__(asset_id, time_step) + # Initialize asset-specific state (profiles, COP, storage, etc.) + + def set_state(self, state: dict[str, float]) -> None: + # Called by NetworkController.update_network_state() before each update_setpoints. + # Receive state dict from entity-layer asset via get_state(). + # Example: read current supply temperature or storage level. + pass + + def calculate_setpoints(self, time: datetime.datetime) -> dict[str, float]: + # Called by ControllerNetwork or NetworkController.update_setpoints(). + # Return a dict mapping property names to setpoint values. + # Example: return {"heat_demand": 100000, "supply_temperature": 55} + return {} + +The two key methods are: + +- ``set_state`` — receive current network state (temperature, flow, pressure) from the + entity-layer asset. +- ``calculate_setpoints`` — compute and return the setpoints for the next solver call. + +2. Wire the new asset controller into ControllerNetwork +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Edit ``src/omotes_simulator_core/entities/assets/controller/controller_network.py``. + +In the ``ControllerNetwork.__init__`` constructor or in ``EsdlControllerMapper``, add the new +asset controller to the appropriate list: + +- ``self.producers`` — for production assets +- ``self.consumers`` — for demand assets +- ``self.storages`` — for storage assets +- ``self.heat_transfer_assets_prim`` or ``self.heat_transfer_assets_sec`` — for heat exchangers + or heat pumps + +Then update ``calculate_setpoints`` inside ``ControllerNetwork`` (if it exists) or inside +``NetworkController.update_setpoints`` to include logic that consults your new controller. + +3. Create the controller mapper +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create a new file in ``src/omotes_simulator_core/adapter/transforms/controller_mappers/``, +for example ``controller_my_asset_mapper.py``. + +Inherit from ``EsdlMapperAbstract``: + +.. code-block:: python + + from omotes_simulator_core.simulation.mappers.mappers import EsdlMapperAbstract + from omotes_simulator_core.entities.assets.controller.asset_controller_abstract import ( + AssetControllerAbstract, + ) + from omotes_simulator_core.entities.assets.esdl_asset_object import EsdlAssetObject + from omotes_simulator_core.entities.assets.controller.controller_my_asset import ( + ControllerMyAsset, + ) + + class EsdlControllerMyAssetMapper(EsdlMapperAbstract): + + def to_esdl(self, entity: ControllerMyAsset) -> EsdlAssetObject: + raise NotImplementedError("EsdlControllerMyAssetMapper.to_esdl()") + + def to_entity(self, esdl_asset: EsdlAssetObject, timestep: float) -> AssetControllerAbstract: + return ControllerMyAsset( + asset_id=esdl_asset.esdl_asset.id, + time_step=timestep, + # read additional properties with esdl_asset.get_property(name, default) + ) + +4. Register the mapper +~~~~~~~~~~~~~~~~~~~~~~~ + +Open ``src/omotes_simulator_core/adapter/transforms/controller_mapper.py`` and add two changes. + +First, import the new mapper: + +.. code-block:: python + + from omotes_simulator_core.adapter.transforms.controller_mappers.controller_my_asset_mapper import ( + EsdlControllerMyAssetMapper, + ) + +Second, add an entry to the controller dispatch table (inside ``EsdlControllerMapper.to_entity`` +or in a dispatch dict): + +.. code-block:: python + + mapper = EsdlControllerMyAssetMapper() + controller = mapper.to_entity(esdl_asset, timestep=config.timestep) + +The exact pattern depends on the current controller mapper implementation. Study the existing +mappers for the current pattern. + +5. Add unit and integration tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unit tests for the asset-level controller belong in ``unit_test/entities/controller/``. +Follow the pattern of existing controller tests: + +.. code-block:: python + + class ControllerMyAssetTest(unittest.TestCase): + def setUp(self) -> None: + self.controller = ControllerMyAsset(asset_id="my_asset_id", time_step=3600) + + def test_calculate_setpoints(self) -> None: + time = datetime.datetime(2020, 1, 1, 0, 0, 0) + setpoints = self.controller.calculate_setpoints(time) + self.assertIn("heat_demand", setpoints) + self.assertIsInstance(setpoints["heat_demand"], (int, float)) + + def test_set_state(self) -> None: + state = {"supply_temperature": 55, "mass_flow": 100} + self.controller.set_state(state) # Should not raise + +Use ``Mock(spec=ControllerNetwork)`` when you need to mock the network object passed to your +controller. + +Integration tests belong in ``unit_test/integration/``. The most relevant integration test +is ``test_communication_controller_network.py``, which verifies that ``update_network_state`` +correctly reads from entity-layer assets and propagates state to your controller. Add a test +there if your controller depends on new state properties. + +Testing control changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +Before submitting: + +1. Run unit tests for your new or modified controller class: + + .. code-block:: bash + + python -m pytest unit_test/entities/controller/test_controller_my_asset.py + +2. Run the integration test that exercises the entity-controller communication: + + .. code-block:: bash + + python -m pytest unit_test/integration/test_communication_controller_network.py + +3. Run a full integration test against a real ESDL file that includes your asset type: + + .. code-block:: bash + + python -m pytest unit_test/integration/test_heat_physics.py + +4. Run the full suite: + + .. code-block:: bash + + python -m pytest unit_test/ + +Common Pitfalls +--------------- + +- **Forgetting to register the mapper**: new controller types that are not registered in + ``controller_mapper.py`` will silently produce no controller in the network. Always register + and always add a unit test for the mapper. +- **Breaking the abstract contract**: ``NetworkSimulation`` calls ``update_setpoints`` only. + Do not require ``NetworkSimulation`` to call additional methods. If your controller needs + initialization, do it in the constructor or lazily inside ``update_setpoints``. +- **Circular dependencies**: asset controllers must not import from ``HeatNetwork`` or + ``Solver``. State flow is unidirectional: entity layer reads state from asset and passes + it to the controller via ``set_state``. +- **Ignoring network isolation**: heat exchangers and heat pumps connect multiple + ``ControllerNetwork`` objects. If your controller modifies supply temperature or COP based + on state, test it with a multi-network ESDL file (e.g. with a heat pump that bridges + two networks). +- **Confusing controller setpoints with solver unknowns**: the controller returns a setpoint + dict; the solver then solves a nonlinear system to find the state that satisfies both + the controller's setpoints and the physical equations. Do not expect the solver to produce + exactly the setpoint values — it produces the closest solution that respects physics. + +Related Documentation +--------------------- + +- Conceptual overview of control: :doc:`../controller/controller` +- Control behavior and dispatch mechanics: :doc:`../controller/controller_behavior` +- Simulation orchestration and control flow: :doc:`simulation_contributor_flow` +- Test layout and patterns: :doc:`testing` +- Full class and module reference: :doc:`api/omotes_simulator_core` diff --git a/doc/developer/developer_main.rst b/doc/developer/developer_main.rst index ee6a3bad..ab3a7d0a 100644 --- a/doc/developer/developer_main.rst +++ b/doc/developer/developer_main.rst @@ -1,21 +1,14 @@ Developer Documentation ======================= -This section groups contributor-facing material and lower-level technical reference for -OMOTES.SIMULATOR_CORE. +This section contains contributor-facing guides for OMOTES.SIMULATOR_CORE. -Use this section when you need implementation-oriented guidance, generated module reference, or -lower-level supporting pages that sit outside the end-user conceptual flow. +Use this section when you need implementation-oriented guidance — how the code is organized, +how to extend the package, how to test your changes, and how to navigate the generated API +reference. -How to use this section ------------------------ - -- Start with the developer navigation page to pick the right path. -- Use the curated reference pages (Architecture, Asset, Solver, Controller) when you need - technical reference organized by topic rather than by Python package. -- Use the API root index for exhaustive package/module/class lookup that the curated pages - do not cover. -- Use Intro, Solver, Network, Physics, and Control for conceptual behavior and interpretation. +For system-level conceptual behavior and governing relations, consult the Intro, Solver, +Network, Physics, and Control sections instead. **Contents** @@ -24,8 +17,18 @@ How to use this section :titlesonly: developer_navigation - ../reference/architecture_reference - ../reference/asset_reference - ../reference/solver_reference - ../reference/controller_reference + simulation_contributor_flow + add_new_asset + add_new_output_format + control_extension + testing + writing_documentation_with_ai api/omotes_simulator_core + + +How to use this section +----------------------- + +- Start with :doc:`developer_navigation` to choose the correct guide for your task. +- Use the toctree above for direct access once you know which page you need. + diff --git a/doc/developer/developer_navigation.rst b/doc/developer/developer_navigation.rst index dec99244..f4f58a2c 100644 --- a/doc/developer/developer_navigation.rst +++ b/doc/developer/developer_navigation.rst @@ -1,4 +1,4 @@ -Developer navigation +Developer Navigation ==================== Purpose @@ -9,19 +9,16 @@ Use this page to quickly choose the right developer documentation path. Start here ---------- -- Need curated technical reference by topic or internal model grouping: go to - :doc:`../reference/architecture_reference`, :doc:`../reference/asset_reference`, - :doc:`../reference/solver_reference`, or :doc:`../reference/controller_reference`. -- Need exhaustive package/module/class lookup instead: go to - :doc:`api/omotes_simulator_core`. -- Need system-level conceptual behavior first: go to :doc:`../intro/intro_main`, - :doc:`../solver/solver_main`, :doc:`../network/network_main`, :doc:`../physics/physics_main`, - or :doc:`../controller/controller`. +- :doc:`simulation_contributor_flow` — use this first for code layout, package structure, + and full execution flow from entrypoint to solver. +- :doc:`add_new_asset` — add a new thermo-hydraulic asset type (entity layer, solver layer, + ESDL mapper, and registry wiring). +- :doc:`add_new_output_format` — add or modify output columns, output datasets, or output + DataFrame assembly behavior. +- :doc:`control_extension` — add or modify controller classes, mappers, and dispatch logic. +- :doc:`testing` — locate tests, run the suite, and follow unit and integration test patterns. +- :doc:`writing_documentation_with_ai` — use the repository AI agent workflow for + documentation authoring, review, and validation. +- :doc:`api/omotes_simulator_core` — use for exhaustive package, module, and class lookup. -Common entry points -------------------- - -- Simulation orchestration APIs: :doc:`api/omotes_simulator_core.infrastructure.simulation_manager` -- Network simulation APIs: :doc:`api/omotes_simulator_core.simulation.networksimulation` -- Heat-network entity APIs: :doc:`api/omotes_simulator_core.entities.heat_network` -- Solver APIs: :doc:`api/omotes_simulator_core.solver.solver` +Use this page as the single routing index for developer tasks. diff --git a/doc/developer/simulation_contributor_flow.rst b/doc/developer/simulation_contributor_flow.rst new file mode 100644 index 00000000..ab52e9aa --- /dev/null +++ b/doc/developer/simulation_contributor_flow.rst @@ -0,0 +1,286 @@ +Simulation Contributor Flow +=========================== + +Purpose +------- + +This guide explains how the OMOTES.SIMULATOR_CORE package is organized, how simulation +executes end-to-end, and where to make changes safely. + +Read this page first before modifying any part of the package. It maps the six top-level +packages to their responsibilities, traces the execution path from the application +entrypoint through to the nonlinear solver, and identifies the abstractions that separate +each layer. + +This page is for contributors and new developers. For conceptual system-level explanations +consult the Intro, Solver, Network, and Control sections. For class-level detail use the +:doc:`api/omotes_simulator_core` root index. + +Relevant Modules and Files +-------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 38 22 40 + + * - File or Module + - Role + - Why it matters for this topic + * - ``src/omotes_simulator_core/infrastructure/app.py`` + - Entrypoint + - Builds ``SimulationConfiguration``, loads the ESDL file, and calls + ``SimulationManager.execute``. The ``run()`` function here is the single + entry point when the package is invoked from the command line. + * - ``src/omotes_simulator_core/infrastructure/simulation_manager.py`` + - Orchestrator + - Creates ``HeatNetwork`` and ``NetworkController`` from the ESDL object, then + creates ``NetworkSimulation`` and calls ``run``. Owns the error boundary for + a full simulation run. + * - ``src/omotes_simulator_core/entities/simulation_configuration.py`` + - Configuration dataclass + - Holds ``simulation_id``, ``name``, ``timestep``, ``start``, and ``stop``. + Passed from the entrypoint through to ``NetworkSimulation``. + * - ``src/omotes_simulator_core/simulation/networksimulation.py`` + - Time-step loop + - Owns the outer time loop, controller update sequencing, the convergence retry + loop (up to 20 iterations per timestep), and the progress callback cadence. + * - ``src/omotes_simulator_core/entities/heat_network.py`` + - Runtime network wrapper + - Holds the asset list and solver. Applies controller setpoints to assets per + timestep, calls ``Solver.solve``, checks convergence, post-processes assets, + and accumulates output. + * - ``src/omotes_simulator_core/entities/assets/asset_abstract.py`` + - Entity-layer base class + - Abstract base for all thermo-hydraulic asset entities. Defines + ``set_setpoints``, ``write_to_output``, and output collection. + * - ``src/omotes_simulator_core/solver/network/network.py`` + - Solver graph model + - Holds the dictionary of solver-layer assets and nodes consumed by ``Solver``. + Assets are added by the mapper, not by ``HeatNetwork`` directly. + * - ``src/omotes_simulator_core/solver/solver.py`` + - Nonlinear solve loop + - Builds the global matrix from each asset's ``get_equations()`` return value + and iterates (up to 100 inner iterations) until convergence. + * - ``src/omotes_simulator_core/entities/network_controller_abstract.py`` + - Control abstraction + - Defines the minimal contract used by ``NetworkSimulation``: one abstract + method, ``update_setpoints(time)``. + * - ``src/omotes_simulator_core/entities/network_controller.py`` + - Concrete controller + - Implements ``NetworkControllerAbstract``. Owns a list of ``ControllerNetwork`` + objects (one per hydraulically isolated sub-network) and orchestrates + per-asset setpoint dispatch across those networks. + * - ``src/omotes_simulator_core/adapter/transforms/mappers.py`` + - ESDL-to-entity mapper + - ``EsdlEnergySystemMapper.to_entity`` converts an ``EsdlObject`` into the + ``(list[AssetAbstract], list[Junction])`` tuple consumed by ``HeatNetwork``. + * - ``src/omotes_simulator_core/adapter/transforms/controller_mapper.py`` + - ESDL-to-controller mapper + - ``EsdlControllerMapper.to_entity`` converts an ``EsdlObject`` into a + ``NetworkController`` containing the correct ``ControllerNetwork`` objects. + * - ``src/omotes_simulator_core/adapter/transforms/esdl_asset_mapper.py`` + - Asset dispatch table + - Maps ESDL asset types to per-asset mapper classes via ``conversion_dict_mappers``. + * - ``unit_test/infrastructure/test_simulationmanager.py`` + - Orchestration unit tests + - Verifies ``SimulationManager.execute`` returns output and triggers the progress + callback correctly. + * - ``unit_test/simulation/test_networksimulation.py`` + - Loop-level unit tests + - Verifies the time-step loop, controller update order, and output collection. + * - ``unit_test/integration/test_heat_physics.py`` + - End-to-end integration test + - Runs a full simulation against ``testdata/test1.esdl`` and asserts physical + output values. The primary integration test for physics correctness. + +Package Layout +-------------- + +The source tree under ``src/omotes_simulator_core/`` contains six top-level packages: + +``infrastructure/`` + Application entrypoint (``app.py``) and ``SimulationManager``. This is the boundary + between the outside world and the simulation internals. It is also the right place to + add top-level error handling or result post-processing. + +``adapter/`` + Everything related to reading and transforming ESDL input. Contains three sub-packages: + + - ``transforms/`` — mapper classes that convert ESDL objects into internal entities and + controller objects. ``esdl_asset_mapper.py`` holds the dispatch table; each asset type + has a dedicated mapper in ``esdl_asset_mappers/``; each controller type has a dedicated + mapper in ``controller_mappers/``. + - ``utility/`` — graph utilities used by the ESDL-to-graph conversion step. + - ``presentation/`` — output presentation layer (currently minimal). + +``entities/`` + The runtime object model. Contains: + + - ``assets/`` — entity-layer asset classes (one per physics asset type), the abstract + base ``AssetAbstract``, and the ``controller/`` sub-package containing per-asset + controller classes. + - ``heat_network.py`` — the runtime container that holds all assets and the solver. + - ``network_controller.py`` and ``network_controller_abstract.py`` — the controller + and its minimal abstract contract. + - ``esdl_object.py``, ``simulation_configuration.py``, ``utility/`` — supporting types. + +``simulation/`` + The time-step orchestration loop (``networksimulation.py``) and the abstract mapper + base class (``mappers/mappers.py``). + +``solver/`` + The nonlinear physics solver. Contains: + + - ``solver.py`` — the solver entry point: assembles the equation matrix and iterates. + - ``network/`` — the solver-side graph model (``Network``) and solver-layer asset + classes under ``network/assets/``. + - ``matrix/`` — the ``Matrix`` class, ``EquationObject``, and index helpers used to + assemble and solve the linear system at each iteration. + +``entities/assets/controller/`` + Per-asset controller classes (``ControllerProducer``, ``ControllerConsumer``, + ``ControllerAtesStorage``, ``ControllerIdealHeatStorage``, ``ControllerHeatTransferAsset``) + and the ``ControllerNetwork`` class that groups hydraulically connected assets. + +Execution Flow +-------------- + +The following numbered steps trace a full simulation run from entrypoint to output: + +1. **Entrypoint** — ``app.run()`` creates a ``SimulationConfiguration`` dataclass (timestep, + start datetime, stop datetime), loads the ESDL file into an ``EsdlObject``, and calls + ``SimulationManager.execute(progress_callback)``. + +2. **ESDL parsing** — ``SimulationManager.execute`` creates two runtime objects from the + ESDL input in parallel: + + - ``HeatNetwork(EsdlEnergySystemMapper(esdl).to_entity)`` — the mapper callable is passed + as a factory argument. ``to_entity`` returns ``(list[AssetAbstract], list[Junction])``; + each asset constructor also creates and registers the corresponding solver-layer asset + inside the ``Network`` graph object. + - ``EsdlControllerMapper().to_entity(esdl, timestep=config.timestep)`` — returns a + ``NetworkController`` containing one ``ControllerNetwork`` per hydraulically isolated + sub-network. + +3. **Simulation loop** — ``SimulationManager`` creates ``NetworkSimulation(network, controller)`` + and calls ``worker.run(config, progress_callback)``. Inside ``run``: + + a. The loop iterates over each timestep from ``config.start`` to ``config.stop`` in + steps of ``config.timestep`` seconds. + + b. Per timestep: + + - ``controller.update_network_state(heat_network)`` — reads current asset state + (temperatures, flows) from each entity-layer asset and updates the corresponding + per-asset controller objects. + - ``controller.update_setpoints(time)`` — calculates and returns + ``controller_input``: a ``dict[asset_id, dict[property, value]]`` containing the + heat demand, supply temperature, return temperature, and pressure setpoints for + every asset. + - A convergence retry loop (up to 20 iterations) runs + ``network.run_time_step(time, timestep, controller_input)`` followed by + ``network.check_convergence()``. + + c. ``network.run_time_step`` applies the setpoints dict to each asset via + ``asset.set_setpoints(...)`` and calls ``solver.solve()``. + + d. ``solver.solve()`` calls ``asset.get_equations()`` on every solver-layer asset and + node in the ``Network`` graph, assembles the global matrix, and runs the linear + solver. The outer iteration loop in ``Solver.solve()`` repeats up to 100 times. + + e. After convergence (or iteration limit), ``network.post_process_assets()`` and + ``network.store_output()`` are called. + +4. **Output collection** — after the time loop, ``worker.gather_output()`` calls + ``network.gather_output()``, which collects each asset's output list into a single + ``pandas.DataFrame`` returned to the caller. + +Two-Layer Asset Model +--------------------- + +Every thermo-hydraulic asset is represented by two classes at different abstraction levels: + +**Entity layer** (``entities/assets/``) + Python classes such as ``ProductionCluster``, ``DemandCluster``, ``Pipe``, ``HeatPump``. + These hold per-timestep state, apply controller setpoints, collect output, and expose + ``get_state()`` for the controller. All inherit from ``AssetAbstract``. + +**Solver layer** (``solver/network/assets/``) + Low-level classes such as ``HeatBoundary``, ``SolverPipe``, ``HeatTransferAsset``. + These implement ``get_equations()`` and supply ``EquationObject`` instances to the + global matrix. They know about mass flow, pressure drop, and energy balance as + algebraic constraints — not about time series or ESDL properties. + +Each entity-layer asset creates its corresponding solver-layer asset in its constructor and +registers it with the ``Network`` graph. The entity layer accesses solver results through +``self.solver_asset`` after each ``Solver.solve()`` call. + +Control Architecture +-------------------- + +The control layer sits between ``NetworkSimulation`` and ``HeatNetwork``: + +- ``NetworkControllerAbstract`` defines the contract: one abstract method, + ``update_setpoints(time: datetime) -> dict``. +- ``NetworkController`` is the concrete implementation. It holds a list of + ``ControllerNetwork`` objects — one per hydraulically isolated sub-network. Each + ``ControllerNetwork`` holds per-asset controller objects + (``ControllerProducer``, ``ControllerConsumer``, ``ControllerAtesStorage``, etc.) + that own demand profiles and storage state. +- ``NetworkSimulation`` only calls ``update_network_state`` and ``update_setpoints`` on the + abstract interface; it does not know about individual asset controllers. + +Testing and Validation +---------------------- + +The most relevant tests for this execution flow are: + +- ``unit_test/infrastructure/test_simulationmanager.py`` — verifies the orchestration path: + checks that ``execute`` returns a non-empty ``DataFrame`` and that the progress callback + is invoked. +- ``unit_test/simulation/test_networksimulation.py`` — verifies the time-step loop in + isolation using mocked ``HeatNetwork`` and ``NetworkController`` objects. +- ``unit_test/integration/test_heat_physics.py`` — runs a full simulation against a real + ESDL file and asserts physical output values. Use this as the reference integration test. +- ``unit_test/integration/test_communication_controller_network.py`` — verifies that + ``update_network_state`` correctly propagates entity-layer asset state to per-asset + controller objects. + +Run the test suite from the repository root:: + + python -m pytest unit_test/ + +Common Pitfalls +--------------- + +- **Editing the wrong layer**: solver-layer asset classes (``solver/network/assets/``) must + not import from ``entities/``. Dependency runs upward only: entity layer depends on solver + layer, never the reverse. +- **Bypassing the mapper registry**: new asset types that are not registered in + ``esdl_asset_mapper.py``'s ``conversion_dict_mappers`` will silently produce no asset + in the network. Always register and always add a unit test for the mapper. +- **Skipping ``update_network_state``**: the controller's per-asset controller objects do + not read from the solver directly. They rely on ``update_network_state`` being called + before ``update_setpoints`` each timestep. If you add state that the controller needs, + expose it via ``AssetAbstract.get_state()`` and read it in ``NetworkController.update_network_state``. +- **Convergence retry confusion**: ``network.run_time_step`` is called inside a retry loop + of up to 20 iterations. Asset state that accumulates side effects across calls within a + single timestep will produce incorrect results. Use ``store_output`` for committed output + and ``post_process_assets`` for end-of-timestep finalization only. +- **Confusing the two solver iteration loops**: there is an outer iteration loop in + ``NetworkSimulation.run`` (convergence retries, max 20) and an inner loop inside + ``Solver.solve`` (matrix iterations, max 100). They serve different purposes: the outer + loop handles controller-physics coupling; the inner loop handles the nonlinear equation + solve. + +Related Documentation +--------------------- + +- Conceptual overview of the system: :doc:`../intro/intro_main` +- Solver behavior and equation assembly: :doc:`../solver/solver_main` +- Network representation: :doc:`../network/network_main` +- Control behavior and setpoint logic: :doc:`../controller/controller` +- Adding a new asset: :doc:`add_new_asset` +- Extending control behavior: :doc:`control_extension` +- Test layout and running tests: :doc:`testing` +- Full class and module reference: :doc:`api/omotes_simulator_core` diff --git a/doc/developer/testing.rst b/doc/developer/testing.rst new file mode 100644 index 00000000..423202a9 --- /dev/null +++ b/doc/developer/testing.rst @@ -0,0 +1,220 @@ +Testing Strategy +================ + +Purpose +------- + +This guide helps contributors understand where tests live, how to run the test suite, what +patterns to follow when writing new tests, and what to check before submitting a change. + +Use this page when you are adding a feature, fixing a bug, or making any structural change that +requires new or modified tests. It is implementation-oriented and assumes you can already navigate +the repository. It does not cover physics derivations or user-facing behavior. + +Test Layout +----------- + +All tests live under ``unit_test/``. The directory is flat at the top level; each subdirectory +targets a distinct layer or cross-cutting concern. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Subdirectory + - What it covers + * - ``unit_test/adapters/`` + - ESDL-to-entity mapping: ``EsdlGraphMapper``, controller mappers, and ESDL asset mappers. + Verifies that ESDL graph topology is translated correctly to internal objects. + * - ``unit_test/entities/`` + - Entity-layer asset classes (``Pipe``, ``HeatPump``, ``Ates``, etc.) and all + asset-level controller classes (``ControllerProducer``, ``ControllerConsumer``, etc.). + Each asset and controller class has its own test module. + * - ``unit_test/infrastructure/`` + - ``SimulationManager`` orchestration and plotting utilities. Tests here cover how + ``SimulationManager`` wires ESDL input to ``HeatNetwork`` and ``NetworkController``. + * - ``unit_test/integration/`` + - Cross-component end-to-end scenarios run through ``SimulationManager`` against real ESDL + files from ``testdata/``. Covers heat physics, pressure physics, zero-flow conditions, + heat transfer assets, and ideal heat buffers across full simulation runs. + * - ``unit_test/simulation/`` + - ``NetworkSimulation`` time-step orchestration. Verifies the simulation loop, controller + update sequencing, and convergence retry logic in isolation. + * - ``unit_test/solver/`` + - Low-level solver components: solver-layer asset classes (``BaseAsset``, ``SolverPipe``, + ``ProductionAsset``, etc.), the network matrix builder, and solver utility functions. + * - ``unit_test/transforms/`` + - Data transformation utilities: ESDL-to-dataframe mapper and transform utility helpers. + +Running Tests +------------- + +Install the development dependencies before running tests:: + + pip install -e ".[dev]" + +Run the full test suite from the repository root: + +.. code-block:: bash + + python -m pytest unit_test/ + +Because the previous step installs the package in editable mode, no manual ``PYTHONPATH`` +setup is required on any platform. Add ``-p no:faulthandler`` to suppress low-level crash +reporting that can produce spurious output when the solver reaches certain numerical states. + +To run only a single subdirectory during development:: + + python -m pytest unit_test/entities/ + +To run a single test file:: + + python -m pytest unit_test/entities/test_pipe.py + +Unit Test Patterns +------------------ + +Asset unit tests +~~~~~~~~~~~~~~~~ + +Unit tests for entity-layer assets live in ``unit_test/entities/``. The pattern follows the +standard ``unittest.TestCase`` structure used throughout the repository: + +- ``setUp`` constructs the asset with representative parameter values. +- Individual test methods verify one behavior each, using the ``Arrange / Act / Assert`` + sequence. +- Solver interactions are replaced with ``unittest.mock.patch`` or ``Mock`` objects so the + entity layer can be tested independently of the solver. + +A concrete example is ``unit_test/entities/test_pipe.py``: + +.. code-block:: python + + class PipeTest(unittest.TestCase): + def setUp(self) -> None: + self.pipe = Pipe( + asset_name="pipe", + asset_id="pipe_id", + port_ids=["test1", "test2"], + length=5, + inner_diameter=1, + roughness=0.001, + alpha_value=0.8, + minor_loss_coefficient=0.0, + external_temperature=293.15, + qheat_external=0.0, + ) + + def test_pipe_create(self) -> None: + # Act and Assert + pipe = Pipe(...) + self.assertIsInstance(pipe, Pipe) + +When adding a new asset: + +- Create ``unit_test/entities/test_.py`` mirroring the structure of + ``unit_test/entities/test_pipe.py`` or the closest existing asset test. +- Test construction with valid parameters and any required defaults. +- Test that output properties return expected types or raise appropriate errors when the + asset has not yet been solved. +- Test any asset-specific logic such as clamping, bypass conditions, or state transitions. + +Solver-layer asset tests live in ``unit_test/solver/network/assets/``. Each file targets one +solver asset class (for example ``test_solver_pipe.py``, ``test_production_asset.py``). These +tests verify that ``get_equations()`` returns the expected matrix contributions for given inputs, +without running the full nonlinear solver. + +Controller unit tests +~~~~~~~~~~~~~~~~~~~~~ + +Controller tests live in ``unit_test/entities/controller/``. See +``unit_test/entities/controller/test_controller_new_class.py`` for a worked example that +exercises ``NetworkController`` with mock ``ControllerNetwork`` instances. Use +``Mock(spec=)`` to constrain mocks to the real interface. + +When adding a new controller class: + +- Create ``unit_test/entities/controller/test_controller_.py``. +- Use ``Mock(spec=ControllerNetwork)`` for the network argument. +- Call ``update_setpoints`` and assert that the returned dict contains the expected keys and + value types. +- Test edge cases such as zero demand, empty subnetworks, or profile boundaries. + +Adapter tests +~~~~~~~~~~~~~ + +Mapper tests live in ``unit_test/adapters/``. The main file is +``unit_test/adapters/test_esdl_graph_mapper.py``. Mapper tests verify that a known ESDL +structure (supplied inline or from a small fixture) maps to the expected internal graph +topology. Use real ESDL objects rather than mocks where construction is straightforward; use +mocks only for external dependencies such as file loaders. + +Integration Test Patterns +------------------------- + +Integration tests live in ``unit_test/integration/``. Each file runs a complete simulation +through ``SimulationManager`` using a real ESDL file from ``testdata/``, then asserts on +output values such as supply temperatures, mass flow rates, pressures, or heat transfer +quantities. + +When to add an integration test: + +- A new asset or controller class introduces cross-component coupling that unit tests cannot + exercise in isolation (for example, a new asset type that affects network-level pressure + balance). +- A bug fix addresses emergent behavior that only manifests across multiple layers (entity, + solver, controller). +- A new ESDL configuration produces a topology that no existing integration test covers. + +The general pattern (taken from ``unit_test/integration/test_heat_physics.py``) is: + +.. code-block:: python + + class HeatDemandTest(unittest.TestCase): + def setUp(self) -> None: + esdl_file_path = str( + Path(__file__).parent / ".." / ".." / "testdata" / "test1.esdl" + ) + esdl_object = EsdlObject(pyesdl_from_file(esdl_file_path)) + self.controller = EsdlControllerMapper().to_entity(esdl_object) + config = SimulationConfiguration( + simulation_id=uuid.uuid1(), + name="test run", + timestep=3600, + ... + ) + manager = SimulationManager(esdl_object, self.controller, config) + self.output = manager.execute() + + def test_supply_temperature(self) -> None: + # Assert on self.output values + +Integration tests are slower than unit tests because they run the full solver loop. Keep +individual integration test files focused on one ESDL topology. Add a new ESDL file to +``testdata/`` if no existing file exercises the required network configuration. + +Testing Checklist +----------------- + +Before submitting a change, verify the following: + +- All existing tests pass: ``python -m pytest unit_test/`` +- A unit test exists for every new entity-layer asset class. +- A unit test exists for every new solver-layer asset class. +- A unit test exists for every new controller class or subclass. +- A unit test exists for every new mapper or transform. +- An integration test has been added if the change introduces cross-component coupling. +- No test imports from a private module interface (i.e., ``_private_method``). +- Mocks use ``Mock(spec=)`` to prevent silent attribute errors. +- New ESDL test fixtures are placed in ``testdata/`` with a descriptive name. +- The documentation build passes: ``python -m sphinx -b html doc doc/_build/html``. + +Related Documentation +--------------------- + +- :doc:`simulation_contributor_flow` — traces the full orchestration path from entrypoint to + solver and identifies which tests correspond to each orchestration layer. +- :doc:`add_new_asset` — step-by-step workflow for adding a new asset; includes test file + placement and what to test at each implementation step. +- :doc:`control_extension` — contributor guide for adding or modifying controller classes, + including the corresponding test patterns for controller unit tests. diff --git a/doc/developer/writing_documentation_with_ai.rst b/doc/developer/writing_documentation_with_ai.rst new file mode 100644 index 00000000..8d6481fe --- /dev/null +++ b/doc/developer/writing_documentation_with_ai.rst @@ -0,0 +1,260 @@ +Writing Documentation with AI Agents +===================================== + +Purpose +------- + +This guide explains how contributors use the SIMULATOR-CORE AI agent workflow to write, +review, and validate documentation. It is written for anyone who needs to add or modify +documentation in this project and wants to understand which agents exist, what each one +does, how to invoke them, and how to validate the result. + +Use this guide instead of the conceptual documentation or the API reference when your goal +is to write documentation itself — new pages, corrections to existing pages, or navigation +updates. + +Relevant Agent Files +-------------------- + +All agent definitions live under ``.github/agents/`` in the repository root. The shared +cross-cutting rules used by all agents are in +``.github/instructions/documentation-architecture.instructions.md``. + +.. list-table:: + :header-rows: 1 + :widths: 30 35 35 + + * - Agent file + - Role + - When to use + * - ``DocumentationCoordinator.agent.md`` + - Entry point for all documentation tasks. Classifies requests, delegates to specialist + agents, enforces the fixed top-level section order, and ensures navigation consistency. + - Start here for any documentation task that spans multiple pages, sections, or agent + types, or when you are unsure which specialist agent to use. + * - ``PhysicsAssetDocAgent.agent.md`` + - Writes end-user physics asset pages under ``doc/physics``. Documents what an asset + represents, its inputs, control signals, outputs, and governing physical relations. + - Adding or updating a page under ``doc/physics`` for a thermal asset such as a heat + pump, consumer, producer, ATES cluster, or heat exchanger. + * - ``SystemConceptDocAgent.agent.md`` + - Writes conceptual narrative pages for the Intro, Solver, Network, and user-facing + Control sections. + - Adding or updating a conceptual page in ``doc/intro``, ``doc/solver``, + ``doc/network``, or ``doc/controller`` that explains system behavior rather than + implementation details. + * - ``SolverBehaviorDocAgent.agent.md`` + - Writes detailed solver-behavior documentation in ``doc/solver``, explaining what the + solver assembles and solves each timestep and the physical impact of that solve. + - Adding or updating ``doc/solver/solver_behavior.rst`` or similar solver-depth pages. + * - ``ControllerBehaviorDocAgent.agent.md`` + - Writes detailed controller-behavior documentation in ``doc/controller``, explaining + what the network controller decides each timestep and how those decisions affect the + solved physical model. + - Adding or updating controller dispatch or per-component behavior pages under + ``doc/controller``. + * - ``DeveloperGuideAgent.agent.md`` + - Writes contributor-facing developer guide pages under ``doc/developer``. Documents + code layout, execution flow, extension workflows, and testing guidance for + contributors. + - Adding or updating pages in ``doc/developer`` that explain how to extend, test, or + navigate the codebase. + * - ``APIReferenceAgent.agent.md`` + - Maintains the autogenerated API reference under ``doc/developer/api``. Manages + autodoc and apidoc integration. Does not write narrative documentation. + - Adjusting API reference page structure, toctrees, or the apidoc integration. Do not + use for narrative or conceptual content. + * - ``NavigationAgent.agent.md`` + - Creates and maintains toctrees, section landing pages, and cross-links. Maintains the + mandatory top-level section order. + - Adding a page to the toctree, updating a landing page summary, or correcting broken + navigation structure. + * - ``SupportDocAgent.agent.md`` + - Writes concise support pages under ``doc/support``. Documents where to get help, how + to report issues, and what information to include. + - Adding or updating pages in ``doc/support``. + * - ``DocReviewAgent.agent.md`` + - Reviews documentation for audience fit, scope correctness, duplication, completeness, + and cross-link quality. Does not rewrite pages from scratch. + - After authoring a page, use this agent to check audience fit, scope drift, and + structural consistency before a build check. + * - ``SphinxValidationAgent.agent.md`` + - Validates the documentation build: toctree integrity, autodoc resolution, and the + absence of Sphinx warnings and errors. Delegates reStructuredText syntax checks to + ``RstSyntaxAgent`` and routes content fixes to the correct specialist agent. + - After any documentation change, use this agent to confirm the build is clean. Use it + when the build produces warnings or errors you need diagnosed. RST syntax issues are + routed to ``RstSyntaxAgent`` automatically. + * - ``RstSyntaxAgent.agent.md`` + - Reviews and validates reStructuredText syntax and formatting: headings, lists, links, + code blocks, directives, tables, and equations. + - When a specific file has syntax or formatting issues that do not require a full content + review. + +Documentation Workflow +----------------------- + +The following steps describe the typical workflow for adding a new documentation page using +the agent system. + +1. **Identify the documentation type.** Decide which section the new page belongs to based + on the fixed top-level section order: + + 1. Introduction + 2. Solver + 3. Network + 4. Physics + 5. Control + 6. Developer Documentation + 7. Support + + Each section has a corresponding specialist agent. If you are unsure, invoke the + ``DocumentationCoordinator`` and describe your goal. + +2. **Invoke the DocumentationCoordinator** (optional but recommended for multi-page or + cross-section tasks). Provide the documentation goal, the target section or file, and any + scope constraints. The coordinator classifies the task, selects the correct specialist + agent, and defines the expected output. + +3. **Invoke the appropriate specialist agent.** For a single page, you may invoke the + specialist agent directly: + + - Physics asset page: ``PhysicsAssetDocAgent`` + - Intro/Solver/Network/Control concept page: ``SystemConceptDocAgent`` + - Solver behavior detail page: ``SolverBehaviorDocAgent`` + - Controller behavior detail page: ``ControllerBehaviorDocAgent`` + - Developer guide page: ``DeveloperGuideAgent`` + - API reference: ``APIReferenceAgent`` + - Support page: ``SupportDocAgent`` + + Provide the agent with: the page goal, page title, target file path, and scope constraints. + +4. **Update navigation.** After the page is authored, ensure it is reachable through exactly + one ``.. toctree::`` entry. Invoke ``NavigationAgent`` if the toctree update is + non-trivial or spans multiple landing pages. For simple additions (such as adding a single + page to ``developer_main.rst`` and ``developer_navigation.rst``), the edit can be made + directly. + +5. **Review the authored page.** Invoke ``DocReviewAgent`` to check audience fit, scope + correctness, duplication, and cross-link quality. Apply any corrections the review + identifies. + +6. **Validate the build.** Invoke ``SphinxValidationAgent`` or run the build command + directly (see `Testing and Validation`_). If the build produces warnings or errors, + ``SphinxValidationAgent`` can diagnose them and route fixes to the correct specialist + agent. + +7. **Fix syntax issues.** ``SphinxValidationAgent`` routes reStructuredText syntax + problems to ``RstSyntaxAgent`` automatically when it detects them during a build + validation pass. To run a targeted syntax check on a specific file before a full + build — for example after writing a new page — invoke ``RstSyntaxAgent`` directly + on that file. + +Implementation Notes +-------------------- + +**Single toctree path rule.** +Every page must be reachable through exactly one ``.. toctree::`` path. Linking the same +page from two toctrees creates duplicate navigation entries. When adding a new page, check +that it is added to at most one toctree. Use ``:doc:`` prose links to cross-reference a page +from a second location without creating a second toctree entry. + +**Specialist agents do not replace each other.** +Each specialist agent is scoped to its own documentation type. The ``DeveloperGuideAgent`` +writes contributor-facing implementation guides; ``SystemConceptDocAgent`` writes end-user +conceptual pages; ``PhysicsAssetDocAgent`` writes asset physics pages. Invoking the wrong +agent produces a page with the wrong audience, tone, and scope. Use the +``DocumentationCoordinator`` when the correct agent is not obvious. + +**Generated API reference is not hand-edited.** +The pages under ``doc/developer/api/`` are generated by the ``run_apidoc()`` hook in +``doc/conf.py``. Do not edit these files by hand and do not add them to toctrees other than +the one already managed by ``APIReferenceAgent``. Use ``APIReferenceAgent`` only for +structural API reference changes, not for narrative developer documentation. + +**Documentation architecture instructions apply to all agents.** +The file ``.github/instructions/documentation-architecture.instructions.md`` contains the +fixed top-level section order, equation notation rules, single toctree path rule, and the +build-validation command. Every agent loads these shared rules. When you see a deviation from +the expected structure, the instructions file is the canonical source. + +**Coordinator handoff sequence.** +``DocumentationCoordinator`` defines two built-in handoffs that apply after any specialist +author completes a page: + +- ``DocReviewAgent`` — audience/scope/duplication review, +- ``SphinxValidationAgent`` — documentation build validation. + +When using the coordinator for a multi-page task, these handoffs are triggered automatically. +For single-page tasks handled directly through a specialist agent, trigger the review and +validation steps manually. + +Testing and Validation +----------------------- + +After authoring or editing any documentation page, validate the build from the repository +root using the following command: + +.. code-block:: console + + python -m sphinx -b html doc doc/_build/html + +A clean build produces no warnings or errors. If the build reports warnings, read the output +carefully: most warnings identify the file and line number of the problem. + +For targeted syntax checks before running the full build, invoke ``RstSyntaxAgent`` on the +specific file. ``RstSyntaxAgent`` checks heading underline consistency, list formatting, +directive indentation, table syntax, and cross-reference formatting. + +For toctree and autodoc issues, invoke ``SphinxValidationAgent``. It runs the build command, +parses the output, delegates reStructuredText syntax fixes to ``RstSyntaxAgent``, and routes +other content-level fixes to the correct specialist agent. + +Common documentation validation checks: + +- Verify reStructuredText syntax and formatting via ``RstSyntaxAgent`` (or check headings, + lists, code blocks, directives, and tables manually if the agent is unavailable). +- All new pages appear in exactly one ``.. toctree::``. +- All ``:doc:`` and ``:ref:`` cross-references resolve without warnings. +- All ``.. list-table::`` directives have consistent column widths and correct indentation. +- The heading hierarchy within each file is consistent (no skipped heading levels). +- No hand-edited files exist under ``doc/developer/api/``. + +Common Pitfalls +--------------- + +- **Using the wrong specialist agent.** Physics asset pages, conceptual control pages, + controller behavior pages, and developer guides each require a different agent. Using + ``DeveloperGuideAgent`` for an asset physics page produces implementation-focused + documentation where end-user-focused documentation is expected. +- **Adding a page to two toctrees.** Violates the single toctree path rule and creates + duplicate navigation entries. Use ``:doc:`` prose links for cross-references instead of + adding a second toctree entry. +- **Hand-editing generated API reference files.** Files under ``doc/developer/api/`` are + regenerated on every build. Manual edits are overwritten silently. +- **Skipping the DocReviewAgent step.** New pages frequently drift in audience or scope + without a review pass. A page written for contributors may inadvertently contain + end-user-only material, or vice versa. +- **Not running the build before submitting.** Sphinx builds catch broken references, + missing toctree entries, and directive errors that are not visible from the file content + alone. Always run the build after any documentation change. +- **Omitting required sections.** Each specialist agent defines a required section order for + its documentation type. Omitting required sections (for example, omitting ``Common + Pitfalls`` from a developer guide or ``Assumptions`` from a physics page) reduces + consistency with the rest of the documentation set. +- **Invoking the DocumentationCoordinator for a single simple edit.** The coordinator is + optimized for multi-agent, multi-page tasks. For a small targeted fix to an existing page, + invoke the owning specialist agent directly. + +Related Documentation +--------------------- + +- :doc:`developer_navigation` — start here for a quick map of all developer guides. +- :doc:`simulation_contributor_flow` — code layout, package structure, and execution flow + for contributors making code changes. +- :doc:`testing` — how to run the test suite and validate code changes alongside + documentation changes. +- :doc:`../support/support` — where to ask questions and report issues. +- The ``.github/agents/`` directory and + ``.github/instructions/documentation-architecture.instructions.md`` in the repository root + are the canonical sources for agent definitions and shared documentation rules. diff --git a/doc/reference/architecture_reference.rst b/doc/reference/architecture_reference.rst deleted file mode 100644 index 947bc668..00000000 --- a/doc/reference/architecture_reference.rst +++ /dev/null @@ -1,19 +0,0 @@ -Architecture Reference -====================== - -Curated technical reference for orchestration flow, configuration, and asset -construction structure. - -Use this section when package-based API navigation is less helpful than a -workflow-oriented view of how simulator setup and execution fit together. - -.. toctree:: - :maxdepth: 1 - - ../architecture/architecture - ../architecture/configuration - ../architecture/esdl_asset_object - ../architecture/esdl_object - ../architecture/simulation_manager - ../architecture/network_simulation - ../architecture/asset_factories diff --git a/doc/reference/asset_reference.rst b/doc/reference/asset_reference.rst deleted file mode 100644 index 4a38a24d..00000000 --- a/doc/reference/asset_reference.rst +++ /dev/null @@ -1,32 +0,0 @@ -Asset Reference -=============== - -Purpose -------- - -This landing page contains the main curated set of entity-level asset reference -pages used throughout simulation and control documentation. - -Supporting asset entities that are not part of this main set are collected -separately in :doc:`asset_uncovered_entities`. - -Behavioral interpretation of these entities belongs in the Physics section; see -:doc:`../physics/physics_main` for the governing relations and asset behavior -pages. - -Contents --------- - -.. toctree:: - :maxdepth: 1 - - ../assets/producer_asset - ../assets/consumer_asset - ../assets/pipe_asset - ../assets/heat_pump_asset - ../assets/heat_exchanger_asset - ../assets/ideal_heat_storage_asset - ../assets/junction_asset - ../assets/air_to_water_heat_pump_asset - ../assets/ates_asset - ./asset_uncovered_entities diff --git a/doc/reference/asset_uncovered_entities.rst b/doc/reference/asset_uncovered_entities.rst deleted file mode 100644 index 5a8ff5cc..00000000 --- a/doc/reference/asset_uncovered_entities.rst +++ /dev/null @@ -1,26 +0,0 @@ -Asset Reference: Supporting Entities -==================================== - -Purpose -------- - -This landing page contains supporting asset-related reference pages that are -not covered in the main curated entity-level asset set in -:doc:`asset_reference`. - -These pages complement the main asset taxonomy without duplicating it. - -For physical behavior and model interpretation, use the Physics section; -start from :doc:`../physics/physics_main`. - -Contents --------- - -.. toctree:: - :maxdepth: 1 - - ../assets/asset_abstract_asset - ../assets/asset_defaults_asset - ../assets/esdl_asset_object_asset - ../assets/asset_utils_asset - ../assets/pyjnius_loader_asset diff --git a/doc/reference/controller_reference.rst b/doc/reference/controller_reference.rst deleted file mode 100644 index f78adcf8..00000000 --- a/doc/reference/controller_reference.rst +++ /dev/null @@ -1,25 +0,0 @@ -Controller Reference -==================== - -Curated technical reference for controller classes, sub-network coordination, -and asset-specific controller components. - -Use this section for implementation-oriented controller pages that complement -the conceptual Control section rather than duplicate its user-facing behavior -overview. - -The main curated path covers the network controller, subnetwork coordination, -and primary asset controller types. Additional controller components, including -heat-transfer and storage controllers, remain grouped under -:doc:`controller_uncovered_entities` so they stay discoverable through -Developer Documentation without duplicating the conceptual Control navigation. - -.. toctree:: - :maxdepth: 1 - - ../controller/main_controller_class - ../controller/sub_network_class - ../controller/assets/producer - ../controller/assets/consumer - ../controller/assets/ates - ./controller_uncovered_entities diff --git a/doc/reference/controller_uncovered_entities.rst b/doc/reference/controller_uncovered_entities.rst deleted file mode 100644 index 6330a4e1..00000000 --- a/doc/reference/controller_uncovered_entities.rst +++ /dev/null @@ -1,25 +0,0 @@ -Controller Reference: Supporting Entities -========================================== - -Purpose -------- - -This landing page contains supporting controller-related reference pages that -are not covered in the main curated controller set in -:doc:`controller_reference`. - -These pages complement the main controller taxonomy without duplicating it. -Use this group for additional controller components such as heat-transfer and -storage controllers, shared controller abstractions, and supporting helpers. - -Contents --------- - -.. toctree:: - :maxdepth: 1 - - ../controller/assets/controller_network - ../controller/assets/controller_heat_transfer - ../controller/assets/controller_storage - ../controller/assets/asset_controller_abstract - ../controller/assets/profile_interpolation diff --git a/doc/reference/solver_reference.rst b/doc/reference/solver_reference.rst deleted file mode 100644 index 8560ed67..00000000 --- a/doc/reference/solver_reference.rst +++ /dev/null @@ -1,19 +0,0 @@ -Solver Reference -================ - -Curated technical reference for internal solver entities, matrix assembly, -network structure, and solver-side asset behavior. - -Use this section for implementation-oriented solver details that complement the -conceptual Solver section without replacing it. - -.. toctree:: - :maxdepth: 1 - - ../solver/solver - ../solver/matrix - ../solver/equation_object - ../solver/network - ../solver/solver_utility - ../solver/asset_main - ./solver_uncovered_entities diff --git a/doc/reference/solver_uncovered_entities.rst b/doc/reference/solver_uncovered_entities.rst deleted file mode 100644 index 636c021a..00000000 --- a/doc/reference/solver_uncovered_entities.rst +++ /dev/null @@ -1,23 +0,0 @@ -Solver Reference: Supporting Entities -====================================== - -Purpose -------- - -This landing page contains supporting solver-related reference pages that are -not covered in the main curated solver set in :doc:`solver_reference`. - -These pages complement the main solver taxonomy without duplicating it. - -Contents --------- - -.. toctree:: - :maxdepth: 1 - - ../solver/assets/solver_boundary - ../solver/assets/solver_buffer_asset - ../solver/assets/solver_heat_transfer_asset - ../solver/assets/solver_production_asset - ../solver/assets/base_node_item - ../solver/assets/solver_air_to_water_heat_pump_asset