Skip to content

Commit 3338840

Browse files
authored
Merge pull request #11 from underworldcode/development
Development - synchronise changes to documentation / JOSS
2 parents 6209bf5 + 74fb33b commit 3338840

35 files changed

Lines changed: 1674 additions & 760 deletions

docs/joss-paper/paper.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ Users of `underworld3` typically develop python scripts within `jupyter` noteboo
6767

6868
# Statement of need
6969

70+
Typical problems in geodynamics usually require computing material deformation, damage evolution, and interface tracking in the large-deformation limit. These are typically not well supported by standard engineering finite element simulation codes. Underworld is a python software framework that is intended to solve geodynamics problems that sit at the interface between computational fluid mechanics and solid mechanics (often known as *complex fluids*). It does so by putting Lagrangian and Eulerian variables on an equal footing at both the user and computational levels.
71+
7072
Underworld is built around a general, symbolic partial differential equation solver but provides template forms to solve common geophysical fluid dynamics problems such as the Stokes equation for mantle convection, subduction-zone evolution, lithospheric deformation, glacial isostatic adjustment, ice flow; Navier-Stokes equations for finite Prandtl number fluid flow and short-timescale, viscoelastic deformation; and Darcy Flow for porous media problems including groundwater flow and contaminant transport.
7173

7274
These problems have a number of defining characteristics: geomaterials are non-linear, viscoelastic/plastic and have a propensity for strain-dependent softening during deformation; strain localisation is very common as a consequence. Geological structures that we seek to understand are often emergent over the course of loading and are observed in the very-large deformation limit. Material properties have strong spatial gradients arising from pressure and temperature dependence and jumps of several orders of magnitude resulting from material interfaces.

docs/user/NextSteps.qmd

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ In addition to the notebooks in this brief set of examples, there are a number o
1616

1717
- [The Underworld Website / Blog](https://www.underworldcode.org)
1818

19-
- [The API documentation](https://underworldcode.github.io/underworld3/main_api/underworld3/index.html)
19+
- [The API documentation](https://underworldcode.github.io/underworld3/main_api/underworld3/index.html)
2020
(all the modules and functions and their full sets of arguments) is automatically generated from the source code and uses the same rich markdown content as the notebook help text.
2121

2222
- [The API documentation (development branch)](https://underworldcode.github.io/underworld3/development_api/underworld3/index.html)
@@ -46,6 +46,33 @@ Almost all of our notebook examples are annotated python for this reason.An exce
4646

4747
The main difference between the notebook development environment and HPC is the lack of interactivity, particularly in sending parameters to the script at launch time. Typically, we expect the HPC version to be running at much higher resolution, or for many more timesteps than the development notebook. We use the `PETSc` command line parsing machinery to generate notebooks that also can ingest run-time parameters from a script (as above).
4848

49+
#### Parallel scaling / performance
50+
51+
Running geodynamic models on a single CPU/processor (i.e. serial) is time-consuming and limits us to low resolution. Underworld is build from the ground-up as a parallel computing solution which means we can easily run large models on high performance computing clusters (HPC); that is, sub-divide the problem into many smaller chunks and use multiple processors to solve each one, taking care to combine and synchronise the answers from each processor to obtain the correct solution to the original problem.
52+
53+
Parallel computation can reduce time we need to wait for the our results to be computed but it does happen at the expense of some overhead The overhead does depend on the nature of the computer we are using but typically we need to think about:
54+
55+
- **Code complexity**: any time we manage computations across different processors, we have additional coding to reassemble the calculations correctly and we need to think about many special cases. For example, integrating a quantity of the surface of a mesh: many processes contribute, some do not, the results have to be computed independently then combined.
56+
57+
- **Additional memory is often required**: to manage copies of information that lives on / near boundaries, to store the topology of the decomposed domain and to help navigate the passing of information between processes.
58+
59+
- **The time taken to synchronise results** and the work required to keep track of who is doing what, when they are done, and in making sure everyone waits for everyone else. There is a time-cost in actually sending information as part of a synchronisation and a computational cost in ensuring that work is distributed efficiently.
60+
61+
To determine the efficiency of parallel computation, we introduce the *strong scaling test* which measures the time taken to solve a problem in parallel compared to the same problem solved in serial. In strong scaling tests, the size of the problem is kept constant, while the number of processors is increased. The reduction in run-time due to the addition of more processors is commonly expressed in terms of the speed-up:
62+
63+
$$
64+
\textrm{speed up} = \frac{t(N_{ref})}{t(N)}
65+
$$
66+
67+
where $t(N_{ref})$ is the run-time for a reference number of processors, $N_{ref}$, and $t(N)$ is the run-time when $N$ processors are used. In the ideal case, $N$ additional processors should contribute all of its resources in solving the problem and reduce the compute time by a factor of $N$ relative to the reference run time. For example, using $2 N_{ref}$ processors will ideally halve the run-time resulting to a speed-up = 2.
68+
69+
::: {#fig-strong-scaling}
70+
71+
![](media/UW3-StrongScalingSolvers.png)
72+
73+
Strong parallel-scaling tests run on Australia's peak computing system, [GADI, at the National Computational Infrastructure](https://nci.org.au/our-systems/hpc-systems?ref=underworldcode.org). This is a typical High Performance Computing facility with large numbers of dedicated, identical CPUs and fast communication links.
74+
:::
75+
4976

5077
### Advanced capabilities
5178

@@ -79,11 +106,11 @@ It is also possible to use the PETSc mesh adaption capabilities, to refine the r
79106

80107
```{=html}
81108
<center>
82-
<iframe src="media/pyvista/AdaptedSphere.html" width="600" height="300">
109+
<iframe src="media/pyvista/AdaptedSphere.html" width="600" height="500">
83110
</iframe>
84111
</center>
85112
```
86-
*Live Image: Static mesh adaptation to the slope of a field. The driving buoyancy term is three plume-like upwellings and the slope of this field is shown in colour (red high, blue low). The adapted mesh is shown in green.*
113+
*Live Image: Static mesh adaptation to the slope of a field. The driving buoyancy term is a plume-like upwelling and the slope of this field is shown in colour (red high, blue low). Don't forget to zoom in !*
87114

88115
```python
89116

docs/user/Notebooks/1-Meshes.ipynb

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,18 @@
1313
}
1414
},
1515
"source": [
16+
"\n",
17+
"# Notebook 1: Meshes\n",
18+
"\n",
1619
"<div style=\"float: right; width: 40%\">\n",
1720
" \n",
1821
"![](media/SampleSphericalMesh.png)\n",
1922
"\n",
2023
"</div>\n",
2124
"\n",
2225
"\n",
23-
"## Notebook 1: Meshes\n",
24-
"\n",
25-
"Introducing meshes: how to build them, interrogate them and visualise them.\n",
26-
"\n",
27-
" - `mesh.view()`\n",
28-
" - Mesh refinement options\n",
29-
" - Mesh coordinates\n",
30-
" - Mesh coordinate systems\n",
31-
" - Mesh deformation\n",
32-
"\n",
33-
"\n",
3426
"\n",
35-
"Mesh adaptivity is a work-in-progress.\n",
36-
"\n",
37-
"\n"
27+
"This notebookIntroduces the mesh discretisation that we use in `Underworld3` and how you can build one of the pre-defined meshes. This notebook also show you how to use the `pyvista` visualisation tools for `Underworld3` objects. The mesh holds information on the mesh geometry, boundaries and coordinate systems and you can attach data to the mesh (see Notebook 2: [Variables](2-Variables.ipynb)). \n"
3828
]
3929
},
4030
{
@@ -71,15 +61,7 @@
7161
},
7262
"tags": []
7363
},
74-
"outputs": [
75-
{
76-
"name": "stdout",
77-
"output_type": "stream",
78-
"text": [
79-
"PostHog telemetry failed: HTTPSConnectionPool(host='eu.i.posthog.com', port=443): Max retries exceeded with url: /capture/ (Caused by NameResolutionError(\"<urllib3.connection.HTTPSConnection object at 0x3049912b0>: Failed to resolve 'eu.i.posthog.com' ([Errno 8] nodename nor servname provided, or not known)\"))\n"
80-
]
81-
}
82-
],
64+
"outputs": [],
8365
"source": [
8466
"#| output: false # Suppress warnings in html version\n",
8567
"\n",
@@ -105,7 +87,7 @@
10587
},
10688
{
10789
"cell_type": "code",
108-
"execution_count": 22,
90+
"execution_count": 3,
10991
"id": "1c928d60-24a9-4415-ab22-41834695c70a",
11092
"metadata": {
11193
"editable": true,
@@ -157,7 +139,7 @@
157139
},
158140
{
159141
"cell_type": "code",
160-
"execution_count": 23,
142+
"execution_count": 4,
161143
"id": "b9cfac97-5c19-46b1-aebd-0fb77678b9ed",
162144
"metadata": {},
163145
"outputs": [
@@ -173,7 +155,7 @@
173155
" [ 0.51755571, 0.41031492, 0.44421012]])"
174156
]
175157
},
176-
"execution_count": 23,
158+
"execution_count": 4,
177159
"metadata": {},
178160
"output_type": "execute_result"
179161
}
@@ -232,7 +214,7 @@
232214
},
233215
{
234216
"cell_type": "code",
235-
"execution_count": 26,
217+
"execution_count": 5,
236218
"id": "1cb8378c-cdb8-4e75-bd12-e85f12169ef7",
237219
"metadata": {
238220
"editable": true,
@@ -266,7 +248,7 @@
266248
},
267249
{
268250
"cell_type": "code",
269-
"execution_count": 27,
251+
"execution_count": 6,
270252
"id": "fd6cbed0-3159-4c6c-a482-6a9636158854",
271253
"metadata": {
272254
"editable": true,
@@ -291,10 +273,10 @@
291273
" "
292274
],
293275
"text/plain": [
294-
"<IPython.lib.display.IFrame at 0x35f726660>"
276+
"<IPython.lib.display.IFrame at 0x33d867770>"
295277
]
296278
},
297-
"execution_count": 27,
279+
"execution_count": 6,
298280
"metadata": {},
299281
"output_type": "execute_result"
300282
}
@@ -406,19 +388,19 @@
406388
"text": [
407389
"\n",
408390
"\n",
409-
"Mesh # 0: .meshes/uw_cubed_spherical_shell_ro1.0_ri0.547_elts8_plexFalse.msh\n",
391+
"Mesh # 0: .meshes/uw_cubed_spherical_shell_ro1.0_ri0.547_elts8_plexTrue.msh\n",
410392
"\n"
411393
]
412394
},
413395
{
414396
"data": {
415397
"application/vnd.jupyter.widget-view+json": {
416-
"model_id": "f18b77ba1d8d44ae96a3832ea3ffa5a3",
398+
"model_id": "9b169322ec7d469e81893a05b2cbfffb",
417399
"version_major": 2,
418400
"version_minor": 0
419401
},
420402
"text/plain": [
421-
"Widget(value='<iframe src=\"http://localhost:50188/index.html?ui=P_0x307b3b5f0_1&reconnect=auto\" class=\"pyvista…"
403+
"Widget(value='<iframe src=\"http://localhost:58527/index.html?ui=P_0x33d89cf80_1&reconnect=auto\" class=\"pyvista…"
422404
]
423405
},
424406
"metadata": {},
@@ -428,28 +410,42 @@
428410
"name": "stdout",
429411
"output_type": "stream",
430412
"text": [
431-
"Number of cells: 3072\n",
413+
"Number of cells: 7615\n",
432414
"\n",
433415
"No variables are defined on the mesh\n",
434416
"\n",
435-
"| Boundary Name | ID |\n",
436-
"| -------------------------------- |\n",
437-
"| Lower | 1 |\n",
438-
"| Upper | 2 |\n",
439-
"| Null_Boundary | 666 |\n",
440-
"| All_Boundaries | 1001 |\n",
441-
"| All_Boundaries | 1001 |\n",
442-
"| UW_Boundaries | -- |\n",
443-
"| -------------------------------- |\n",
417+
"| Boundary Name | ID | Min Size | Max Size |\n",
418+
"| ------------------------------------------------------ |\n",
419+
"| Lower | 1 | 1062 | 1062 |\n",
420+
"| Upper | 2 | 1062 | 1062 |\n",
421+
"| Null_Boundary | 666 | 1672 | 1672 |\n",
422+
"| All_Boundaries | 1001 | 1536 | 1536 |\n",
423+
"| All_Boundaries | 1001 | 1536 | 1536 |\n",
424+
"| UW_Boundaries | -- | 5332 | 5332 |\n",
425+
"| ------------------------------------------------------ |\n",
444426
"\n",
445427
"\n",
446-
"Use view(1) to view detailed mesh information.\n",
447-
"\n"
428+
"DM Object: uw_.meshes/uw_cubed_spherical_shell_ro1.0_ri0.547_elts8_plexTrue.msh 1 MPI process\n",
429+
" type: plex\n",
430+
"uw_.meshes/uw_cubed_spherical_shell_ro1.0_ri0.547_elts8_plexTrue.msh in 3 dimensions:\n",
431+
" Number of 0-cells per rank: 1672\n",
432+
" Number of 1-cells per rank: 10053\n",
433+
" Number of 2-cells per rank: 15998\n",
434+
" Number of 3-cells per rank: 7615\n",
435+
"Labels:\n",
436+
" depth: 4 strata with value/size (0 (1672), 1 (10053), 2 (15998), 3 (7615))\n",
437+
" All_Boundaries: 1 strata with value/size (1001 (1536))\n",
438+
" Elements: 1 strata with value/size (99999 (7871))\n",
439+
" Lower: 1 strata with value/size (1 (1062))\n",
440+
" Upper: 1 strata with value/size (2 (1062))\n",
441+
" celltype: 4 strata with value/size (0 (1672), 1 (10053), 3 (15998), 6 (7615))\n",
442+
" Null_Boundary: 1 strata with value/size (666 (1672))\n",
443+
" UW_Boundaries: 4 strata with value/size (1 (1062), 2 (1062), 666 (1672), 1001 (1536))\n"
448444
]
449445
}
450446
],
451447
"source": [
452-
"mesh.view()"
448+
"mesh.view(1)"
453449
]
454450
},
455451
{
@@ -470,14 +466,6 @@
470466
"\n",
471467
"See Notebook 8 for a short mesh-deformation example.\n"
472468
]
473-
},
474-
{
475-
"cell_type": "code",
476-
"execution_count": null,
477-
"id": "2374ad95-c893-49a8-9915-de68374135ba",
478-
"metadata": {},
479-
"outputs": [],
480-
"source": []
481469
}
482470
],
483471
"metadata": {

docs/user/Notebooks/2-Variables.ipynb

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
"source": [
1616
"# Notebook 2: Variables\n",
1717
"\n",
18-
"We can add discrete variables (unknowns associated with the mesh points)."
18+
"We can add discrete \"variables\" (unknowns associated with the mesh points) to a mesh, assign values to them and build expressions that `sympy` can understand, manipulate and simplify.\n",
19+
"\n",
20+
"This notebook introduces the concept of `MeshVariables` in `Underworld3`. These are both data containers and `sympy` symbolic objects. We show you how to inspect a `meshVariable`, set the data values in the `MeshVariable` and visualise them, and build expressions that `sympy` can understand, manipulate and simplify.\n",
21+
"\n"
1922
]
2023
},
2124
{
@@ -50,15 +53,7 @@
5053
},
5154
"tags": []
5255
},
53-
"outputs": [
54-
{
55-
"name": "stdout",
56-
"output_type": "stream",
57-
"text": [
58-
"PostHog telemetry failed: HTTPSConnectionPool(host='eu.i.posthog.com', port=443): Max retries exceeded with url: /capture/ (Caused by NameResolutionError(\"<urllib3.connection.HTTPSConnection object at 0x33cee0560>: Failed to resolve 'eu.i.posthog.com' ([Errno 8] nodename nor servname provided, or not known)\"))\n"
59-
]
60-
}
61-
],
56+
"outputs": [],
6257
"source": [
6358
"#| output: false # Suppress warnings in html version\n",
6459
"\n",
@@ -139,22 +134,14 @@
139134
},
140135
{
141136
"cell_type": "code",
142-
"execution_count": 18,
137+
"execution_count": 5,
143138
"id": "333ea2f7-1df3-49f5-9f28-0dbebabae49b",
144139
"metadata": {},
145-
"outputs": [
146-
{
147-
"name": "stdout",
148-
"output_type": "stream",
149-
"text": [
150-
"Expression to be evaluated: Matrix([[N.x/sqrt(N.x**2 + N.y**2 + N.z**2), N.y/sqrt(N.x**2 + N.y**2 + N.z**2), N.z/sqrt(N.x**2 + N.y**2 + N.z**2)]])\n"
151-
]
152-
}
153-
],
140+
"outputs": [],
154141
"source": [
155142
"with mesh.access(scalar_var, vector_var):\n",
156-
" scalar_var.data[:,0] = uw.function.evaluate(r, scalar_var.coords, evalf=False )\n",
157-
" vector_var.data[:,:] = uw.function.evaluate(r_vec, vector_var.coords, evalf=False, verbose=True)"
143+
" scalar_var.data[:,0] = uw.function.evaluate(r, scalar_var.coords)\n",
144+
" vector_var.data[:,:] = uw.function.evaluate(r_vec, vector_var.coords)"
158145
]
159146
},
160147
{
@@ -167,7 +154,7 @@
167154
},
168155
{
169156
"cell_type": "code",
170-
"execution_count": 24,
157+
"execution_count": 6,
171158
"id": "9e778873-9ba9-4778-a0d2-828c1647cf50",
172159
"metadata": {},
173160
"outputs": [
@@ -264,7 +251,7 @@
264251
},
265252
{
266253
"cell_type": "code",
267-
"execution_count": 25,
254+
"execution_count": 7,
268255
"id": "1ad62dad-6247-4818-a7bd-8227fc5ace69",
269256
"metadata": {
270257
"editable": true,
@@ -310,7 +297,7 @@
310297
},
311298
{
312299
"cell_type": "code",
313-
"execution_count": 26,
300+
"execution_count": 8,
314301
"id": "4754590a-23c4-42d7-ab04-97f6ea8421a9",
315302
"metadata": {
316303
"editable": true,
@@ -335,10 +322,10 @@
335322
" "
336323
],
337324
"text/plain": [
338-
"<IPython.lib.display.IFrame at 0x3503a9490>"
325+
"<IPython.lib.display.IFrame at 0x34f6b1370>"
339326
]
340327
},
341-
"execution_count": 26,
328+
"execution_count": 8,
342329
"metadata": {},
343330
"output_type": "execute_result"
344331
}
@@ -363,8 +350,24 @@
363350
"source": [
364351
"## More information\n",
365352
"\n",
366-
"The meshVariable code is described in the API docs: https://underworldcode.github.io/underworld3/main_api/underworld3/meshing.html"
353+
"The meshVariable code is described [**API docs** here.](https://underworldcode.github.io/underworld3/development_api/underworld3/discretisation.html#underworld3.discretisation.MeshVariable)"
367354
]
355+
},
356+
{
357+
"cell_type": "code",
358+
"execution_count": null,
359+
"id": "b13b41c5-8b5c-417f-b60e-0f82376ef686",
360+
"metadata": {},
361+
"outputs": [],
362+
"source": []
363+
},
364+
{
365+
"cell_type": "code",
366+
"execution_count": null,
367+
"id": "d3d9c223-b7b9-4bb3-a81c-a33521392d30",
368+
"metadata": {},
369+
"outputs": [],
370+
"source": []
368371
}
369372
],
370373
"metadata": {

0 commit comments

Comments
 (0)