diff --git a/docs/README.md b/docs/README.md index 3f84a516..3cfd1b72 100644 --- a/docs/README.md +++ b/docs/README.md @@ -74,7 +74,7 @@ You can then open http://localhost:8000 in your browser to watch a live updated ## Writing Tutorials -We use Sphinx-Gallery to build the tutorials inside the `docs/tutorials` directory. Check `docs/tutorials/demo.py` to see an example of a tutorial and [Sphinx-Gallery documentation](https://sphinx-gallery.github.io/stable/syntax.html) for more information. +We use Sphinx-Gallery to build the tutorials inside the `docs/tutorials` directory. Check [Sphinx-Gallery documentation](https://sphinx-gallery.github.io/stable/syntax.html) for more information. To convert Jupyter Notebooks to the python tutorials you can use [this script](https://gist.github.com/mgoulao/f07f5f79f6cd9a721db8a34bba0a19a7). diff --git a/docs/tutorials/new_problem.md b/docs/development/new_problem.md similarity index 100% rename from docs/tutorials/new_problem.md rename to docs/development/new_problem.md diff --git a/docs/development/problem_constraints.md b/docs/development/problem_constraints.md new file mode 100644 index 00000000..490de948 --- /dev/null +++ b/docs/development/problem_constraints.md @@ -0,0 +1,97 @@ +# Problem constraints + +The [`Problem`](#engibench.core.Problem) class provides a [`check_constraints`](#engibench.core.Problem.check_constraints) method to validate input parameters. + +So that it works, problems have to declare the constraints for their parameters in their `Conditions` class member (which itself is a [dataclass](https://docs.python.org/3/library/dataclasses.html)). + +Constraints can have the following categories: + +```{eval-rst} +.. autodata:: engibench.constraint.THEORY +``` + +```{eval-rst} +.. autodata:: engibench.constraint.IMPL +``` + + +A constraint can have more than one category. The `|` operator can be used to combine categories. + +On top of categories, constraints have a criticality level ([`Error`](engibench.constraint.Criticality.Error) by default) + +```{eval-rst} +.. autoclass:: engibench.constraint.Criticality + :members: + :undoc-members: +``` + +There are 2 ways to declare a constraint: + +## Simple constraint, only constraining a single parameter + +Use [typing.Annotated](https://docs.python.org/3/library/typing.html#typing.Annotated), +where the annotation is one or multiple [`Constraint`](#engibench.constraint.Constraint) objects. + +Predefined constraints are: + +```{eval-rst} +.. automethod:: engibench.constraint.bounded +``` + +```{eval-rst} +.. automethod:: engibench.constraint.less_than +``` + +```{eval-rst} +.. automethod:: engibench.constraint.greater_than +``` + +Example: +```py + @dataclass + class Conditions: + """Conditions.""" + + volfrac: Annotated[ + float, + bounded(lower=0.0, upper=1.0).category(THEORY), + bounded(lower=0.1, upper=0.9).warning().category(IMPL), + ] = 0.35 +``` + +Here, we declare a [`THEORY`](engibench.constraint.THEORY)/[`Error`](engibench.constraint.Criticality.Error) constraint and a [`IMPL`](engibench.constraint.IMPL)/[`Warning`](engibench.constraint.Criticality.Warning) constraint for the `volfrac` parameter. + +## Constraint which also may affect more than one parameter +Add a static method, decorated with the [`@constraint`](#engibench.constraint.constraint) decorator. + +Example: +```py + @dataclass + class Config(Conditions): + """Structured representation of conditions.""" + + rmin: float = 2.0 + nelx: int = 100 + nely: int = 50 + + @constraint + @staticmethod + def rmin_bound(rmin: float, nelx: int, nely: int) -> None: + """Constraint for rmin ∈ (0.0, max{ nelx, nely }].""" + assert 0 < rmin <= max(nelx, nely), f"Params.rmin: {rmin} ∉ (0, max(nelx, nely)]" +``` + +This declares a constraint for the 3 parameters (`rmin`, `nelx`, `nely`) with custom logic. This constraint does not have any category. +If we would want to add a category, `@constraint` could be replaced by `@constraint(category=ERROR)` for example. + +# API + +```{eval-rst} +.. autofunction:: engibench.constraint.constraint +``` + + +```{eval-rst} +.. autoclass:: engibench.constraint.Constraint + :members: +``` diff --git a/docs/index.md b/docs/index.md index 92507a97..0afdeb7f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -77,15 +77,9 @@ utils/index ```{toctree} :hidden: :glob: -:caption: Tutorials - -tutorials/* -``` - -```{toctree} -:hidden: :caption: Development Github Contribute to the Docs +development/* ``` diff --git a/engibench/constraint.py b/engibench/constraint.py index b2ecfad8..98552d1f 100644 --- a/engibench/constraint.py +++ b/engibench/constraint.py @@ -24,7 +24,11 @@ class Category(Flag): IMPL = Category.Implementation +"""Violating the constraint, will cause runtime errors / undefined behavior + due to the implementation.""" THEORY = Category.Theory +"""The constraint is not known to cause a runtime error, values outside of + the constraint domain are unphysical and might lead to unphysical domains.""" UNCATEGORIZED = Category(0)