Adding a new problem#
Note: Read our contribution guide before diving into the code!
Install#
To install EngiBench for development, clone the repo, install the pre-commit hooks, and install all dev dependencies:
git clone git@github.com:IDEALLab/EngiBench.git
cd EngiBench
pre-commit install
pip install -e ".[dev]"
Also worth installing ruff and mypy in your editor as we are checking the code style and type safety on our CI.
Code#
In general, follow the beams2d/ example.
Create a new problem module in engibench/problems/ following the following layout (e.g. engibench/problems/beams2d/), where you later also can add other versions / variant of the problem:
📦 engibench └─ 📂 problems └─ 📂 new_problem ├── 📄 __init__.py └── 📄 v0.py__init__.py"""NewProblem problem module.""" from engibench.problems.new_problem.v0 import NewProblem __all__ = ["NewProblem"]
The
v0module already proactively introduces versioning.Ideally, all non-breaking changes should not create a new versioned module. Also in many cases, code duplication can be avoided, by introducing a new parameter to the problem class.
Define your problem class that implements the
Probleminterface with its functions and attributes inproblems/new_problem/v0.py(e.g. beams2d/v0.py).problems/new_problem/v0.pyfrom engibench.core import Problem class NewProblem(Problem[...]) # <- insert type for DesignType here ... # define your problem here
You can consult the documentation for info about the API; see below for how to build the website locally.
Run
pytest tests/test_problem_implementations.py(requirespip install ".[test]") to verify that the newProblemclass defines all required metadata attributes.Complete your docstring (Python documentation) thoroughly, LLMs + coding IDE will greatly help.
Documentation#
Install necessary documentation tools:
pip install ".[doc]".If it is a new problem family, add a new
.mdfile in docs/problems/ following the existing structure and add your problem family in thetoctreeof docs/problems/index.md.Add a problem markdown file to the
toctreeindocs/problems/new_problem.md. In the md file, use EngiBench’s ownproblem:tableandproblem:conditionsdirectives in the docs of your new problem:# Your Problem ``` {problem:table} :lead: Chuck Norris @chucknorris ``` ... ## Conditions ``` {problem:conditions} ``` ...
problem:table: This directive extracts metadata from a problem and inserts a table filled with the metadata. By default, the directive will try to import the problemengibench.problems.<problem_id>, where<problem_id>is the filename (without.mdextension) of the markdown file the directive is used.Options (optional):
:problem_id:override<problem_id>,:lead:Add a row “Lead” to the table, containing the specified value. If the value ends with@username, a link tohttps://github.com/usernamewill be inserted.
problem:conditions: This directive lists the conditions extracted from a problem as in the “Conditions” row produced by theproblem:tabledirective. The<problem_id>is determined the same way as inproblem:table.Options:
:problem_id:override<problem_id>,:defaults:include default values in the list of conditions
Here,
new_problem/__init__.pyis crucial as it makes the problem class discoverable to theproblemdirective by the reexportfrom engibench.problems.new_problem.v0 import NewProblem.Add an image (result of
problem.render(design)) indocs/_static/img/problems. The file’s name should be<new_problem>.png, with your problem module as in the point above.cd docs/Run
sphinx-autobuild -b dirhtml --watch ../engibench --re-ignore "pickle$" . _buildGo to http://127.0.0.1:8000/ and check if everything is fine.
Congrats! You can commit your changes and open a PR.