Skip to content
Commits on Source (44)
......@@ -21,7 +21,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source $SCRIPT_DIR/util
TEST_SOURCEDIR=${SCRIPT_DIR}/../test
TUTORIAL_SOURCEDIR=${SCRIPT_DIR}/../doc
DOCS_SOURCEDIR=${SCRIPT_DIR}/../doc
print_opts_file() {
cat "${DUNE_OPTIONS_FILE}"
......@@ -74,9 +74,9 @@ eval cmake $RELEASE_CMAKE_FLAGS $TEST_SOURCEDIR
cmake --build . --target build_system_tests
ctest -j4 -L "system" --output-on-failure
echo $GREEN "============================ Tutorial Tests ============================" $RESET
echo $GREEN "============================ Documentation Tests ============================" $RESET
BUILD_PATH=/tmp/build-system-tutorials
BUILD_PATH=/tmp/build-docs-tests
[[ -d ${BUILD_PATH} ]] && ONFAILURE_MESSAGE+="the folder '${BUILD_PATH}' should not exist prior running this script\n" && exit 1
mkdir $BUILD_PATH && cd $BUILD_PATH
......@@ -84,10 +84,10 @@ if [[ -n "$DUNE_OPTIONS_FILE" ]]; then
RELEASE_CMAKE_FLAGS="$(. $DUNE_OPTIONS_FILE; eval echo \$CMAKE_FLAGS)"
fi
echo "cmake $RELEASE_CMAKE_FLAGS $TUTORIAL_SOURCEDIR"
eval cmake $RELEASE_CMAKE_FLAGS $TUTORIAL_SOURCEDIR
cmake --build . --target build_tutorial_tests
ctest -j4 -L "tutorial" --output-on-failure
echo "cmake $RELEASE_CMAKE_FLAGS $DOCS_SOURCEDIR"
eval cmake $RELEASE_CMAKE_FLAGS $DOCS_SOURCEDIR
cmake --build . --target build_docs_tests
ctest -j4 -L "docs" --output-on-failure
cd $SCRIPT_PATH
trap cleanup EXIT
test/data/** filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
doc/joss/cardiac_ep.png filter=lfs diff=lfs merge=lfs -text
......@@ -23,6 +23,7 @@ doc/docusaurus/build
# Generated files
doc/docusaurus/.docusaurus
doc/docusaurus/.cache-loader
doc/docusaurus/static/doxygen/
doc/docusaurus/npm-debug.log*
doc/docusaurus/yarn-debug.log*
......@@ -37,3 +38,7 @@ test/build/
# editor files
*.swo
*.swp
doc/joss/paper.jats
doc/joss/media/
......@@ -25,10 +25,10 @@ variables:
PACKAGE_REGISTRY: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/dune-copasi
MASTER_IMAGE: debian:bookworm
BASE_IMAGE_VERSION:
value: "v2.0.1-git"
value: "v2.0.2-git"
options:
- "v2.0.1-git" # Main dependecy base image
- "v2.0.1-git-tmp" # Temporary (one time testing)
- "v2.0.2-git" # Main dependecy base image
- "v2.0.2-git-tmp" # Temporary (one time testing)
description: "Key to tag images in the registry. Use '*-tmp' key to try out changes that need to rebild the dependencies image"
FORCE_REBUILD_BASE_IMAGE:
value: "false"
......@@ -187,7 +187,7 @@ codespell:
image: ${DEPENDENCIES_IMAGE}
script:
- codespell
--skip="./doc/docusaurus/yarn.lock,./.git/**/*"
--skip="./doc/docusaurus/yarn.lock,./.git/**/*,./doc/joss/paper.bib"
--ignore-words-list="warn"
config_format:
......@@ -294,7 +294,7 @@ deploy_wasm:debian_emscripten:
deploy:documentation:
image: ${DEPENDENCIES_IMAGE}
variables:
<<: *debian_emscripten
<<: *debian_base
GIT_STRATEGY: none
stage: deploy
script:
......@@ -308,3 +308,36 @@ deploy:documentation:
- !reference [.deploy_rules, rules]
- changes:
- doc/**/*
build:doxygen:
<<: *update_version
image: ${DEPENDENCIES_IMAGE}
variables:
<<: *debian_clang
stage: build
script:
- |
cd doc/doxygen
cmake -S . -B build
cmake --build build
cd build/html/
zip -r doxygen.zip ./*
rules:
- !reference [.build_rules, rules]
artifacts:
paths:
- doc/doxygen/build/html/doxygen.zip
deploy:doxygen:
image: ${DEPENDENCIES_IMAGE}
variables:
<<: *debian_clang
stage: deploy
script:
- |
VERSION=$(./util/version_handler.py --replace-prerelease="git")
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file doc/doxygen/build/html/doxygen.zip "${PACKAGE_REGISTRY}/${VERSION}/dune-copasi-doxygen.zip"
dependencies:
- build:doxygen
rules:
- !reference [.deploy_rules, rules]
......@@ -28,12 +28,30 @@ Types of changes
## [Unreleased] ([git-diff][Unreleased-diff])
### Added
- Add experimental support for moving domains !205
- Enable super builds for simpler installation instructions !230
- Numerical jacobians !204
### Changed
- Update ExprTk to 0.0.3 !237
- Improve documentation !210 !211 !212 !213 !214 !215 !216 !217 !218 !219 !220 !221 !222 !223 !224 !225 !226 !227 !228
### Fixed
- Wrong configuration of higher order polynomial degrees !236
- Memory leak on the UMFPack solver !235
- Outflow derivatives set its prefix incorrectly !229
- Improve muParser search with CMake !203 !232
## [2.0.1] ([git-diff][2.0.1-diff]) - 2024-04-22
### Fixed
* Fix memory errors on Blocked Jacobi !197
* Remove Muparser invalid assertions !196
- Fix memory errors on Blocked Jacobi !197
- Remove Muparser invalid assertions !196
## [2.0.0] ([git-diff][2.0.0-diff]) - 2024-03-26
......@@ -41,22 +59,22 @@ _**Note**: This version is a complete re-write of the library based on a custom
### Refactor
* Allows different parser backends: [muparser](https://beltoforion.de/en/muparser/), [exprtk](https://github.com/ArashPartow/exprtk), and [SymEngine](https://github.com/symengine/symengine) !83
* Adds constants, (lambda) function, and [random fields](https://github.com/parafields/parafields-core) definitions within the parsers !83
* Re-implementation of local operator: huge performance improvements !83
* Adds tensor cross-diffusion, storage, velocity, and external boundary terms !83
* Allows for volume coupling between compartments !83
* Splits the subdomain and the compartment concepts. Now compartments with no entities or no components are perfectly possible !83
* Uses new basis functions from dune-pdelab that allows native usage of multi-domains (branch: features/dune-assembler/main) !83
* Extends compatibility of tiff images to different bit sizes !83
* Adds monitoring (info, warning and error) of variables with new generic reduce operators !83
* Switches logging from dune-logging to [spdlog](https://github.com/gabime/spdlog) !83
* Designed to be thread-safe, although is not entirely yet implemented !83
* Adds tracing capabilities with [perfetto](https://perfetto.dev/) !83
* Allows Selection of between direct and sparse solvers, and matrix free operators !83
* Allows to print matrix layout in a SVG file !83
* Unifies the executable for different dimensions and different degrees of freedom layouts !83
* Improves command line interface !83
- Allows different parser backends: [muparser](https://beltoforion.de/en/muparser/), [exprtk](https://github.com/ArashPartow/exprtk), and [SymEngine](https://github.com/symengine/symengine) !83
- Adds constants, (lambda) function, and [random fields](https://github.com/parafields/parafields-core) definitions within the parsers !83
- Re-implementation of local operator: huge performance improvements !83
- Adds tensor cross-diffusion, storage, velocity, and external boundary terms !83
- Allows for volume coupling between compartments !83
- Splits the subdomain and the compartment concepts. Now compartments with no entities or no components are perfectly possible !83
- Uses new basis functions from dune-pdelab that allows native usage of multi-domains (branch: features/dune-assembler/main) !83
- Extends compatibility of tiff images to different bit sizes !83
- Adds monitoring (info, warning and error) of variables with new generic reduce operators !83
- Switches logging from dune-logging to [spdlog](https://github.com/gabime/spdlog) !83
- Designed to be thread-safe, although is not entirely yet implemented !83
- Adds tracing capabilities with [perfetto](https://perfetto.dev/) !83
- Allows Selection of between direct and sparse solvers, and matrix free operators !83
- Allows to print matrix layout in a SVG file !83
- Unifies the executable for different dimensions and different degrees of freedom layouts !83
- Improves command line interface !83
### Added
- Docusaurus now upgrades latest `canary` wasm binary automatically !186
......@@ -99,7 +117,7 @@ _**Note**: This version is a complete re-write of the library based on a custom
- Improve support for Wasm binaries !170 !182
- Move configuration options to a JSON file and use schema validator on it !174
- Use Debian Bookworm in the CI !171
- Conditinally test possion config if ExprTk is available !168
- Conditionally test possion config if ExprTk is available !168
- Use (faster) integer based multi-domain grid !165
- Simplify CMake usage !161 !162 !163
- Improve version handler !159
......@@ -137,7 +155,7 @@ _**Note**: This version is a complete re-write of the library based on a custom
- Compile final executable with different parsers !95
- CMake problems on target installation !94
- Support for {fmt} >= 9.0.0 !90 !91 !93 !129
- Docker image now uses `dune-copas` executable instead of `dune-copasi-[sd|md]` !91
- Docker image now uses `dune-copasi` executable instead of `dune-copasi-[sd|md]` !91
- CI jobs now passes since the re-write !89
- Solver on linear problems was wrongly reused !85
### Removed
......
......@@ -40,7 +40,7 @@ list(PREPEND CMAKE_MODULE_PATH \"\${dune-copasi_MODULE_PATH}\")
include(CMakeFindDependencyMacro)
")
foreach(module ${ALL_DEPENDENCIES})
foreach(module ${DUNE_FOUND_DEPENDENCIES})
if(${${module}_FOUND})
set(DUNE_CUSTOM_PKG_CONFIG_SECTION "${DUNE_CUSTOM_PKG_CONFIG_SECTION}
find_dependency(${module} REQUIRED)
......
# Contributing
When contributing to `dune-copasi`, first discuss the change you wish to make via the
When contributing to DuneCopasi, first discuss the change you wish to make via the
[issue tracker](https://gitlab.dune-project.org/copasi/dune-copasi/-/issues).
Try to do this before anything else. This will greately improve both your and
our experience working together :-). We follow the
......@@ -14,14 +14,14 @@ contributing single features can be summarized by following these steps:
proposal has a major change, create a *meta-task*, which should divide the
proposal in several tasks. Use a suitable issue template for your proposal.
2. In the created issue, discuss with others the whole idea of your proposal.
This is important because you may get input from someone that know the
software on how to do it effectively, and poimting out considerations you may
This is important because you may get input from someone who knows the
software on how to do it effectively, and pointing out considerations you may
have missed. It also synchronizes ideas so that changes are more easily
accepted.
3. **CODE**: Implement what you proposed :-) in a new branch.
4. Create a [Merge Request (MR)](https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html)
3. **CODE**: Implement what you proposed in a new branch :-)
4. Create a [Merge Request (MR)](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
using suitable template. Mark the MR as
[*Work In Progress* (WIP)](https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html)
[*Draft*](https://docs.gitlab.com/ee/user/project/merge_requests/drafts.html)
until is sent to review for approval. MR differ from issues in that MR
discuss *how* to implement the idea rather than the idea itself. A MR is
filled of technical details that ensure that the *task* idea is fulfilled.
......@@ -32,7 +32,7 @@ contributing single features can be summarized by following these steps:
6. If applicable, create a
[unit test](https://en.wikipedia.org/wiki/Unit_testing) that proves that your
implementation has the expected behavior. Ensure that the created test is
being run by the [Gitlab CI](https://docs.gitlab.com/ee/ci/pipelines.html).
being run by the [Gitlab CI](https://about.gitlab.com/blog/2020/12/10/basics-of-gitlab-ci-updated/).
7. **TEST**: Once implementation and test are finished, ensure that your MR is
passing the different [pipelines](https://gitlab.dune-project.org/copasi/dune-copasi/-/tree/master/.ci).
8. Update the [CHANGELOG](CHANGELOG.md) with changes to the interface. It
......
......@@ -2,21 +2,181 @@
[![Build Status](https://github.com/dune-copasi/dune-copasi/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/dune-copasi/dune-copasi/actions/workflows/ci.yml)
[![Netlify Status](https://api.netlify.com/api/v1/badges/6fc6d371-87df-49b5-8e72-e1873fa5d54b/deploy-status)](https://app.netlify.com/sites/dune-copasi/deploys)
# DuneCopasi
<!-- IMPORTANT: Do not add relative links on this file because this is rendered out of source at https://www.dune-project.org/modules/dune-copasi/ too -->
**WARNING**: This repository is in an ongoing refactor for version 2.0, check out the releases for stable versions!
---
# DuneCopasi: A Multi-Compartment Reaction-Diffusion Simulator
Solver for reaction-diffusion systems in multiple compartments
DuneCopasi is a C++ library providing a numerical simulator for systems of reaction-diffusion equations on single and multiple compartments using the **D**istributed and **U**nified **N**umerics **E**nvironment [DUNE](https://www.dune-project.org). It supports multi-threaded computations with continuous finite elements on unstructured grids in 1, 2, and 3 dimensions. An application program is made available as a Docker Image, as a Web Assembly binary, or as a GUI through the [Spatial Model Editor](https://spatial-model-editor.github.io) for the manipulation of spatial models of bio-chemical reactions.
* Solve a different reaction-diffusion system for each comartment
* Custom fluxes between compartments
* Easy to modify configuration file
* Initial conditions can be a TIFF file and/or math expressions
* Using the finite element/finite volume method
* Output in the VTK format
# Table of Contents
Get started [here](https://dune-copasi.netlify.app/docs//install_use).
- [DuneCopasi: A Multi-Compartment Reaction-Diffusion Simulator](#dunecopasi-a-multi-compartment-reaction-diffusion-simulator)
- [Table of Contents](#table-of-contents)
- [Overview](#overview)
- [Features](#features)
- [Capabilities](#capabilities)
- [Model Problem](#model-problem)
- [Getting Started](#getting-started)
- [Installation](#installation)
- [Basic Commands](#basic-commands)
- [Tutorials](#tutorials)
- [Configuration Options](#configuration-options)
- [Contributing](#contributing)
- [Reporting Issues](#reporting-issues)
- [Contributing Guide](#contributing-guide)
- [Folder Structure](#folder-structure)
- [Additional Information](#additional-information)
- [License](#license)
- [Acknowledgements](#acknowledgements)
---
# Overview
DuneCopasi bridges the gap between systems biology and scientific computing by providing a robust tool for simulating complex biochemical networks, especially those with spatial dependencies. It is particularly suitable for researchers and engineers in systems biology, computational biology, and related fields, offering capabilities that include advanced handling of multi-compartment reaction-diffusion systems.
## Features
- **Multi-Compartment Reaction-Diffusion Simulation**: Solve systems of PDEs across multiple compartments with configurable parameters.
- **Continuous Galerkin Method**: Utilize continuous finite elements on unstructured grids in 1D, 2D, and 3D.
- **Multi-Threaded Computation**: Efficient simulation on modern multi-core processors.
- **Interoperability**: Designed to work seamlessly with SBML, TIFF files for initial conditions, and systems biology workflows.
- **Flexible Deployment**: Available as a Docker image, WebAssembly binary, and as a GUI through the Spatial Model Editor.
## Capabilities
- **Configurable Executable**: Single executable with runtime configuration options.
- **SBML Compatibility**: Supports math parsers compatible with the Systems Biology Markup Language (SBML) for model specifications.
- **Custom Grid and TIFF Input**: Accepts custom grids and image files for initial conditions.
- **Advanced Boundary Conditions**: Flexible boundary/transmission conditions for complex biological models.
- **Cross-Diffusion Support**: Allows species to cross-diffuse across compartments.
- **Result Comparison**: Built-in tools for comparing simulation results with objective functions.
- **Random Field Generator**: Generates statistical spatial variations using embedded random field algorithms.
## Model Problem
DuneCopasi solves the following system of partial differential equations (PDEs):
$$
\begin{aligned}
\partial_t (\phi_{ik} u_{ik}) &= \nabla \cdot \vec{\mathcal{j}}_{ik}+\mathcal{R}_{ik}(\mathbf{u})\qquad &\text{in }\Omega_k\subset \mathbb{R}^d,\\
u_{ik} &= u^{(0)}_{ik} \qquad &\text{on }\Gamma_k^D\subseteq\partial\Omega_k,\\
\vec{\mathcal{j}}_{ik}\cdot \mathbf{n}_k &= \sum_{l\in T_k}\mathcal{T}_{ikl}(\mathbf{u}) \qquad &\text{on }\partial\Omega_k \setminus \Gamma^D_{k},\\
\vec{\mathcal{j}}_{ik} &:= \sum_{j\in N_k}\mathsf{D}_{ijk}\nabla u_{jk}\\
\end{aligned}
$$
where $i\in N_k$ is the subscript for each mass balance equation in the $k$-th compartment and with $k\in K$, $T_k:=\{l\in K : \Gamma_{kl}\neq\varnothing\}$, $\mathbf{u}_k:=(u_{1k},\ldots,u_{\text{dim}(N_k)k})$, $\mathbf{u} := (\mathbf{u}_1, \ldots, \mathbf{u}_{\text{dim}(K)})$, $\mathbf{n}_k$ the unit outer normal on $\Omega_k$, $\overline{\Omega}:=\bigcup_{k\in K}\overline{\Omega}_k$, and $\Gamma_{kl}$ is $\partial\Omega_k\cap\overline{\Omega}_l$ if $k \neq l$ or $\partial\Omega_k\cap\overline{\Omega}$ otherwise.
All of the parameterization for the equations are easily configurable at run-time using the command line or a configuration file. That is, the underlying grid, the partition for each sub-domain $\Omega_k$ on the grid, the reaction operator $\mathcal{R}_{ik}(\mathbf{u})$, the non-linear transmission conditions $\mathcal{T}_{ikl}(\mathbf{u})$ on $\Gamma_{kl}$, the Dirichlet boundary conditions $u^{(0)}_{ik}$ on $\Gamma^D_{k}$, the storage terms $\phi_{ik}$, and the cross-diffusion terms $\mathsf{D}_{ijk}$.
# Getting Started
## Installation
For detailed installation instructions specific to each version, please refer to our comprehensive [online documentation](https://dune-copasi.netlify.app).
## Basic Commands
```
USAGE: dune-copasi [options]
Numerical simulator for diffusion-reaction systems on single or multiple compartments
Website: <https://dune-copasi.netlify.app>
OPTIONS:
-h / --help - Display this help.
--help-full - Display this help with long descriptions.
--version - Display the version of this program.
--parser-default - Display the default parser.
--parser-list - Display the parsers available for this program.
--dimension-list - Display the grid dimensions available for this program.
--dump-config - Dumps configuration in the INI format to stdout.
--config=<string> - Specifies a config file in INI format. See Configuration Options.
--{key}={value} - Overrides key=value sections of the config file. See Configuration Options.
```
## Tutorials
To help you get started with DuneCopasi, we offer a dedicated [tutorial website](https://dune-copasi.netlify.app/tutorials) featuring step-by-step guides and practical examples. These tutorials are designed to walk you through various aspects of the software.
## Configuration Options
We have a rich set of options to configure many possible settings for our problem model.
You can find detailed information of each option by invoking the `--help-full` command or by exploring our [online documentation](https://dune-copasi.netlify.app).
# Contributing
## Reporting Issues
If you encounter any issues, please report them on the [issue tracker](https://gitlab.dune-project.org/copasi/dune-copasi/issues) or by contacting us via the email ![Service Desk](https://img.shields.io/badge/dune--copasi%40dune--project.org-informational).
## Contributing Guide
We welcome contributions from the community. Please read our Contributing Guide in `CONTRIBUTING.md` file for details on our code of conduct, and the process for submitting merge requests.
## Folder Structure
The following may help you understand the general structure of this project.
Below, you can find the folder structure with the most prominent parts of this repository and a short description of their purpose.
Notice that many of these sub-directories have their own `README.md` file explaining how to use its contents.
```
. # . Root directory
├── .ci # ├── Scripts to run during Continuous Integration (CI)
├── .github # ├── GitHub configuration files
├── .gitlab # ├── GitLab configuration files
├── cmake # ├── CMake scripts and modules
├── doc # ├── Documentation files
│ ├── docusaurus # │ ├── Files for online documentation
│ │ ├── docs # │ │ ├── Main online documentation files
│ │ │ ├── assets/ini # │ │ │ ├── Configuration examples for online documentation (tested)
│ │ │ └── assets/config_opts.json # │ │ │ └── Configuration options database (source of truth for all docs)
│ │ ├── tutorials # │ │ ├── Main online tutorial files
│ │ │ └── assets/ini # │ │ │ └── Configuration examples for online tutorials (tested)
│ │ └── ... # │ │ └── [...]
│ ├── doxygen # │ ├── Configuration files for autogenerated C++ documentation
│ ├── joss # │ ├── Paper submitted to the Journal of Open Source Software
│ └── man # │ └── Documentation for `man`
├── docker # ├── Docker files for different environments
├── dune/copasi # ├── C++ header files
│ ├── common # │ ├── Common infrastructure
│ ├── concepts # │ ├── Type constrains/requirements
│ ├── finite_element # │ ├── Finite element utilities
│ ├── grid # │ ├── Grids utilities
│ ├── model # │ ├── Simulation logic for a model problem
│ │ └── diffusion_reaction # │ │ └── Diffusion-Reaction specifics of the model problem
│ ├── parser # │ ├── Interface and implementation of math parsers
│ └── solver/istl # │ └── Custom linear algebra solvers/preconditioners for dune-istl
├── npm # ├── WebAssembly package files for NPM
├── src # ├── Object files and main program (mirrors dune/copasi folder)
├── test # ├── Testing suite
│ ├── data # │ ├── Custom data used for tests
│ ├── dune # │ ├── Unit tests on specific C++ constructs (mirrors dune/copasi folder)
│ └── *.ini # │ └── Configuration files for system tests
├── util # ├── Misc utilities to handle the repository
├── .gitlab-ci.yml # ├── GitLab CI configuration file
├── CHANGELOG.md # ├── List of major changes
├── CMakeFiles.txt # ├── Main CMake configuration file
├── CODE_OF_CONDUCT.md # ├── Code of conduct
├── CONTRIBUTING.md # ├── Contribution guilde
├── Dockerfile # ├── Main docker file to build the project
├── dune-copasi.opts # ├── DUNE options file with default CMake options
├── LICENSE.md # ├── BSD 2-Clause License file
├── README.md # ├── Overview documentation of repository
└── ... # └── [...]
```
# Additional Information
## License
This project is licensed under the BSD 2-Clause License - see the `LICENSE.md` file for details.
## Acknowledgements
Research funded by the German federal Ministry of Education and Research (BMBF) FKZ 031L0158
......@@ -38,14 +38,6 @@ if(muparser_FOUND
muparser_VERSION_STRING
"${muparser_version_str}")
unset(muparser_version_str)
add_library(
muparser::muparser
UNKNOWN
IMPORTED)
set_target_properties(
muparser::muparser
PROPERTIES IMPORTED_LOCATION ${muparser_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${muparser_INCLUDE_DIR})
set(muparser_test_path "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/muparser_test.cc")
set(muparser_test_source
......@@ -60,21 +52,42 @@ if(muparser_FOUND
file(WRITE "${muparser_test_path}" "${muparser_test_source}")
try_compile(COMPILE_RESULT_DYNAMIC "${CMAKE_CURRENT_BINARY_DIR}"
SOURCES "${muparser_test_path}"
LINK_LIBRARIES muparser::muparser)
CXX_STANDARD 17
LINK_LIBRARIES ${muparser_LIBRARY}
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${muparser_INCLUDE_DIR})
if(NOT COMPILE_RESULT_DYNAMIC)
if(COMPILE_RESULT_DYNAMIC)
add_library(
muparser::muparser
UNKNOWN
IMPORTED)
set_target_properties(
muparser::muparser
PROPERTIES IMPORTED_LOCATION ${muparser_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${muparser_INCLUDE_DIR})
else()
file(WRITE "${muparser_test_path}" "${muparser_test_source}")
try_compile(COMPILE_RESULT_STATIC "${CMAKE_CURRENT_BINARY_DIR}"
SOURCES "${muparser_test_path}"
COMPILE_DEFINITIONS -DMUPARSER_STATIC
LINK_LIBRARIES muparser::muparser)
CXX_STANDARD 17
LINK_LIBRARIES ${muparser_LIBRARY}
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${muparser_INCLUDE_DIR})
if(NOT COMPILE_RESULT_STATIC)
message(FATAL_ERROR "A simple muparser test program could not be successfully compiled")
endif()
# message(FATAL_ERROR "A simple muparser test program could not be successfully compiled")
set(muparser_FOUND OFF)
else()
set_target_properties(
muparser::muparser
PROPERTIES INTERFACE_COMPILE_DEFINITIONS MUPARSER_STATIC)
add_library(
muparser::muparser
UNKNOWN
IMPORTED)
set_target_properties(
muparser::muparser
PROPERTIES IMPORTED_LOCATION ${muparser_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${muparser_INCLUDE_DIR}
INTERFACE_COMPILE_DEFINITIONS MUPARSER_STATIC)
endif()
endif()
endif()
......@@ -21,25 +21,50 @@ if (TARGET Dune::Copasi::Executable)
enable_testing()
dune_declare_test_label(LABELS tutorial)
dune_declare_test_label(LABELS documentation)
file(COPY "docusaurus/tutorials/assets/ini" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tutorials/")
file(COPY "docusaurus/docs/assets/ini" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/docs/")
dune_add_test(
NAME tutorial_test
LABELS tutorial
NAME docs_test
LABELS docs
TARGET Dune::Copasi::Executable
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tutorials/ini/"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/ini/"
CMD_ARGS --config=test.ini)
dune_add_test(
NAME docs_heat
LABELS docs
TARGET Dune::Copasi::Executable
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/ini/"
CMD_ARGS --config=heat.ini)
dune_add_test(
NAME docs_volka_terra
LABELS docs
TARGET Dune::Copasi::Executable
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/ini/"
CMD_ARGS --config=volka_terra.ini)
dune_add_test(
NAME docs_grey_scott
LABELS docs
TARGET Dune::Copasi::Executable
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/ini/"
CMD_ARGS --config=grey_scott.ini
--model.time_step_operator.time_end=1.5)
file(COPY "docusaurus/tutorials/assets/ini" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tutorials/")
if(ExprTk IN_LIST DUNE_COPASI_PARSER_LIST)
dune_add_test(
NAME tutorial_EP_simulation1
LABELS tutorial
LABELS docs
TARGET Dune::Copasi::Executable
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tutorials/ini/"
CMD_ARGS --config=EP_simulation1.ini
--model.time_step_operator.time_end=10)
CMD_ARGS --config=cardiac_ep_1.ini
--model.time_step_operator.time_end=10
--grid.refinement_level=6)
endif()
endif()
......@@ -3,8 +3,12 @@ id: api
title: Application Programming Interface
description: Application Programming Interface
sidebar_label: API
tags:
- API
---
import DoxygenButton from '@site/src/components/DoxygenButton'
### Doxygen Documentation
The C++ classes are documented in the C++ source code and may be visualized with
......@@ -12,3 +16,5 @@ The C++ classes are documented in the C++ source code and may be visualized with
documentation, build [DuneCopasi from source](install_source) and use the
`make dune-copasi-doxygen` target in the build directory. For this, you need to
have `doxygen` on your system.
<DoxygenButton/>
......@@ -145,6 +145,45 @@
}
}
},
"model.jacobian.[type|epsilon]": {
".brief": "General options for the jacobian of the model",
".options": {
"type": {
".type": "enum",
".brief": "Evaluation type of the jacobian",
".default": "analytical",
".details": [
"This option specifies how to generate the assembled operator that is applied on linear systems.",
"If the type is 'analytical', each entry is constructed from the 'model.scalar_field.{var}.jacobian.{dvar}'",
"configuration options."
],
".options": {
"'analytical'": {
".brief": "Jacobians are computed from analyicial expressions provided within the configuration options",
".details": [
"In this case, the sparsity pattern is inferred from the 'model.scalar_field.{var}.jacobian.{dvar}'",
"configuration options and its value corresponds to the evaluation of these expressions."
]
},
"'numeric'": {
".brief": "Jacobians are computed numerically from the primary expressions provided within the configuration options",
".details": [
"In this case, the sparsity pattern is inferred from the 'model.scalar_field.{var}.jacobian.{dvar}'",
"configuration options and its value corresponds a forward euler evaluation of the",
"'model.scalar_field.{var}' expressions. Notice that the 'jacobian' configuration options may not be evaluated at all",
"(e.g. 'no_value' is a valid expression) but they still need to be present, otherwise, the pattern will not be created",
"correctly and the numerical evaluation will yield an invalid access error."
]
}
}
},
"epsilon": {
".type": "float",
".brief": "The discretization step to evaluate jacobians with a numerical type",
".default": "1e-7"
}
}
},
"model.assembly.[type|partition.type|partition.patches|partition.coloring]": {
".brief": "Options for the execution policy on the assembly of residuals and jacobians",
".options": {
......@@ -199,6 +238,25 @@
".brief": "Control data layout of the matrices and vectors. Note that this affects the allowed solvers",
".details": "To visualize the resulting layout of a matrix use the `model.time_step_operator.linear_solver.layout.writer.svg.path` option."
},
"model.domain.deformation.[x|y|z].[expression|parser_type]": {
".brief": "Expression options for the deformation of the domain (Experimental)`",
".details": [
"The domain deformation expressions may depend on any number of variables `{var}` from the 'scalar_field' section and only works when using numerical jacobians.",
"Depending on a variable `{var}` makes the problem non-linear and makes every `{var}` in 'scalar_field' depend on the variables `{var}` used here.",
"In practice, this means that the jacobian of every sub-section in `scalar_field.{var}` needs to also explicitly show the dependency on the variables used here.",
"The differential equations on the `scalar` section are posed on the deformed domain and conserved over time via the Reynolds Transport Theorem.",
"The latter means that the equations are in their conservative form."
],
".options": {
"expression": {
".type": "math-expr"
},
"parser_type": {
".type": "enum",
".default": "<see '--parser-default' option>"
}
}
},
"model.scalar_field.{var}.[reaction|storage|velocity.[x|y|z]|outflow.{cmp}].jacobian.{wrt}.[expression|parser_type]": {
".brief": "Expression options for the jacobian wrt variable `{wrt}` of the scalar field equation in variable `{var}`",
".options": {
......
#########################################################################
# GREY-SCOTT EQUATIONS:
#
# ∂ₜu = 2·D·∂ₓ∂ₓu + f·(1-u) - u·v²
# ∂ₜv = D·∂ₓ∂ₓu - (f+k)·v + u·v²
#
# See: https://groups.csail.mit.edu/mac/projects/amorphous/GrayScott/
#
#########################################################################
[grid]
extensions = 1 1
dimension = 2
refinement_level = 7
[parser_context.bump]
type = function
expression = x, y: 0.5*exp(-100*(x^2 + y^2))
parser_type = ExprTk
[parser_context.F]
type = constant
value = 0.0420
[parser_context.k]
type = constant
value = 0.0610
[parser_context.D]
type = constant
value = 1e-5
[model]
order = 1
parser_type = ExprTk
[model.time_step_operator]
time_begin = 0
time_end = 10000
time_step_initial = 0.1
time_step_max = 50
[model.time_step_operator.linear_solver]
type = RestartedGMRes
preconditioner.type = Jacobi
[model.time_step_operator.nonlinear_solver]
type = Alexander2
convergence_condition.relative_tolerance = 1.00000000000000002e-08
convergence_condition.absolute_tolerance = 0
[model.writer.vtk]
path = vtk
[compartments]
compartment.expression = 1
[model.scalar_field.U]
compartment = compartment
initial.expression = 0.7
storage.expression = 1
reaction.expression = F*(1-U) - U*V^2
reaction.jacobian.U.expression = -F - V^2
reaction.jacobian.V.expression = -2*U*V
cross_diffusion.U.expression = D*2
[model.scalar_field.V]
compartment = compartment
initial.expression = bump(0.25-position_x, 0.25-position_y) + bump(0.25-position_x, 0.75-position_y) + bump(0.75-position_x, 0.25-position_y) + bump(0.75-position_x, 0.75-position_y)
storage.expression = 1
reaction.expression = -(F+k)*V + U*V^2
reaction.jacobian.U.expression = V^2
reaction.jacobian.V.expression = -(F+k) + 2*U*V
cross_diffusion.V.expression = D
#########################################################################
# HEAT EQUATION:
#
# ∂ₜu = ∂ₓ(T·∂ₓu) + ∂ᵧ(T·∂ᵧu)
#
# where u(x,y,t) is the temperature at a time t on the domain for a
# thermal conductivity T.
#
# See: https://en.wikipedia.org/wiki/Heat_equation
#
#########################################################################
[grid]
# extensions of the grid in x and y directions
extensions = 1 0.1
# where the grid left-bottom corner starts
origin = 0.0 0.0
# number of cells of the initial grid in x and y directions
cells = 10 1
# number of times to refine the grid
refinement_level = 5
# defines a compartment with the name "domain"
[compartments.domain]
expression = 1
# Define a constant with name "T" to use in the equations
[parser_context.T]
type = constant
value = 0.005
# our model is linear because there is no reaction
[model]
is_linear = true
##### Definition of the equation to solve function u(x,y,t) ######
# Declares the compartment where this function is defined
[model.scalar_field.u]
compartment = domain
# Declares that the equation is transient
[model.scalar_field.u.storage]
expression = 1
# Declares the diffusion part on the diffusion-reaction equation
[model.scalar_field.u.cross_diffusion.u]
expression = T
[model.scalar_field.u.initial]
# Declares the value of the function at the initial time: u(x,y,0)
# Try changing this to be a function of x and y: use "position_x" and "position_y"
# to represents its values, for example:
# "expression = position_x^2"
# represents the case where u(x,y,0) := x^2
# ...
# function for u(x,y,0)
expression = 10
# Declares the diffusion part on the diffusion-reaction equation
# Here we use the following ExprTk syntax to constraint the left and right parts of
# the compartment: "condition ? if_true : if_false"
# the "if_true" part contains the values set on the left and right boundaries
[model.scalar_field.u.constrain.boundary]
expression = (position_x <= 0. or position_x >= 1.) ? 0. : no_value
parser_type = ExprTk
[model.time_step_operator]
# initial time of the simulation
time_begin = 0
# final time of the simulation
time_end = 10
......@@ -8,17 +8,10 @@ refinement_level = 5
type = expression
expression = 1
[parser_context]
diffusion.type = constant
diffusion.value = 0.005
gauss.type = function
gauss.expression = x, y, z: exp(-(x^2+y^2+z^2)/(4*diffusion)) / (4*3.14159265359*diffusion)
[model.scalar_field.u]
compartment = domain
cross_diffusion.u.expression = diffusion
initial.expression = gauss(position_x, position_y, position_z)
cross_diffusion.u.expression = 0.005
initial.expression = exp(-(position_x^2+position_y^2+position_z^2)/(4*0.005)) / (4*3.14159265359*0.005)
storage.expression = 1
[model.time_step_operator]
......
#########################################################################
# VOLKA-TERRA EQUATIONS:
#
# ∂ₜu = α·u - β·u·v
# ∂ₜv = δ·u·v - γ·v
#
# See: https://en.wikipedia.org/wiki/Lotka%E2%80%93Volterra_equations
#
# Note that there is not derivative on the positions x or y, so the
# functions are the same on every point in x and y for a given time t.
# Hence, we do not refine the grid at all.
#
#########################################################################
[grid]
# extensions of the grid in x and y directions
extensions = 1 1
# number of cells of the initial grid in x and y directions
cells = 1 1
# defines a compartment with the name "domain"
[compartments.domain]
expression = 1
# Define constants with name "alpha", "beta", "delta", and "gamma"
# representing α, β, δ, and γ respectively
[parser_context.alpha]
type = constant
value = 0.666666
[parser_context.beta]
type = constant
value = 1.33333
[parser_context.delta]
type = constant
value = 1
[parser_context.gamma]
type = constant
value = 1
# our model is linear because there is a non-linear reaction part
[model]
is_linear = false
##### Definition of the equation to solve function u(x,y,t) ######
# Declares the compartment where this function is defined
[model.scalar_field.u]
compartment = domain
# Declares that the equation is transient
[model.scalar_field.u.storage]
expression = 1
# Declares the reaction part on the diffusion-reaction equation for equation for u
[model.scalar_field.u.reaction]
expression = alpha*u - beta*u*v
# Declares the jacobian of the reaction of u
[model.scalar_field.u.reaction.jacobian.u]
# ∂ᵤ(α·u - β·u·v) = α - β·v
expression = alpha - beta*v
[model.scalar_field.u.reaction.jacobian.v]
# ∂ᵥ(α·u - β·u·v) = - β·u
expression = -beta*u
[model.scalar_field.u.initial]
# function for u(x,y,0)
expression = 1
##### Definition of the equation to solve function v(x,y,t) ######
# Declares the compartment where this function is defined
[model.scalar_field.v]
compartment = domain
# Declares that the equation is transient
[model.scalar_field.v.storage]
expression = 1
# Declares the reaction part on the diffusion-reaction equation for equation for v
[model.scalar_field.v.reaction]
expression = delta*u*v - gamma*v
# Declares the jacobian of the reaction of v
[model.scalar_field.v.reaction.jacobian.u]
# ∂ᵤ(δ·u·v - γ·v) = δ·v
expression = delta*v
[model.scalar_field.v.reaction.jacobian.v]
# ∂ᵥ(δ·u·v - γ·v) = δ·u - γ
expression = delta*u-gamma
[model.scalar_field.v.initial]
# function for v(x,y,0)
expression = 1
[model.time_step_operator]
# initial time of the simulation
time_begin = 0
# final time of the simulation
time_end = 20
# limit the maximum time-step
time_step_max = 0.25
---
id: config
title: Configuration Options
description: API & CLI configuration options
sidebar_label: Configuration Options
tags:
- API
- CLI
---
import DocCardList from '@theme/DocCardList';
In order to configure DuneCopasi, a set of configuration options must be provided.
When using the [GUI](use_gui), the program will automatically them set up for you. On the other hand, in the
case of [CLI](use_cli) and [API](use_cli) usage, they need to be manually specified.
In the following documentation pages we will assume that you are working with the [CLI](use_cli).
The [API](use_cli) essentially consists on the same options sythetized in the
[`Dune::ParameterTree`](https://www.dune-project.org/doxygen/2.9.1/classDune_1_1ParameterTree.html) C++ object.
<DocCardList/>
......@@ -3,46 +3,37 @@ id: ini_file
title: Config File
description: Syntax of INI file
sidebar_label: Config File
tags:
- API
- CLI
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
The [INI format](https://en.wikipedia.org/wiki/INI_file) defines a set of [configuration options](param_tree) to initialize and run the models.
::::note CLI Usage
This documentation page is intended for the [Command Line Interface (CLI)](use_cli). If you're new to DuneCopasi, we recommend starting with our [Tutorials](/tutorials).
::::
## Format
To express different [mathematical problems](/math_model) we typically write a configuration file (with `.ini` extension by convention) which entails all the information that is needed for the DuneCopasi solver to construct the problem at hand.
The configuration file consists of a parameter tree containing the [simulation options](param_tree). The nodes at the top level can be divided in 4 categories:
The forrmat we use follows the DUNE `ini` file convention. In short, the data is composed of a *key–value pairs* on the form `key = value`.
| Category | Description |
| ---- | ----------- |
| `grid` | The nodes under the grid header describe the basic properties of the grid. For example the dimension, extension, origin, etc.
| `parser_context` | Under this node we are able to define constant and functions that can be used to define the mathematical model.
| `compartments` | In this category we define the properties related to division of the problem to multiple compartments.
| `model` | This is the heart of the mathematical problem where we define the reaction terms, diffusion, etc.
### Comments
Characters followed by hash `#` will be ignored.
```ini title="config.ini"
# %highlight
# line comment
key = value
```
### Entries
An entry is given by a *key-value pair* and must be entirely contained in one line. Additionally, *keys* must be unique.
The ini files we use follow the DUNE convention. In short, the data is composed of a key–value pairs on the form ```key = value```. For example, to define a `property` of the category `grid` we write
```ini title="config.ini"
id = value
# %highlight-error
id = val
# error: repeated key 'id'
grid.property = value
```
### Group
In essence the ini file is nothing else than a parameter tree of key-value pairs. For convenience one can use sections to avoid rewriting the leading part and provide more structure. This is done by using ``` [section.subsection] ``` syntax. The keys below will now be within the designated subsection. As an example, the three following ini files, are equivalent
A *key* is a string which may be contained on a common
group of parameters by preceding the line with the *group name* between
brackets and/or by preceding the *key* by the *group name* separated by a dot. Notice that
the two forms may be combined.
As an example, the three following INI files, are equivalent
<Tabs
defaultValue="form1"
values={[
......@@ -55,7 +46,7 @@ As an example, the three following INI files, are equivalent
<TabItem value="form1">
```ini title="config.ini"
# No preceding section
# No preceding section (everything after a '#' will be ignored)
section.subsection.first = 1.0
section.subsection.second = 2.0
```
......@@ -82,3 +73,39 @@ second = 2.0
</TabItem>
</Tabs>
:::tip Examples
import HeatINI from '!!raw-loader!./assets/ini/heat.ini';
import VolkaTerraINI from '!!raw-loader!./assets/ini/volka_terra.ini';
import GreyScottINI from '!!raw-loader!./assets/ini/grey_scott.ini';
<Tabs
groupId="config-examples"
defaultValue="heat"
values={[
{label: 'Heat Eqs', value: 'heat', },
{label: 'Volka-Terra Eqs', value: 'volka_terra', },
{label: 'Grey-Scott Eqs', value: 'grey_scott', },
]
}>
<TabItem value="heat">
<CodeBlock language="ini" title="heat.ini" showLineNumbers>
{HeatINI}
</CodeBlock>
</TabItem>
<TabItem value="volka_terra">
<CodeBlock language="ini" title="volka_terra.ini" showLineNumbers>
{VolkaTerraINI}
</CodeBlock>
</TabItem>
<TabItem value="grey_scott">
<CodeBlock language="ini" title="grey_scott.ini" showLineNumbers>
{GreyScottINI}
</CodeBlock>
</TabItem>
</Tabs>
:::
......@@ -3,6 +3,9 @@ id: input_data
title: Input Data
description: List of possible to input data
sidebar_label: Input Data
tags:
- API
- CLI
---
import ConfigOptsJSON from './assets/config_opts.json';
......@@ -10,6 +13,10 @@ import Markdown from 'react-markdown';
export const JoinDetailsArray = (a) => {return Array.isArray(a) ? a.join('\n') : a}
::::note CLI Usage
This documentation page is intended for the [Command Line Interface (CLI)](use_cli). If you're new to DuneCopasi, we recommend starting with our [Tutorials](/tutorials).
::::
Several input data files in the `dune-copasi` program are possible:
### Config Options (INI Format)
......@@ -85,4 +92,4 @@ Notice how `position_x` and `position_y` are assigned on each grid cell to deter
If the resulting function `{tkn}` is evaluated outside the domain of the `tiff` image, the
arguments will be [clamped](https://en.wikipedia.org/wiki/Clamping_(graphics)) to
the nearest valid point in the domain.
:::
\ No newline at end of file
:::
---
id: install
title: Installation Options
description: What are the installation options?
sidebar_label: Install
tags:
- Docker
- Debian
- GUI
- API
- CLI
---
import DocCardList from '@theme/DocCardList';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
import React, { useState } from 'react';
:::tip CLI on the Web Browser
If you're interested in exploring and using the [Command Line Interface (CLI)](use_cli) without installation, you're in luck! The [Web Browser executable](try) allows you to interact with the CLI directly from any device. No setup required—just open your browser and start experimenting!
:::
## Tailored Recommendations
Getting started with DuneCopasi might seem daunting due to its wide range of options.
However, by making selections below, you'll receive tailored recommendations that fit your needs and use case.
export const Checklist = ({ title, options, selectedOptions, setSelectedOptions }) => {
const handleCardClick = (value) => {
setSelectedOptions((prev) =>
prev.includes(value) ? prev.filter((item) => item !== value) : [...prev, value]
);
};
return (
<div className="container">
<div className="card-description-container">
<h4 className="card-title">{title}</h4>
</div>
<div className="card-list">
{options.map(({ value, label }) => (
<div
key={value}
className={`card-container ${selectedOptions.includes(value) ? 'selected' : ''}`}
onClick={() => handleCardClick(value)}
>
<input
type="checkbox"
value={value}
checked={selectedOptions.includes(value)}
onChange={() => handleCardClick(value)}
style={{ display: 'none' }}
/>
<div className="card-style">
<div className="card-body">
<h4 className="card-title">{label}</h4>
</div>
</div>
</div>
))}
</div>
</div>
);
};
export const FilterDocCardList = ({ ids }) => (
<DocCardList
items={useCurrentSidebarCategory().items.filter(
item => !ids || ids.length === 0 || ids.includes(item.docId)
)}
/>
);
export const getRecommendations = (os, usage, user) => {
const recommendations = [];
if (usage.includes('GUI')) {
recommendations.push('install_binary');
}
if (usage.includes('CLI')) {
recommendations.push('install_docker');
if (os.includes('Linux') && user.includes('user')) {
recommendations.push('install_package');
}
}
if (usage.includes('API')) {
recommendations.push('install_docker');
if (os.includes('Linux') || os.includes('macOS')) {
recommendations.push('install_source');
}
}
if (user.includes('dev')) {
recommendations.push('install_docker');
if (os.includes('Linux') || os.includes('macOS')) {
recommendations.push('install_source');
}
}
if (recommendations.length === 0) {
recommendations.push('install_binary');
}
return recommendations;
};
export function TailoredRecommendation() {
const [osSelection, setOsSelection] = useState([]);
const [usageSelection, setUsageSelection] = useState([]);
const [userSelection, setUserSelection] = useState([]);
const osOptions = [
{ value: 'Windows', label: 'Windows' },
{ value: 'macOS', label: 'macOS' },
{ value: 'Linux', label: 'Linux' },
];
const usageOptions = [
{ value: 'GUI', label: 'Graphical User Interface' },
{ value: 'CLI', label: 'Command Line Interface' },
{ value: 'API', label: 'Application Public Interface' },
];
const userOptions = [
{ value: 'user', label: 'Simulate Models' },
{ value: 'dev', label: 'Develop New Features' },
];
const recommendations = getRecommendations(osSelection, usageSelection, userSelection);
return (
<div>
<Checklist
title="I want to use the"
options={usageOptions}
selectedOptions={usageSelection}
setSelectedOptions={setUsageSelection}
/>
<Checklist
title="My Operating System is"
options={osOptions}
selectedOptions={osSelection}
setSelectedOptions={setOsSelection}
/>
<Checklist
title="I want to"
options={userOptions}
selectedOptions={userSelection}
setSelectedOptions={setUserSelection}
/>
<div className="recommendation-container">
<h3 className="recommendation-title">Recommendations:</h3>
{recommendations.length > 0 && (
<FilterDocCardList ids={recommendations} />
)}
</div>
</div>
);
}
<TailoredRecommendation />
## Installation Guides by Category
Explore the installation options organized by different categories:
### By usage interface
<Tabs className="unique-tabs">
<TabItem value="GUI" label="Graphical User Interface">
<FilterDocCardList ids = {['install_binary']}/>
</TabItem>
<TabItem value="CLI" label="Command Line Interface" default>
<FilterDocCardList ids = {['install_docker', 'install_package', 'install_source']}/>
</TabItem>
<TabItem value="API" label="Application User Interface">
<FilterDocCardList ids = {['install_docker', 'install_source']}/>
</TabItem>
</Tabs>
### By operating system
<Tabs className="unique-tabs">
<TabItem value="Windows" label="Windows">
<FilterDocCardList ids = {['install_binary', 'install_docker']}/>
</TabItem>
<TabItem value="macOS" label="macOS" default>
<FilterDocCardList ids = {['install_docker', 'install_source']}/>
</TabItem>
<TabItem value="Debian" label="Linux (Debian 11)">
<FilterDocCardList ids = {['install_package', 'install_docker', 'install_source']}/>
</TabItem>
<TabItem value="Linux" label="Linux (Other)">
<FilterDocCardList ids = {['install_docker', 'install_source']}/>
</TabItem>
</Tabs>