dualmesh-multiphysics 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dualmesh_multiphysics-0.1.0/.clang-format +13 -0
- dualmesh_multiphysics-0.1.0/.github/workflows/ci.yml +116 -0
- dualmesh_multiphysics-0.1.0/.github/workflows/wheels.yml +63 -0
- dualmesh_multiphysics-0.1.0/.gitignore +44 -0
- dualmesh_multiphysics-0.1.0/.readthedocs.yaml +28 -0
- dualmesh_multiphysics-0.1.0/CHANGELOG.md +167 -0
- dualmesh_multiphysics-0.1.0/CITATION.cff +37 -0
- dualmesh_multiphysics-0.1.0/CMakeLists.txt +141 -0
- dualmesh_multiphysics-0.1.0/CONTRIBUTING.md +62 -0
- dualmesh_multiphysics-0.1.0/LICENSE +502 -0
- dualmesh_multiphysics-0.1.0/PKG-INFO +198 -0
- dualmesh_multiphysics-0.1.0/README.md +150 -0
- dualmesh_multiphysics-0.1.0/docs/_generate_syntax.py +333 -0
- dualmesh_multiphysics-0.1.0/docs/_syntax_examples.py +818 -0
- dualmesh_multiphysics-0.1.0/docs/api.rst +108 -0
- dualmesh_multiphysics-0.1.0/docs/conf.py +78 -0
- dualmesh_multiphysics-0.1.0/docs/developing.rst +122 -0
- dualmesh_multiphysics-0.1.0/docs/getting_started.rst +159 -0
- dualmesh_multiphysics-0.1.0/docs/index.rst +183 -0
- dualmesh_multiphysics-0.1.0/docs/input_files.rst +117 -0
- dualmesh_multiphysics-0.1.0/docs/installation.rst +67 -0
- dualmesh_multiphysics-0.1.0/docs/openfoam.rst +157 -0
- dualmesh_multiphysics-0.1.0/docs/references.rst +540 -0
- dualmesh_multiphysics-0.1.0/docs/scope.rst +176 -0
- dualmesh_multiphysics-0.1.0/docs/theory/adaptivity.rst +522 -0
- dualmesh_multiphysics-0.1.0/docs/theory/elements.rst +745 -0
- dualmesh_multiphysics-0.1.0/docs/theory/finite_volume.rst +589 -0
- dualmesh_multiphysics-0.1.0/docs/theory/foundations.rst +239 -0
- dualmesh_multiphysics-0.1.0/docs/theory/heat_and_fluids.rst +671 -0
- dualmesh_multiphysics-0.1.0/docs/theory/index.rst +36 -0
- dualmesh_multiphysics-0.1.0/docs/theory/nonlinear_and_time.rst +88 -0
- dualmesh_multiphysics-0.1.0/docs/theory/parallel.rst +604 -0
- dualmesh_multiphysics-0.1.0/docs/theory/solid_mechanics.rst +576 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/custom_kernel.rst +38 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/elasticity.rst +25 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/flow.rst +21 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/heat_conduction.rst +47 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/index.rst +15 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/structures.rst +33 -0
- dualmesh_multiphysics-0.1.0/docs/tutorials/transient.rst +21 -0
- dualmesh_multiphysics-0.1.0/docs/user_guide/index.rst +19 -0
- dualmesh_multiphysics-0.1.0/docs/user_guide/meshes.rst +539 -0
- dualmesh_multiphysics-0.1.0/docs/user_guide/output.rst +212 -0
- dualmesh_multiphysics-0.1.0/docs/user_guide/problem_setup.rst +333 -0
- dualmesh_multiphysics-0.1.0/docs/user_guide/solving.rst +388 -0
- dualmesh_multiphysics-0.1.0/docs/verification.rst +296 -0
- dualmesh_multiphysics-0.1.0/examples/bus_bar.yaml +52 -0
- dualmesh_multiphysics-0.1.0/examples/cooling_fin.py +35 -0
- dualmesh_multiphysics-0.1.0/examples/custom_kernel.py +45 -0
- dualmesh_multiphysics-0.1.0/examples/functionally_graded_beam.py +69 -0
- dualmesh_multiphysics-0.1.0/examples/lid_driven_cavity.py +93 -0
- dualmesh_multiphysics-0.1.0/examples/natural_convection.py +117 -0
- dualmesh_multiphysics-0.1.0/examples/plate_with_hole.py +63 -0
- dualmesh_multiphysics-0.1.0/examples/transient_slab.py +52 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/Factory.h +77 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/Kernel.h +110 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/Material.h +58 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/Object.h +98 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/Problem.h +478 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/base/QpContext.h +71 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/core/ADReal.h +387 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/core/Function.h +69 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/core/InputParameters.h +123 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/core/ParsedFunction.h +91 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/core/Types.h +80 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/fe/Assembly.h +95 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/fe/ReferenceElement.h +223 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/fv/CellMesh.h +90 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/linalg/IncompleteLU.h +83 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/mesh/Adapt.h +57 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/mesh/Mesh.h +196 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/modules/Framework.h +177 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/parallel/Communicator.h +68 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/parallel/DistributedProblem.h +205 -0
- dualmesh_multiphysics-0.1.0/include/dualmesh/parallel/Partition.h +80 -0
- dualmesh_multiphysics-0.1.0/pyproject.toml +72 -0
- dualmesh_multiphysics-0.1.0/python/bindings/module.cpp +1064 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/__init__.py +162 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/ad.py +60 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/adaptivity.py +164 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/cli.py +348 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/expressions.py +50 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/fgm.py +127 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/meshing.py +417 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/mms.py +542 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/objects.py +234 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/parallel.py +331 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/physics.py +338 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/postprocess.py +64 -0
- dualmesh_multiphysics-0.1.0/python/dualmesh/problem.py +552 -0
- dualmesh_multiphysics-0.1.0/src/base/Objects.cpp +478 -0
- dualmesh_multiphysics-0.1.0/src/base/Problem.cpp +589 -0
- dualmesh_multiphysics-0.1.0/src/base/ProblemAssembly.cpp +1082 -0
- dualmesh_multiphysics-0.1.0/src/base/ProblemFiniteVolume.cpp +651 -0
- dualmesh_multiphysics-0.1.0/src/base/ProblemPostprocess.cpp +549 -0
- dualmesh_multiphysics-0.1.0/src/core/Function.cpp +37 -0
- dualmesh_multiphysics-0.1.0/src/core/InputParameters.cpp +332 -0
- dualmesh_multiphysics-0.1.0/src/core/ParsedFunction.cpp +459 -0
- dualmesh_multiphysics-0.1.0/src/fe/Assembly.cpp +842 -0
- dualmesh_multiphysics-0.1.0/src/fe/ReferenceElement.cpp +1268 -0
- dualmesh_multiphysics-0.1.0/src/fv/CellMesh.cpp +237 -0
- dualmesh_multiphysics-0.1.0/src/linalg/IncompleteLU.cpp +97 -0
- dualmesh_multiphysics-0.1.0/src/mesh/Adapt.cpp +271 -0
- dualmesh_multiphysics-0.1.0/src/mesh/Mesh.cpp +1235 -0
- dualmesh_multiphysics-0.1.0/src/modules/Fluids.cpp +382 -0
- dualmesh_multiphysics-0.1.0/src/modules/Framework.cpp +632 -0
- dualmesh_multiphysics-0.1.0/src/modules/HeatTransfer.cpp +393 -0
- dualmesh_multiphysics-0.1.0/src/modules/SolidMechanics.cpp +511 -0
- dualmesh_multiphysics-0.1.0/src/modules/SolidMechanicsStructures.cpp +978 -0
- dualmesh_multiphysics-0.1.0/src/parallel/Communicator.cpp +254 -0
- dualmesh_multiphysics-0.1.0/src/parallel/DistributedProblem.cpp +1033 -0
- dualmesh_multiphysics-0.1.0/src/parallel/Partition.cpp +375 -0
- dualmesh_multiphysics-0.1.0/tests/cpp/benchmark.cpp +134 -0
- dualmesh_multiphysics-0.1.0/tests/cpp/parallel_tests.cpp +435 -0
- dualmesh_multiphysics-0.1.0/tests/cpp/unit_tests.cpp +568 -0
- dualmesh_multiphysics-0.1.0/tests/python/conftest.py +30 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_adaptivity.py +394 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_beams.py +313 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_element_types.py +289 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_finite_volume.py +396 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_fluids.py +288 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_framework.py +848 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_heat_transfer.py +457 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_mms.py +423 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_multiphysics.py +160 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_parallel.py +263 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_plates.py +463 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_quadratic_elements.py +460 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_solid_mechanics.py +527 -0
- dualmesh_multiphysics-0.1.0/tests/python/test_time_stepping.py +284 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/README.md +25 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/cavity_openfoam.sh +70 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/compare_cavity.py +229 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/compare_conduction.py +107 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/compare_plate_hole.py +168 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/conduction_openfoam.sh +137 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/plate_hole_openfoam.sh +37 -0
- dualmesh_multiphysics-0.1.0/verification/openfoam/run_all.sh +9 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Based on the MOOSE framework style.
|
|
2
|
+
BasedOnStyle: LLVM
|
|
3
|
+
AlwaysBreakAfterReturnType: TopLevelDefinitions
|
|
4
|
+
AlignAfterOpenBracket: Align
|
|
5
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
6
|
+
BinPackArguments: false
|
|
7
|
+
BinPackParameters: false
|
|
8
|
+
BreakBeforeBraces: Allman
|
|
9
|
+
ColumnLimit: 100
|
|
10
|
+
IndentWidth: 2
|
|
11
|
+
PointerAlignment: Middle
|
|
12
|
+
SpaceAfterCStyleCast: true
|
|
13
|
+
Standard: c++17
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
cpp:
|
|
15
|
+
name: C++ (${{ matrix.os }})
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.11"
|
|
26
|
+
- name: Configure
|
|
27
|
+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DDUALMESH_BUILD_PYTHON=OFF
|
|
28
|
+
- name: Build
|
|
29
|
+
run: cmake --build build --config Release -j
|
|
30
|
+
- name: Test
|
|
31
|
+
run: ctest --test-dir build --build-config Release --output-on-failure
|
|
32
|
+
|
|
33
|
+
mpi:
|
|
34
|
+
name: MPI (1, 2, 3 and 4 processes)
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- name: Install MPI and METIS
|
|
39
|
+
run: sudo apt-get update && sudo apt-get install -y libopenmpi-dev openmpi-bin libmetis-dev libeigen3-dev
|
|
40
|
+
- name: Configure
|
|
41
|
+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DDUALMESH_BUILD_PYTHON=OFF -DDUALMESH_ENABLE_MPI=ON
|
|
42
|
+
- name: Build
|
|
43
|
+
run: cmake --build build -j
|
|
44
|
+
- name: Distributed tests
|
|
45
|
+
run: |
|
|
46
|
+
for n in 1 2 3 4; do
|
|
47
|
+
mpirun --oversubscribe -n $n ./build/dualmesh_parallel_tests
|
|
48
|
+
done
|
|
49
|
+
|
|
50
|
+
python:
|
|
51
|
+
name: Python ${{ matrix.python-version }} (${{ matrix.os }})
|
|
52
|
+
runs-on: ${{ matrix.os }}
|
|
53
|
+
strategy:
|
|
54
|
+
fail-fast: false
|
|
55
|
+
matrix:
|
|
56
|
+
os: [ubuntu-latest, macos-latest]
|
|
57
|
+
python-version: ["3.9", "3.11", "3.12"]
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
- uses: actions/setup-python@v5
|
|
61
|
+
with:
|
|
62
|
+
python-version: ${{ matrix.python-version }}
|
|
63
|
+
- name: Install
|
|
64
|
+
run: pip install .[all,test]
|
|
65
|
+
- name: Verification suite
|
|
66
|
+
run: pytest -q
|
|
67
|
+
- name: Examples
|
|
68
|
+
run: |
|
|
69
|
+
python examples/cooling_fin.py
|
|
70
|
+
python examples/custom_kernel.py
|
|
71
|
+
python examples/functionally_graded_beam.py
|
|
72
|
+
python examples/transient_slab.py
|
|
73
|
+
python examples/natural_convection.py
|
|
74
|
+
- name: Command line
|
|
75
|
+
run: |
|
|
76
|
+
dualmesh --version
|
|
77
|
+
dualmesh list --module heat_transfer
|
|
78
|
+
dualmesh describe HeatConduction
|
|
79
|
+
cd examples && dualmesh run bus_bar.yaml
|
|
80
|
+
|
|
81
|
+
lint:
|
|
82
|
+
name: Lint
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- uses: actions/setup-python@v5
|
|
87
|
+
with:
|
|
88
|
+
python-version: "3.11"
|
|
89
|
+
- name: Install tools
|
|
90
|
+
run: pip install ruff
|
|
91
|
+
- name: Ruff
|
|
92
|
+
run: ruff check python tests examples
|
|
93
|
+
- name: clang-format
|
|
94
|
+
run: |
|
|
95
|
+
sudo apt-get update && sudo apt-get install -y clang-format
|
|
96
|
+
find include src python/bindings tests/cpp -name '*.h' -o -name '*.cpp' \
|
|
97
|
+
| xargs clang-format --dry-run --Werror
|
|
98
|
+
|
|
99
|
+
docs:
|
|
100
|
+
name: Documentation
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@v4
|
|
104
|
+
- uses: actions/setup-python@v5
|
|
105
|
+
with:
|
|
106
|
+
python-version: "3.11"
|
|
107
|
+
- name: Install
|
|
108
|
+
run: |
|
|
109
|
+
sudo apt-get update && sudo apt-get install -y libeigen3-dev
|
|
110
|
+
pip install .[docs,all]
|
|
111
|
+
- name: Build documentation
|
|
112
|
+
run: sphinx-build -b html docs docs/_build/html
|
|
113
|
+
- uses: actions/upload-artifact@v4
|
|
114
|
+
with:
|
|
115
|
+
name: documentation
|
|
116
|
+
path: docs/_build/html
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Wheels
|
|
2
|
+
|
|
3
|
+
# Binary wheels, so that `pip install dualmesh-multiphysics` needs no compiler.
|
|
4
|
+
#
|
|
5
|
+
# The wheels are built on every tag that starts with "v" and on demand, and are
|
|
6
|
+
# kept as workflow artifacts. Publishing to PyPI is the last job; it runs only
|
|
7
|
+
# for a tag, and uses PyPI's trusted publishing, which has to be enabled once
|
|
8
|
+
# for the repository on pypi.org (Publishing -> Add a new publisher) before the
|
|
9
|
+
# first release.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags: ["v*"]
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
wheels:
|
|
18
|
+
name: Wheels (${{ matrix.os }})
|
|
19
|
+
runs-on: ${{ matrix.os }}
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
os: [ubuntu-latest, macos-15-intel, macos-14, windows-latest]
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: pypa/cibuildwheel@v4.2.1
|
|
27
|
+
env:
|
|
28
|
+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
|
|
29
|
+
CIBW_SKIP: "*-musllinux_* *-win32 *-manylinux_i686"
|
|
30
|
+
CIBW_TEST_EXTRAS: "test"
|
|
31
|
+
CIBW_TEST_COMMAND: >-
|
|
32
|
+
pytest {project}/tests/python -q -x
|
|
33
|
+
--ignore={project}/tests/python/test_mms.py
|
|
34
|
+
- uses: actions/upload-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: wheels-${{ matrix.os }}
|
|
37
|
+
path: wheelhouse/*.whl
|
|
38
|
+
|
|
39
|
+
sdist:
|
|
40
|
+
name: Source distribution
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- run: pipx run build --sdist
|
|
45
|
+
- uses: actions/upload-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: sdist
|
|
48
|
+
path: dist/*.tar.gz
|
|
49
|
+
|
|
50
|
+
publish:
|
|
51
|
+
name: Publish to PyPI
|
|
52
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
53
|
+
needs: [wheels, sdist]
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
environment: pypi
|
|
56
|
+
permissions:
|
|
57
|
+
id-token: write
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
path: dist
|
|
62
|
+
merge-multiple: true
|
|
63
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# build artefacts
|
|
2
|
+
build/
|
|
3
|
+
build-*/
|
|
4
|
+
_build/
|
|
5
|
+
dist/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.so
|
|
8
|
+
*.pyd
|
|
9
|
+
*.dylib
|
|
10
|
+
*.o
|
|
11
|
+
*.a
|
|
12
|
+
CMakeCache.txt
|
|
13
|
+
CMakeFiles/
|
|
14
|
+
|
|
15
|
+
# python
|
|
16
|
+
__pycache__/
|
|
17
|
+
*.py[cod]
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.venv/
|
|
21
|
+
venv/
|
|
22
|
+
|
|
23
|
+
# results
|
|
24
|
+
*.vtu
|
|
25
|
+
*.pvtu
|
|
26
|
+
*.pvd
|
|
27
|
+
*.csv
|
|
28
|
+
*.e
|
|
29
|
+
*.exo
|
|
30
|
+
!examples/**/*.csv
|
|
31
|
+
|
|
32
|
+
# editors and systems
|
|
33
|
+
.vscode/
|
|
34
|
+
.idea/
|
|
35
|
+
.DS_Store
|
|
36
|
+
|
|
37
|
+
# OpenFOAM cases
|
|
38
|
+
verification/openfoam/run/
|
|
39
|
+
|
|
40
|
+
# generated by the documentation build
|
|
41
|
+
docs/objects.rst
|
|
42
|
+
|
|
43
|
+
# generated when the documentation is built
|
|
44
|
+
docs/syntax/
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
build:
|
|
4
|
+
os: ubuntu-22.04
|
|
5
|
+
tools:
|
|
6
|
+
python: "3.11"
|
|
7
|
+
apt_packages:
|
|
8
|
+
- cmake
|
|
9
|
+
- libeigen3-dev
|
|
10
|
+
jobs:
|
|
11
|
+
post_checkout:
|
|
12
|
+
- git fetch --unshallow || true
|
|
13
|
+
|
|
14
|
+
python:
|
|
15
|
+
install:
|
|
16
|
+
- method: pip
|
|
17
|
+
path: .
|
|
18
|
+
extra_requirements:
|
|
19
|
+
- docs
|
|
20
|
+
- all
|
|
21
|
+
|
|
22
|
+
sphinx:
|
|
23
|
+
configuration: docs/conf.py
|
|
24
|
+
fail_on_warning: false
|
|
25
|
+
|
|
26
|
+
formats:
|
|
27
|
+
- pdf
|
|
28
|
+
- htmlzip
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses
|
|
5
|
+
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
dualmesh is now described, and organised, as what it is: a multiphysics
|
|
10
|
+
framework for heat transfer, solid mechanics and fluid dynamics, in which the
|
|
11
|
+
finite element method, two finite volume methods and the dual mesh control
|
|
12
|
+
domain method are four discretisations of one problem description.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Four new element types**: the serendipity `Quad8` and `Hex20`, the
|
|
17
|
+
triangular prism `Wedge6` and the pyramid `Pyramid5` (with Bedrosian's
|
|
18
|
+
rational basis). Meshes may mix types freely. Every type works with the
|
|
19
|
+
finite element and cell-centred finite volume methods; the dual mesh and
|
|
20
|
+
vertex-centred methods, which need node-centred control domains, accept the
|
|
21
|
+
prism (whose dual is the triangle's median dual times a half-segment) and
|
|
22
|
+
refuse the serendipity elements and the pyramid with the reason and the
|
|
23
|
+
methods that do accept them. `Mesh.second_order(serendipity=True)`,
|
|
24
|
+
generators for all four, uniform refinement of prisms and pyramids, and
|
|
25
|
+
meshio reading and writing.
|
|
26
|
+
- **Systematic verification by manufactured solutions**: `dualmesh.mms`
|
|
27
|
+
derives the forcing of a chosen solution symbolically (diffusion,
|
|
28
|
+
advection, reaction, time derivative, linear elasticity; Cartesian,
|
|
29
|
+
axisymmetric and spherical) and runs convergence studies;
|
|
30
|
+
`Problem.error_norms` measures the L2 error and the H1 seminorm. The suite
|
|
31
|
+
runs 161 studies and every observed order matches the theory of its method.
|
|
32
|
+
- **Coupled heat transfer and flow**: `HeatConvection` (the flow carries the
|
|
33
|
+
heat) and `BoussinesqBuoyancy` (the temperature drives the flow), with
|
|
34
|
+
`physics.add_boussinesq_buoyancy`. The natural convection benchmark of de
|
|
35
|
+
Vahl Davis is reproduced to within 0.2 % in the Nusselt number
|
|
36
|
+
(`examples/natural_convection.py`).
|
|
37
|
+
- **Overlapping Schwarz**: the distributed preconditioners now work on
|
|
38
|
+
subdomains that overlap by `overlap` layers of elements (default 1), with
|
|
39
|
+
fully assembled subdomain matrices exchanged between ranks, an exact or
|
|
40
|
+
incomplete subdomain solve (`subdomain_solver`), and the two levels combined
|
|
41
|
+
multiplicatively. The iteration count of the default no longer grows with
|
|
42
|
+
the number of processes: 23 to 25 iterations from 1 to 16 ranks on a 48 by 48
|
|
43
|
+
Poisson problem. With `linear_solver="cg"` the symmetric (classical) forms
|
|
44
|
+
are used.
|
|
45
|
+
- **Automatic linear solver** (`linear_solver="automatic"`, the new default):
|
|
46
|
+
a direct factorisation where it is cheap and BiCGSTAB with a new ILU(0)
|
|
47
|
+
preconditioner where it is not, falling back to the direct solver if the
|
|
48
|
+
iteration fails. Also `"gmres"` and the `preconditioner` option (`ilu`,
|
|
49
|
+
`ilut`, `jacobi`, `none`). On a three-dimensional elasticity system of 36 000
|
|
50
|
+
unknowns the solve fell from 18 s to 0.3 s.
|
|
51
|
+
- `Problem.linear_system()` returns the residual and the Jacobian as NumPy and
|
|
52
|
+
SciPy objects, for use with other solvers.
|
|
53
|
+
- Expressions are compiled by a C++ parser (`ParsedFunction`), and a string
|
|
54
|
+
that is not the name of a registered function is compiled as an expression.
|
|
55
|
+
- The command-line driver runs an input file under `mpirun` with the
|
|
56
|
+
distributed solver (configured by a `parallel` block), accepts `threads`, and
|
|
57
|
+
refuses an unknown block or setting with a suggestion.
|
|
58
|
+
- "Did you mean" suggestions for misspelled object types, parameters,
|
|
59
|
+
variables, boundaries, blocks and solver options.
|
|
60
|
+
- A continuous-integration job that runs the distributed tests on 1 to 4
|
|
61
|
+
processes, and a workflow that builds binary wheels.
|
|
62
|
+
- Documentation: a scope chapter that defines the package as a multiphysics
|
|
63
|
+
framework and compares it honestly with MOOSE and COMSOL; a
|
|
64
|
+
manufactured-solutions chapter; the new elements, solvers and
|
|
65
|
+
preconditioners; the current MOOSE citation (MOOSE 4.0, 2025).
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- **The structural module is merged into solid mechanics.** Beams and plates
|
|
70
|
+
are the reduced theories of solid mechanics and are now registered in the
|
|
71
|
+
`solid_mechanics` module, next to continuum elasticity.
|
|
72
|
+
- **The default distributed preconditioner is `two_level_schwarz` with an
|
|
73
|
+
overlap of one element layer** (it was `jacobi`).
|
|
74
|
+
- **The cell-centred finite volume method has an exact Jacobian**: the
|
|
75
|
+
non-orthogonal correction is differentiated through the least-squares
|
|
76
|
+
stencils instead of being lagged, so Newton's method converges
|
|
77
|
+
quadratically on skewed meshes.
|
|
78
|
+
- **Efficiency**: element geometry is mapped once per integration point and
|
|
79
|
+
reference-element data are cached; the derivative arrays of the automatic
|
|
80
|
+
differentiation are copied only as far as they are used and their loops
|
|
81
|
+
vectorise; symmetric quadrature rules on triangles, tetrahedra and prisms
|
|
82
|
+
replace the collapsed tensor rules for the finite element method (8 points
|
|
83
|
+
instead of 27 on a tetrahedron); Gauss rules are tabulated. On the bundled
|
|
84
|
+
benchmark (three-dimensional elasticity on 8000 `Hex8` elements) the
|
|
85
|
+
assembly of every method is about three times faster on one thread; the
|
|
86
|
+
Python test suite runs in about 60 % of its former time.
|
|
87
|
+
- All element types use the VTK node numbering, so files need no permutation.
|
|
88
|
+
- Package metadata points to the GitHub repository.
|
|
89
|
+
|
|
90
|
+
### Fixed
|
|
91
|
+
|
|
92
|
+
- **The θ-method evaluated the old part of the residual at the new time**,
|
|
93
|
+
which cost Crank-Nicolson its second order whenever a coefficient or a
|
|
94
|
+
source depends on time (serial and distributed).
|
|
95
|
+
- **The Schwarz preconditioners factorised each rank's partial local matrix**
|
|
96
|
+
instead of the fully assembled subdomain matrix, which is why they stopped
|
|
97
|
+
converging at eight ranks.
|
|
98
|
+
- **The penalty formulation of incompressible flow locked on the
|
|
99
|
+
vertex-centred finite volume method**: the two-point gradient correction was
|
|
100
|
+
applied to the reduced-integration term. It is no longer, and the
|
|
101
|
+
cell-centred method, on which the formulation cannot work, now refuses it.
|
|
102
|
+
- **A compiled expression passed as a parameter was evaluated through
|
|
103
|
+
Python**, because pybind11's function test is Python's `callable()`, which
|
|
104
|
+
also serialised the assembly onto one thread.
|
|
105
|
+
- **Thermal stress in plane strain was wrong by a factor of `1 + nu`.** The
|
|
106
|
+
stiffness matrix left the out-of-plane column empty, so the thermal strain
|
|
107
|
+
subtracted from the out-of-plane normal strain never reached the in-plane
|
|
108
|
+
rows. For a fully restrained body the code gave
|
|
109
|
+
`E alpha dT / [(1 + nu)(1 - 2 nu)]` where the correct value is
|
|
110
|
+
`E alpha dT / (1 - 2 nu)`. Plane stress was unaffected.
|
|
111
|
+
- **A Python callable passed directly to a parameter no longer deadlocks the
|
|
112
|
+
threaded assembly.**
|
|
113
|
+
- **The cell-centred finite volume method is refused by the distributed
|
|
114
|
+
solver** instead of returning a wrong answer.
|
|
115
|
+
- **The distributed BiCGSTAB detects near-breakdown and restarts.**
|
|
116
|
+
- The Python test suite no longer imports the source tree instead of the
|
|
117
|
+
installed package when the extension has not been built in place.
|
|
118
|
+
|
|
119
|
+
### Earlier unreleased work
|
|
120
|
+
|
|
121
|
+
- **Quadratic elements** `Edge3`, `Tri6`, `Quad9`, `Tet10` and `Hex27`, with
|
|
122
|
+
the dual mesh built for each; **adaptive mesh refinement** by gradient
|
|
123
|
+
recovery, marking and longest-edge bisection; the automatic quadrature
|
|
124
|
+
order; `DUALMESH_MAX_AD_DERIVATIVES`; the manual reorganised into a user
|
|
125
|
+
guide and a theory manual with every method cited to its primary source.
|
|
126
|
+
|
|
127
|
+
## [0.1.0] - 2026-09-18
|
|
128
|
+
|
|
129
|
+
The first release: the framework, five physics modules, and a verification
|
|
130
|
+
suite that reproduces the published results of Reddy's book.
|
|
131
|
+
|
|
132
|
+
### Added
|
|
133
|
+
|
|
134
|
+
- **Framework**: the canonical conservation form `-div F + S = 0`; the median
|
|
135
|
+
dual mesh for `Edge2`, `Tri3`, `Quad4`, `Tet4` and `Hex8`; assembly for the
|
|
136
|
+
dual mesh control domain method and for the Galerkin finite element method
|
|
137
|
+
from the same kernels; forward-mode automatic differentiation for exact
|
|
138
|
+
Jacobians; per-kernel quadrature (Gauss, midpoint, trapezoid, Simpson,
|
|
139
|
+
nodal, interface, control-domain trapezoid) and selective reduced
|
|
140
|
+
integration; Cartesian, axisymmetric and spherical coordinates; blocks
|
|
141
|
+
(subdomains), side sets and node sets.
|
|
142
|
+
- **Solvers**: Newton's method, direct (Picard) iteration with relaxation,
|
|
143
|
+
load stepping, steady and transient (θ-method) executioners, sparse LU,
|
|
144
|
+
BiCGSTAB and conjugate gradient linear solvers.
|
|
145
|
+
- **Heat transfer module**: conduction with temperature-dependent
|
|
146
|
+
conductivity, volumetric heating, heat capacity, convective, radiative and
|
|
147
|
+
prescribed-flux boundary conditions.
|
|
148
|
+
- **Solid mechanics module**: linear elasticity (plane stress, plane strain,
|
|
149
|
+
axisymmetric, three-dimensional), traction and pressure boundary conditions,
|
|
150
|
+
stress and strain as material properties.
|
|
151
|
+
- **Structural module**: mixed Euler–Bernoulli beam, displacement and mixed
|
|
152
|
+
Timoshenko beams, first-order axisymmetric circular plate, first-order
|
|
153
|
+
rectangular plate, functionally graded sections, von Kármán nonlinearity.
|
|
154
|
+
- **Fluids module**: penalty formulation of the Stokes and Navier–Stokes
|
|
155
|
+
equations with recovered pressure.
|
|
156
|
+
- **Meshing**: line, rectangle, box and annulus generators with graded
|
|
157
|
+
spacing, uniform refinement, geometric side sets and node sets, and readers
|
|
158
|
+
and writers for Gmsh, Exodus, VTK, Abaqus and the other formats meshio
|
|
159
|
+
supports.
|
|
160
|
+
- **Python interface**: `Problem`, mesh generators, physics helpers,
|
|
161
|
+
post-processing, functionally graded stiffness formulas, and base classes
|
|
162
|
+
for kernels, boundary conditions and materials written in Python.
|
|
163
|
+
- **Command line**: `dualmesh run input.yaml`, `dualmesh list`,
|
|
164
|
+
`dualmesh describe <type>`.
|
|
165
|
+
- **Verification**: the published dual mesh results of Chapters 3, 5, 6, 7, 8,
|
|
166
|
+
9 and 10 of Reddy's book, plus patch tests, conservation tests and
|
|
167
|
+
cross-verification against OpenFOAM.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
title: "dualmesh: a multiphysics framework for heat transfer, solid mechanics and fluid dynamics"
|
|
3
|
+
message: "If you use this software, please cite both the software and the method (see references)."
|
|
4
|
+
type: software
|
|
5
|
+
version: 0.1.0
|
|
6
|
+
license: LGPL-2.1-or-later
|
|
7
|
+
repository-code: "https://github.com/MohamedAbdulHameed/dualmesh"
|
|
8
|
+
url: "https://dualmesh.readthedocs.io"
|
|
9
|
+
abstract: >-
|
|
10
|
+
dualmesh is a multiphysics framework for heat transfer, solid mechanics and
|
|
11
|
+
fluid dynamics. Coupled problems are solved monolithically by Newton's method
|
|
12
|
+
with exact Jacobians from automatic differentiation, and the same problem
|
|
13
|
+
definition is discretised by the Galerkin finite element method, the
|
|
14
|
+
vertex-centred or cell-centred finite volume method, or the dual mesh control
|
|
15
|
+
domain method (DMCDM) of J. N. Reddy. The library is written in
|
|
16
|
+
C++17 with Python bindings, is organized as a modular framework of kernels,
|
|
17
|
+
boundary conditions and materials, and is verified against the published
|
|
18
|
+
results of Reddy's book and against OpenFOAM.
|
|
19
|
+
keywords:
|
|
20
|
+
- dual mesh control domain method
|
|
21
|
+
- finite element method
|
|
22
|
+
- finite volume method
|
|
23
|
+
- fluid dynamics
|
|
24
|
+
- solid mechanics
|
|
25
|
+
- heat transfer
|
|
26
|
+
- multiphysics
|
|
27
|
+
authors:
|
|
28
|
+
- name: "The dualmesh developers"
|
|
29
|
+
references:
|
|
30
|
+
- type: book
|
|
31
|
+
title: "Computational Methods in Engineering: Finite Difference, Finite Volume, Finite Element, and Dual Mesh Control Domain Methods"
|
|
32
|
+
authors:
|
|
33
|
+
- family-names: Reddy
|
|
34
|
+
given-names: "J. N."
|
|
35
|
+
publisher:
|
|
36
|
+
name: "CRC Press"
|
|
37
|
+
year: 2024
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.18)
|
|
2
|
+
project(dualmesh VERSION 0.1.0 LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
7
|
+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
8
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
9
|
+
endif()
|
|
10
|
+
|
|
11
|
+
option(DUALMESH_BUILD_PYTHON "Build the Python extension module" ON)
|
|
12
|
+
option(DUALMESH_BUILD_TESTS "Build the C++ unit tests" ON)
|
|
13
|
+
option(DUALMESH_ENABLE_OPENMP "Thread the assembly loops with OpenMP" ON)
|
|
14
|
+
option(DUALMESH_ENABLE_MPI "Build the distributed (MPI) solver" OFF)
|
|
15
|
+
option(DUALMESH_ENABLE_METIS "Use METIS for mesh partitioning when available" ON)
|
|
16
|
+
# Automatic differentiation seeds one derivative slot per element node and
|
|
17
|
+
# variable, so the default of 48 covers, for example, Quad9 with five fields,
|
|
18
|
+
# Hex8 with six and Hex27 with one. Raise it for a multi-field problem on a
|
|
19
|
+
# Hex27 mesh; every ADReal grows with it, so raising it costs memory and
|
|
20
|
+
# assembly time everywhere.
|
|
21
|
+
set(DUALMESH_MAX_AD_DERIVATIVES 48 CACHE STRING
|
|
22
|
+
"Maximum seeded derivatives per element (nodes per element x variables)")
|
|
23
|
+
|
|
24
|
+
# ---- dependencies ---------------------------------------------------------
|
|
25
|
+
# Eigen is header-only. A system installation is used when there is one
|
|
26
|
+
# (macOS: `brew install eigen`; Debian/Ubuntu: `apt install libeigen3-dev`);
|
|
27
|
+
# otherwise the headers are downloaded into the build tree.
|
|
28
|
+
find_package(Eigen3 3.3 QUIET NO_MODULE)
|
|
29
|
+
if(NOT Eigen3_FOUND)
|
|
30
|
+
set(DUALMESH_EIGEN_VERSION 3.4.0)
|
|
31
|
+
set(DUALMESH_EIGEN_DIR ${CMAKE_BINARY_DIR}/_deps/eigen-${DUALMESH_EIGEN_VERSION})
|
|
32
|
+
if(NOT EXISTS ${DUALMESH_EIGEN_DIR}/Eigen/Dense)
|
|
33
|
+
set(DUALMESH_EIGEN_ARCHIVE ${CMAKE_BINARY_DIR}/_deps/eigen.tar.gz)
|
|
34
|
+
message(STATUS "Eigen not found; downloading Eigen ${DUALMESH_EIGEN_VERSION}")
|
|
35
|
+
file(DOWNLOAD
|
|
36
|
+
https://gitlab.com/libeigen/eigen/-/archive/${DUALMESH_EIGEN_VERSION}/eigen-${DUALMESH_EIGEN_VERSION}.tar.gz
|
|
37
|
+
${DUALMESH_EIGEN_ARCHIVE}
|
|
38
|
+
EXPECTED_HASH SHA256=8586084f71f9bde545ee7fa6d00288b264a2b7ac3607b974e54d13e7162c1c72
|
|
39
|
+
STATUS DUALMESH_EIGEN_DOWNLOAD)
|
|
40
|
+
list(GET DUALMESH_EIGEN_DOWNLOAD 0 DUALMESH_EIGEN_DOWNLOAD_CODE)
|
|
41
|
+
if(NOT DUALMESH_EIGEN_DOWNLOAD_CODE EQUAL 0)
|
|
42
|
+
list(GET DUALMESH_EIGEN_DOWNLOAD 1 DUALMESH_EIGEN_DOWNLOAD_MESSAGE)
|
|
43
|
+
message(FATAL_ERROR
|
|
44
|
+
"Could not download Eigen (${DUALMESH_EIGEN_DOWNLOAD_MESSAGE}).\n"
|
|
45
|
+
"Install it instead — 'brew install eigen' on macOS, "
|
|
46
|
+
"'apt install libeigen3-dev' on Debian or Ubuntu — or point CMake at an "
|
|
47
|
+
"existing copy with -DEigen3_DIR=<path to the Eigen3 CMake package>.")
|
|
48
|
+
endif()
|
|
49
|
+
file(ARCHIVE_EXTRACT INPUT ${DUALMESH_EIGEN_ARCHIVE}
|
|
50
|
+
DESTINATION ${CMAKE_BINARY_DIR}/_deps)
|
|
51
|
+
endif()
|
|
52
|
+
add_library(Eigen3::Eigen INTERFACE IMPORTED)
|
|
53
|
+
set_target_properties(Eigen3::Eigen PROPERTIES
|
|
54
|
+
INTERFACE_INCLUDE_DIRECTORIES ${DUALMESH_EIGEN_DIR})
|
|
55
|
+
endif()
|
|
56
|
+
|
|
57
|
+
# ---- optional parallel dependencies ------------------------------------------
|
|
58
|
+
# OpenMP threads the element assembly loop; it is optional, and without it the
|
|
59
|
+
# library builds and runs exactly as before, on one thread.
|
|
60
|
+
if(DUALMESH_ENABLE_OPENMP)
|
|
61
|
+
find_package(OpenMP COMPONENTS CXX QUIET)
|
|
62
|
+
if(NOT OpenMP_CXX_FOUND)
|
|
63
|
+
message(STATUS "OpenMP not found; the assembly will run on one thread")
|
|
64
|
+
endif()
|
|
65
|
+
endif()
|
|
66
|
+
|
|
67
|
+
# METIS gives better partitions than the built-in geometric partitioner for
|
|
68
|
+
# unstructured meshes. It is what libMesh, and therefore MOOSE, uses.
|
|
69
|
+
if(DUALMESH_ENABLE_METIS)
|
|
70
|
+
find_path(METIS_INCLUDE_DIR metis.h)
|
|
71
|
+
find_library(METIS_LIBRARY NAMES metis)
|
|
72
|
+
if(METIS_INCLUDE_DIR AND METIS_LIBRARY)
|
|
73
|
+
message(STATUS "METIS found: ${METIS_LIBRARY}")
|
|
74
|
+
else()
|
|
75
|
+
message(STATUS "METIS not found; using the built-in mesh partitioners")
|
|
76
|
+
endif()
|
|
77
|
+
endif()
|
|
78
|
+
|
|
79
|
+
if(DUALMESH_ENABLE_MPI)
|
|
80
|
+
find_package(MPI COMPONENTS CXX REQUIRED)
|
|
81
|
+
endif()
|
|
82
|
+
|
|
83
|
+
# ---- core library ------------------------------------------------------------
|
|
84
|
+
file(GLOB_RECURSE DUALMESH_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/*.cpp)
|
|
85
|
+
add_library(dualmesh_core STATIC ${DUALMESH_SOURCES})
|
|
86
|
+
target_include_directories(dualmesh_core PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
|
87
|
+
target_link_libraries(dualmesh_core PUBLIC Eigen3::Eigen)
|
|
88
|
+
target_compile_definitions(dualmesh_core
|
|
89
|
+
PUBLIC DUALMESH_MAX_AD_DERIVATIVES=${DUALMESH_MAX_AD_DERIVATIVES})
|
|
90
|
+
if(MSVC)
|
|
91
|
+
target_compile_options(dualmesh_core PRIVATE /W3 /bigobj)
|
|
92
|
+
target_compile_definitions(dualmesh_core PUBLIC _USE_MATH_DEFINES)
|
|
93
|
+
else()
|
|
94
|
+
target_compile_options(dualmesh_core PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
|
95
|
+
endif()
|
|
96
|
+
if(DUALMESH_ENABLE_OPENMP AND OpenMP_CXX_FOUND)
|
|
97
|
+
target_link_libraries(dualmesh_core PUBLIC OpenMP::OpenMP_CXX)
|
|
98
|
+
endif()
|
|
99
|
+
if(DUALMESH_ENABLE_METIS AND METIS_INCLUDE_DIR AND METIS_LIBRARY)
|
|
100
|
+
target_include_directories(dualmesh_core PRIVATE ${METIS_INCLUDE_DIR})
|
|
101
|
+
target_link_libraries(dualmesh_core PRIVATE ${METIS_LIBRARY})
|
|
102
|
+
target_compile_definitions(dualmesh_core PRIVATE DUALMESH_HAVE_METIS)
|
|
103
|
+
endif()
|
|
104
|
+
if(DUALMESH_ENABLE_MPI)
|
|
105
|
+
target_link_libraries(dualmesh_core PUBLIC MPI::MPI_CXX)
|
|
106
|
+
target_compile_definitions(dualmesh_core PUBLIC DUALMESH_HAVE_MPI)
|
|
107
|
+
endif()
|
|
108
|
+
|
|
109
|
+
# ---- command-line driver --------------------------------------------------------
|
|
110
|
+
# (the Python package provides the full input-file driver: `dualmesh run input.yaml`)
|
|
111
|
+
|
|
112
|
+
# ---- tests ---------------------------------------------------------------------
|
|
113
|
+
if(DUALMESH_BUILD_TESTS)
|
|
114
|
+
enable_testing()
|
|
115
|
+
add_executable(dualmesh_unit_tests tests/cpp/unit_tests.cpp)
|
|
116
|
+
target_link_libraries(dualmesh_unit_tests PRIVATE dualmesh_core)
|
|
117
|
+
add_test(NAME unit_tests COMMAND dualmesh_unit_tests)
|
|
118
|
+
add_executable(dualmesh_benchmark tests/cpp/benchmark.cpp)
|
|
119
|
+
target_link_libraries(dualmesh_benchmark PRIVATE dualmesh_core)
|
|
120
|
+
add_executable(dualmesh_parallel_tests tests/cpp/parallel_tests.cpp)
|
|
121
|
+
target_link_libraries(dualmesh_parallel_tests PRIVATE dualmesh_core)
|
|
122
|
+
add_test(NAME parallel_tests COMMAND dualmesh_parallel_tests)
|
|
123
|
+
endif()
|
|
124
|
+
|
|
125
|
+
# ---- Python module ---------------------------------------------------------------
|
|
126
|
+
if(DUALMESH_BUILD_PYTHON)
|
|
127
|
+
find_package(Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
|
128
|
+
find_package(pybind11 CONFIG QUIET)
|
|
129
|
+
if(NOT pybind11_FOUND)
|
|
130
|
+
execute_process(COMMAND ${Python_EXECUTABLE} -m pybind11 --cmakedir
|
|
131
|
+
OUTPUT_VARIABLE pybind11_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
132
|
+
find_package(pybind11 CONFIG REQUIRED)
|
|
133
|
+
endif()
|
|
134
|
+
pybind11_add_module(_core MODULE python/bindings/module.cpp)
|
|
135
|
+
target_link_libraries(_core PRIVATE dualmesh_core)
|
|
136
|
+
if(SKBUILD)
|
|
137
|
+
install(TARGETS _core LIBRARY DESTINATION dualmesh)
|
|
138
|
+
else()
|
|
139
|
+
set_target_properties(_core PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/python/dualmesh)
|
|
140
|
+
endif()
|
|
141
|
+
endif()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Contributing to dualmesh
|
|
2
|
+
|
|
3
|
+
Thank you for considering a contribution. This document explains how to build
|
|
4
|
+
the project, what is expected of a change, and how the code is organized.
|
|
5
|
+
|
|
6
|
+
## Building and testing
|
|
7
|
+
|
|
8
|
+
```console
|
|
9
|
+
git clone https://github.com/MohamedAbdulHameed/dualmesh.git
|
|
10
|
+
cd dualmesh
|
|
11
|
+
pip install -e .[all,test]
|
|
12
|
+
|
|
13
|
+
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
|
14
|
+
cmake --build build -j
|
|
15
|
+
ctest --test-dir build --output-on-failure # C++ unit tests
|
|
16
|
+
pytest # verification suite
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`cmake --build` also places the Python extension in `python/dualmesh`, so
|
|
20
|
+
`PYTHONPATH=$PWD/python` is enough to use the package from a source tree.
|
|
21
|
+
|
|
22
|
+
## What a change should include
|
|
23
|
+
|
|
24
|
+
- **Tests.** New physics needs a verification case with a reference value that
|
|
25
|
+
comes from somewhere trustworthy: a published table (cite it in a comment,
|
|
26
|
+
as the existing tests do), an analytical solution, or a convergence study.
|
|
27
|
+
Bug fixes need a test that fails before the fix.
|
|
28
|
+
- **Documentation.** New objects are documented by their own parameter
|
|
29
|
+
descriptions (`addRequired`/`addOptional` and `setClassDescription`), which
|
|
30
|
+
is what `dualmesh describe` and the object reference in the documentation
|
|
31
|
+
print. Anything conceptually new belongs in `docs/theory.rst` as well.
|
|
32
|
+
- **A note in `CHANGELOG.md`** under "Unreleased".
|
|
33
|
+
|
|
34
|
+
## Style
|
|
35
|
+
|
|
36
|
+
- C++ follows the MOOSE conventions: two-space indentation, `_member`
|
|
37
|
+
variables, `camelCase` functions, `PascalCase` types, `.clang-format` in the
|
|
38
|
+
repository root (`clang-format -i` before committing).
|
|
39
|
+
- Python follows PEP 8 with descriptive, unabbreviated names: `num_elements`,
|
|
40
|
+
`thermal_conductivity`, `transverse_displacement` — not `ne`, `k`, `w`.
|
|
41
|
+
`ruff check python tests` and `ruff format` are configured in
|
|
42
|
+
`pyproject.toml`.
|
|
43
|
+
- Parameter names in `validParams` are the user interface: spell them out, and
|
|
44
|
+
give each one a sentence that explains what it means physically.
|
|
45
|
+
|
|
46
|
+
## Adding physics
|
|
47
|
+
|
|
48
|
+
A kernel supplies a flux, a source, or both, for the canonical form
|
|
49
|
+
`-div F + S = 0`; see `docs/developing.rst` for a worked example and for how
|
|
50
|
+
registration works. Prototyping in Python (`dm.PythonKernel`) is encouraged:
|
|
51
|
+
the interface is the same, so a model that works can be moved to C++ almost
|
|
52
|
+
unchanged.
|
|
53
|
+
|
|
54
|
+
## Reporting problems
|
|
55
|
+
|
|
56
|
+
Please open an issue with the smallest input that reproduces the behaviour, the
|
|
57
|
+
version (`python -c "import dualmesh; print(dualmesh.__version__)"`), and the
|
|
58
|
+
platform. A failing test case is the most useful bug report of all.
|
|
59
|
+
|
|
60
|
+
## Licence
|
|
61
|
+
|
|
62
|
+
Contributions are accepted under the LGPL-2.1-or-later licence of the project.
|