|
1 | 1 | [{: style="width:200px;float: right;" }](https://fenicsproject.org/)
|
2 |
| -[FEniCS](https://fenicsproject.org/) is a popular open-source (LGPLv3) computing platform for |
3 |
| -solving partial differential equations (PDEs). |
4 |
| -FEniCS enables users to quickly translate scientific models |
5 |
| -into efficient finite element code. With the high-level |
6 |
| -Python and C++ interfaces to FEniCS, it is easy to get started, |
7 |
| -but FEniCS offers also powerful capabilities for more |
8 |
| -experienced programmers. FEniCS runs on a multitude of |
9 |
| -platforms ranging from laptops to high-performance clusters. |
10 |
| - |
11 |
| -## How to access the FEniCS through [Anaconda](https://www.anaconda.com/products/individual) |
12 |
| -The following steps provides information about how to installed |
13 |
| -on your local path. |
14 |
| -```bash |
15 |
| -# From your local computer |
16 |
| -$ ssh -X iris-cluster # OR ssh -Y iris-cluster on Mac |
17 | 2 |
|
18 |
| -# Reserve the node for interactive computation with grahics view (plots) |
19 |
| -$ si --x11 --ntasks-per-node 1 -c 4 |
20 |
| -# salloc -p interactive --qos debug -C batch --x11 --ntasks-per-node 1 -c 4 |
| 3 | +<!-- Intro start --> |
21 | 4 |
|
22 |
| -# Go to scratch directory |
23 |
| -$ cds |
| 5 | +[FEniCS](https://fenicsproject.org/) is a popular open-source computing platform for solving partial differential equations (PDEs) using the finite element method ([FEM](https://en.wikipedia.org/wiki/Finite_element_method)). Originally developed in 2003, the earlier version is now known as legacy FEniCS. In 2020, the next-generation framework [FEniCSx](https://docs.fenicsproject.org/) was introduced, with the latest stable [release v0.9.0](https://fenicsproject.org/blog/v0.9.0/) in October 2024. Though it builds on the legacy FEniCS but introduces significant improvements over the legacy libraries. FEniCSx is comprised of the libraries [UFL](https://github.com/FEniCS/ufl), [Basix](https://github.com/FEniCS/basix), [FFCx](https://github.com/FEniCS/ffcx), and [DOLFINx](https://github.com/FEniCS/dolfinx) which are the build blocks of it. And new users are encouraged to adopt [FEniCSx](https://docs.fenicsproject.org/) for its modern features and active development support. |
24 | 6 |
|
25 |
| -/scratch/users/<login> $ Anaconda3-2020.07-Linux-x86_64.sh |
26 |
| -/scratch/users/<login> $ chmod +x Anaconda3-2020.07-Linux-x86_64.sh |
27 |
| -/scratch/users/<login> $ ./Anaconda3-2020.07-Linux-x86_64.sh |
28 | 7 |
|
29 |
| -Do you accept the license terms? [yes|no] |
30 |
| -yes |
31 |
| -Anaconda3 will now be installed into this location: |
32 |
| -/home/users/<login>/anaconda3 |
| 8 | +<!-- // Tutorials: https://jsdokken.com/dolfinx-tutorial/index.html --> |
33 | 9 |
|
34 |
| - - Press ENTER to confirm the location |
35 |
| - - Press CTRL-C to abort the installation |
36 |
| - - Or specify a different location below |
37 | 10 |
|
38 |
| -# You can choose your path where you want to install it |
39 |
| -[/home/users/<login>/anaconda3] >>> /scratch/users/<login>/Anaconda3 |
| 11 | +<!-- Intro end --> |
40 | 12 |
|
41 |
| -# To activate the anaconda |
42 |
| -/scratch/users/<login> $ source /scratch/users/<login>/Anaconda3/bin/activate |
| 13 | +## Installation of FEniCSx |
43 | 14 |
|
44 |
| -# Install the fenics in anaconda environment |
45 |
| -/scratch/users/<login> $ conda create -n fenicsproject -c conda-forge fenics |
| 15 | +FEniCSx can be installed on [ULHPC](https://www.uni.lu/research-en/core-facilities/hpc/) systems using [Easybuild](https://docs.easybuild.io) or [Spack](https://spack.io/), Below are detailed instructions for each method, |
46 | 16 |
|
47 |
| -# Install matplotlib for the visualization |
48 |
| -/scratch/users/<login> $ conda install -c conda-forge matplotlib |
49 |
| -``` |
50 |
| -Once you have installed the anaconda, you can always |
51 |
| -activate it by calling the `source activate` path where `anaconda` |
52 |
| -has been installed. |
53 | 17 |
|
54 |
| -## Working example |
55 |
| -### Interactive mode |
56 |
| -```bash |
57 |
| -# From your local computer |
58 |
| -$ ssh -X iris-cluster # or ssh -Y iris-cluster on Mac |
59 | 18 |
|
60 |
| -# Reserve the node for interactive computation with grahics view (plots) |
61 |
| -$ si --ntasks-per-node 1 -c 4 --x11 |
62 |
| -# salloc -p interactive --qos debug -C batch --x11 --ntasks-per-node 1 -c 4 |
| 19 | +### Building FEniCS With Spack |
63 | 20 |
|
64 |
| -# Activate anaconda |
65 |
| -$ source /${SCRATCH}/Anaconda3/bin/activate |
66 | 21 |
|
67 |
| -# activate the fenicsproject |
68 |
| -$ conda activate fenicsproject |
| 22 | +Building FEniCSx with Spack requires that Spack is already installed, configured, and its environment sourced on the [ULHPC] system. If Spack is not yet configured, follow the [spack documentation](../../environment/spack.md) for installation and configuration. |
69 | 23 |
|
70 |
| -# execute the Poisson.py example (you can uncomment the plot lines in Poission.py example) |
71 |
| -$ python3 Poisson.py |
72 |
| -``` |
| 24 | +!!! note |
| 25 | + Spack can a good choice to build FEniCSx with its many complex dependencies, leveraging the system-provided packages defined in ~/.spack/packages.yaml for optimal performance. |
| 26 | + |
| 27 | +Create and Activate a Spack Environment: |
| 28 | + |
| 29 | +To maintain an isolated installation, create a dedicated Spack environment in a chosen directory. |
| 30 | +The following example builds FEniCSx in the `home` directory: |
| 31 | + |
| 32 | + cd ~ |
| 33 | + spack env create -d fenicsx-main-20230126/ |
| 34 | + spack env activate fenicsx-main-20230126/ |
| 35 | + |
| 36 | + |
| 37 | +Add the core FEniCSx components and common dependencies: |
| 38 | + |
| 39 | + spack add py-fenics-dolfinx@0.9.0+petsc4py fenics-dolfinx+adios2+petsc adios2+python petsc+mumps |
| 40 | + |
| 41 | + # Change @0.9.0 to any version in the above if you want a another version. |
| 42 | + spack concretize |
| 43 | + spack install -j16 |
| 44 | + |
| 45 | + |
| 46 | +!!! note |
| 47 | + |
| 48 | + `spack concretize` resolves all dependencies and selects compatible versions for the specified packages. `-j16` sets the number of parallel build jobs. Using a higher number can speed up the build but should be chosen based on available CPU cores and cluster policies. |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +or the same directly in `spack.yaml` in `$SPACK_ENV` |
| 53 | + |
| 54 | + spack: |
| 55 | + # add package specs to the `specs` list |
| 56 | + specs: |
| 57 | + - py-fenics-dolfinx@0.9.0+petsc4py |
| 58 | + - fenics-dolfinx+adios2+petsc |
| 59 | + - petsc+mumps |
| 60 | + - adios2+python |
| 61 | + |
| 62 | + view: true |
| 63 | + concretizer: |
| 64 | + unify: true |
| 65 | + |
| 66 | +The following are also commonly used in FEniCS scripts and may be useful |
| 67 | + |
| 68 | + spack add gmsh+opencascade py-numba py-scipy py-matplotlib |
| 69 | + |
| 70 | +It is possible to build a specific version (git ref) of DOLFINx. |
| 71 | +Note that the hash must be the full hash. |
| 72 | +It is best to specify appropriate git refs on all components. |
| 73 | + |
| 74 | + # This is a Spack Environment file. |
| 75 | + # |
| 76 | + # It describes a set of packages to be installed, along with |
| 77 | + # configuration settings. |
| 78 | + spack: |
| 79 | + # add package specs to the `specs` list |
| 80 | + specs: |
| 81 | + - fenics-dolfinx@git.4f575964c70efd02dca92f2cf10c125071b17e4d=main+adios2 |
| 82 | + - py-fenics-dolfinx@git.4f575964c70efd02dca92f2cf10c125071b17e4d=main |
| 83 | + |
| 84 | + - py-fenics-basix@git.2e2a7048ea5f4255c22af18af3b828036f1c8b50=main |
| 85 | + - fenics-basix@git.2e2a7048ea5f4255c22af18af3b828036f1c8b50=main |
| 86 | + |
| 87 | + - py-fenics-ufl@git.b15d8d3fdfea5ad6fe78531ec4ce6059cafeaa89=main |
| 88 | + |
| 89 | + - py-fenics-ffcx@git.7bc8be738997e7ce68ef0f406eab63c00d467092=main |
| 90 | + |
| 91 | + - fenics-ufcx@git.7bc8be738997e7ce68ef0f406eab63c00d467092=main |
| 92 | + |
| 93 | + - petsc+mumps |
| 94 | + - adios2+python |
| 95 | + view: true |
| 96 | + concretizer: |
| 97 | + unify: true |
| 98 | + |
| 99 | +It is also possible to build only the C++ layer using |
| 100 | + |
| 101 | + spack add fenics-dolfinx@main+adios2 py-fenics-ffcx@main petsc+mumps |
| 102 | + |
| 103 | +To rebuild FEniCSx from main branches inside an existing environment |
| 104 | + |
| 105 | + spack install --overwrite -j16 fenics-basix py-fenics-basix py-fenics-ffcx fenics-ufcx py-fenics-ufl fenics-dolfinx py-fenics-dolfinx |
| 106 | + |
| 107 | +#### Testing the build |
| 108 | + |
| 109 | +Quickly test the build with |
| 110 | + |
| 111 | + srun python -c "from mpi4py import MPI; import dolfinx" |
| 112 | + |
| 113 | +#### Using the build |
| 114 | + |
| 115 | +See the uni.lu documentation for full details - using the environment should be as |
| 116 | +simple as adding the following where `...` is the name/folder of your environment. |
| 117 | + |
| 118 | + #!/bin/bash -l |
| 119 | + source $HOME/spack/share/spack/setup-env.sh |
| 120 | + spack env activate ... |
| 121 | + |
| 122 | +#### Known issues |
| 123 | + |
| 124 | +Workaround for inability to find gmsh Python package: |
| 125 | + |
| 126 | + export PYTHONPATH=$SPACK_ENV/.spack-env/view/lib64/:$PYTHONPATH |
| 127 | + |
| 128 | +Workaround for inability to find adios2 Python package: |
| 129 | + |
| 130 | + export PYTHONPATH=$(find $SPACK_ENV/.spack-env -type d -name 'site-packages' | grep venv):$PYTHONPATH |
| 131 | + |
| 132 | + |
| 133 | +### Building FEniCS With EasyBuild |
73 | 134 |
|
74 |
| -### Batch script |
75 |
| -```bash |
76 |
| -#!/bin/bash -l |
77 |
| -#SBATCH -J FEniCS |
78 |
| -#SBATCH -N 1 |
79 |
| -###SBATCH -A <project name> |
80 |
| -###SBATCH --ntasks-per-node=1 |
81 |
| -#SBATCH -c 1 |
82 |
| -#SBATCH --time=00:05:00 |
83 |
| -#SBATCH -p batch |
84 |
| - |
85 |
| -echo "== Starting run at $(date)" |
86 |
| -echo "== Job ID: ${SLURM_JOBID}" |
87 |
| -echo "== Node list: ${SLURM_NODELIST}" |
88 |
| -echo "== Submit dir. : ${SLURM_SUBMIT_DIR}" |
89 |
| - |
90 |
| -# activate the anaconda source |
91 |
| -source ${SCRATCH}/Anaconda3/bin/activate |
92 |
| - |
93 |
| -# activate the fenicsproject from anaconda |
94 |
| -conda activate fenicsproject |
95 |
| - |
96 |
| -# execute the poisson.py through python |
97 |
| -srun python3 Poisson.py |
98 |
| -``` |
99 | 135 |
|
100 | 136 | ### Example (Poisson.py)
|
101 | 137 | ```bash
|
102 |
| -# FEniCS tutorial demo program: Poisson equation with Dirichlet conditions. |
103 |
| -# Test problem is chosen to give an exact solution at all nodes of the mesh. |
104 |
| -# -Laplace(u) = f in the unit square |
105 |
| -# u = u_D on the boundary |
106 |
| -# u_D = 1 + x^2 + 2y^2 |
107 |
| -# f = -6 |
108 |
| - |
109 |
| -from __future__ import print_function |
110 |
| -from fenics import * |
111 |
| -import matplotlib.pyplot as plt |
112 |
| - |
113 |
| -# Create mesh and define function space |
114 |
| -mesh = UnitSquareMesh(8, 8) |
115 |
| -V = FunctionSpace(mesh, 'P', 1) |
116 |
| - |
117 |
| -# Define boundary condition |
118 |
| -u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2) |
119 |
| - |
120 |
| -def boundary(x, on_boundary): |
121 |
| - return on_boundary |
122 |
| - |
123 |
| -bc = DirichletBC(V, u_D, boundary) |
124 |
| - |
125 |
| -# Define variational problem |
126 |
| -u = TrialFunction(V) |
127 |
| -v = TestFunction(V) |
128 |
| -f = Constant(-6.0) |
129 |
| -a = dot(grad(u), grad(v))*dx |
130 |
| -L = f*v*dx |
131 |
| - |
132 |
| -# Compute solution |
133 |
| -u = Function(V) |
134 |
| -solve(a == L, u, bc) |
135 |
| - |
136 |
| -# Plot solution and mesh |
137 |
| -#plot(u) |
138 |
| -#plot(mesh) |
139 |
| - |
140 |
| -# Save solution to file in VTK format |
141 |
| -vtkfile = File('poisson/solution.pvd') |
142 |
| -vtkfile << u |
143 |
| -
|
144 |
| -# Compute error in L2 norm |
145 |
| -error_L2 = errornorm(u_D, u, 'L2') |
146 |
| -
|
147 |
| -# Compute maximum error at vertices |
148 |
| -vertex_values_u_D = u_D.compute_vertex_values(mesh) |
149 |
| -vertex_values_u = u.compute_vertex_values(mesh) |
| 138 | + |
| 139 | +# Demo possion problem |
| 140 | +# https://docs.fenicsproject.org/dolfinx/main/python/demos/demo_poisson.html |
| 141 | + |
| 142 | +from mpi4py import MPI |
| 143 | +from petsc4py.PETSc import ScalarType |
| 144 | + |
150 | 145 | import numpy as np
|
151 |
| -error_max = np.max(np.abs(vertex_values_u_D - vertex_values_u)) |
152 | 146 |
|
153 |
| -# Print errors |
154 |
| -print('error_L2 =', error_L2) |
155 |
| -print('error_max =', error_max) |
| 147 | +import ufl |
| 148 | +from dolfinx import fem, mesh |
| 149 | +from dolfinx.fem.petsc import LinearProblem |
| 150 | + |
| 151 | +# Create mesh |
| 152 | +msh = mesh.create_rectangle( |
| 153 | + comm=MPI.COMM_WORLD, |
| 154 | + points=((0.0, 0.0), (2.0, 1.0)), |
| 155 | + n=(32, 16), |
| 156 | + cell_type=mesh.CellType.triangle, |
| 157 | +) |
| 158 | + |
| 159 | +# Function space |
| 160 | +V = fem.functionspace(msh, ("Lagrange", 1)) |
| 161 | + |
| 162 | +# Boundary facets (x=0 and x=2) |
| 163 | +facets = mesh.locate_entities_boundary( |
| 164 | + msh, |
| 165 | + dim=(msh.topology.dim - 1), |
| 166 | + marker=lambda x: np.isclose(x[0], 0.0) | np.isclose(x[0], 2.0), |
| 167 | +) |
| 168 | +dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets) |
| 169 | + |
| 170 | +# Dirichlet BC u = 0 |
| 171 | +bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V) |
| 172 | + |
| 173 | +# Variational problem |
| 174 | +u = ufl.TrialFunction(V) |
| 175 | +v = ufl.TestFunction(V) |
| 176 | +x = ufl.SpatialCoordinate(msh) |
| 177 | +f = 10 * ufl.exp(-((x[0] - 0.5) ** 2 + (x[1] - 0.5) ** 2) / 0.02) |
| 178 | +g = ufl.sin(5 * x[0]) |
| 179 | +a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx |
| 180 | +L = ufl.inner(f, v) * ufl.dx + ufl.inner(g, v) * ufl.ds |
| 181 | + |
| 182 | +# Create problem (no petsc_options_prefix in 0.9.0) |
| 183 | +problem = LinearProblem( |
| 184 | + a, |
| 185 | + L, |
| 186 | + bcs=[bc], |
| 187 | + petsc_options={"ksp_type": "preonly", "pc_type": "lu", "ksp_error_if_not_converged": True}, |
| 188 | +) |
| 189 | + |
| 190 | +# Solve |
| 191 | +uh = problem.solve() |
| 192 | + |
| 193 | +# Only print from rank 0 to avoid MPI spam |
| 194 | +if MPI.COMM_WORLD.rank == 0: |
| 195 | + print("First 10 values of the solution vector:", uh.x.array[:10]) |
| 196 | + |
| 197 | +assert isinstance(uh, fem.Function) |
| 198 | + |
156 | 199 |
|
157 |
| -# Hold plot |
158 |
| -#plt.show() |
159 | 200 | ```
|
160 | 201 |
|
161 | 202 | ## Additional information
|
|
0 commit comments