Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ testing](https://github.com/alucantonio/dctkit/actions/workflows/tests.yml/badge
[![Docs](https://readthedocs.org/projects/dctkit/badge/?version=latest)](https://dctkit.readthedocs.io/en/latest/?badge=latest)

`dctkit` implements operators from Algebraic Topology, Discrete Exterior Calculus and
Discrete Differential Geometry to provide a *mathematical language for building discrete physical models*.
Discrete Differential Geometry to provide a _mathematical language for building discrete physical models_.

Features:

- uses [`jax`](http://github.com/google/jax/) as a backend for numerical computations
- manipulation of simplicial complexes of any dimension: computation of
boundary/coboundary operators, circumcenters, dual/primal volumes
Expand Down Expand Up @@ -60,14 +61,15 @@ Running the benchmarks:
```bash
$ sh ./bench/run_bench
```

The Markdown file `bench_results.md` will be generated containing the results.

## Usage

Read the full [documentation](https://dctkit.readthedocs.io/en/latest/) (including API
docs).

*Example*: solving discrete Poisson equation in 1D (variational formulation):
_Example_: solving discrete Poisson equation in 1D (variational formulation):

```python
import dctkit as dt
Expand Down Expand Up @@ -120,4 +122,15 @@ x = prb.solve(x0=u)
x = jnp.insert(x, 0, 0.)

plot(x)
```
```

## Repositories using dctkit

The following projects leverage dctkit as their discrete calculus toolkit. If you have a project you would like to showcase, please submit a pull request with your repository details to be included in this list.

- [SR-DEC_Examples](https://github.com/cpml-au/SR-DEC_Examples): benchmarks for symbolic regression paired with discrete exterior calculus.
- [SR-Traffic](https://github.com/cpml-au/SR-Traffic): symbolic regression of fundamental diagrams of first-order traffic flow models.

## Acknowledgements

This work is supported by the European Union (European Research Council (ERC), ALPS, 101039481). Views and opinions expressed are however those of the author(s) only and do not necessarily reflect those of the European Union or the ERC Executive Agency. Neither the European Union nor the granting authority can be held responsible for them.
2 changes: 1 addition & 1 deletion docs/tutorials/burgers.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "4c410dec-b7eb-48f6-b0d1-1d77ffcdbf96",
"metadata": {},
"source": [
"# 1D Burgers equation"
"# Burgers equation"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/elastica.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "29896764-6d44-4af7-b98e-1259562e0097",
"metadata": {},
"source": [
"# 1D Euler's Elastica"
"# Euler's Elastica"
]
},
{
Expand Down
176 changes: 7 additions & 169 deletions docs/tutorials/poisson.ipynb

Large diffs are not rendered by default.

214 changes: 214 additions & 0 deletions examples/diffusion.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "61f00f5e",
"metadata": {},
"source": [
"# 3D Diffusion Equation"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e756452c",
"metadata": {},
"outputs": [],
"source": [
"import pyvista as pv\n",
"from pyvista import themes\n",
"import numpy as np\n",
"from dctkit.mesh import util\n",
"import dctkit as dt\n",
"from dctkit.dec import cochain as C\n",
"from dctkit.physics.poisson import energy_poisson\n",
"from dctkit.math.opt import optctrl as oc\n",
"from functools import partial"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "618c4c94",
"metadata": {},
"outputs": [],
"source": [
"dt.config()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "377b6820",
"metadata": {},
"outputs": [],
"source": [
"#pv.set_jupyter_backend('trame')\n",
"pv.global_theme = themes.ParaViewTheme()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "862c1ce6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"number of nodes = 234\n",
"number of tets = 709\n"
]
}
],
"source": [
"lc = 0.2\n",
"mesh, _ = util.generate_cube_mesh(lc)\n",
"#pv.plot(mesh)\n",
"S = util.build_complex_from_mesh(mesh)\n",
"num_nodes = S.num_nodes\n",
"print(\"number of nodes = \", num_nodes)\n",
"print(\"number of tets = \", S.S[3].shape[0])\n",
"S.get_hodge_star()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "cc79f03a",
"metadata": {},
"outputs": [],
"source": [
"# boundary conditions\n",
"bottom_nodes = np.argwhere(S.node_coords[:,2]<1e-6).flatten()\n",
"top_nodes = np.argwhere(abs(S.node_coords[:,2]-1.)<1e-6).flatten()\n",
"values = np.zeros(len(bottom_nodes)+len(top_nodes), dtype=dt.float_dtype)\n",
"boundary_values = (np.hstack((bottom_nodes,top_nodes)), values)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "bf979121",
"metadata": {},
"outputs": [],
"source": [
"def disspot(u, u_prev, deltat):\n",
" u_coch = C.CochainP0(S, u)\n",
" u_prev_coch = C.CochainP0(S, u_prev)\n",
" u_diff = C.sub(u_coch, u_prev_coch)\n",
" return (1/2)*C.inner(u_diff, u_diff)/deltat\n",
"\n",
"energy = partial(energy_poisson, S=S)\n",
"\n",
"def obj(u, u_prev, f, k, boundary_values, gamma, deltat):\n",
" en = energy(x=u, f=f, k=k, boundary_values=boundary_values, gamma=gamma)\n",
" return en + disspot(u, u_prev, deltat)\n",
"\n",
"k = 1.\n",
"f_vec = np.ones(num_nodes, dtype=dt.float_dtype)\n",
"gamma = 1000.\n",
"deltat = 0.05\n",
"\n",
"u_0 = np.zeros(num_nodes, dt.float_dtype)\n",
"u_prev = u_0"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "d21860f9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"t = 0.05\n",
"t = 0.1\n",
"t = 0.15000000000000002\n",
"t = 0.2\n",
"t = 0.25\n",
"t = 0.30000000000000004\n",
"t = 0.35000000000000003\n",
"t = 0.4\n",
"t = 0.45\n",
"t = 0.5\n"
]
},
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sols = []\n",
"prb = oc.OptimizationProblem(dim=num_nodes, state_dim=num_nodes, objfun=obj)\n",
"for i in range(10):\n",
" print(\"t = \", (i+1)*deltat)\n",
" args = {'u_prev': u_prev, 'f': f_vec, 'k': k, 'boundary_values': boundary_values,\n",
" 'gamma': gamma, 'deltat': deltat}\n",
" prb.set_obj_args(args)\n",
" u = prb.solve(u_prev, ftol_abs=1e-8, ftol_rel=1e-8)\n",
" u_prev = u.__array__()\n",
" sols.append(u)\n",
"prb.last_opt_result"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "7c396075",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1495cd1c49e0441890cbca2d783d3920",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Widget(value='<iframe src=\"http://localhost:41085/index.html?ui=P_0x729f90334910_1&reconnect=auto\" class=\"pyvi…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"p = pv.Plotter()\n",
"p.add_mesh(mesh, scalars=sols[-1])\n",
"p.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "dctkit_test",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading