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
1 change: 1 addition & 0 deletions docs/advanced/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@ curved-boundary-conditions
mesh-adaptation
troubleshooting
api-patterns
SWARM-INTEGRATION-STATISTICS
```
5 changes: 0 additions & 5 deletions docs/api/constitutive_models.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Constitutive Models

```{eval-rst}
.. automodule:: underworld3.constitutive_models
:no-members:
```

## Viscous Flow Models

### ViscousFlowModel
Expand Down
5 changes: 0 additions & 5 deletions docs/api/coordinates.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Coordinate Systems

```{eval-rst}
.. automodule:: underworld3.coordinates
:no-members:
```

## CoordinateSystem

The base class for coordinate system handling on meshes.
Expand Down
5 changes: 0 additions & 5 deletions docs/api/discretisation.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Discretisation

```{eval-rst}
.. automodule:: underworld3.discretisation
:no-members:
```

## Mesh

The computational mesh class that provides the spatial discretisation for finite element calculations.
Expand Down
13 changes: 1 addition & 12 deletions docs/api/function.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# Function and Expressions

```{eval-rst}
.. automodule:: underworld3.function
:no-members:
```

## Expressions

### UWexpression

```{eval-rst}
.. autoclass:: underworld3.function.UWexpression
.. autoclass:: underworld3.function.expressions.UWexpression
:members:
:show-inheritance:
```
Expand Down Expand Up @@ -75,12 +70,6 @@ Factory function for creating UWQuantity objects with units.
.. autofunction:: underworld3.function.global_evaluate
```

### evalf

```{eval-rst}
.. autofunction:: underworld3.function.evalf
```

### evaluate_gradient

```{eval-rst}
Expand Down
6 changes: 0 additions & 6 deletions docs/api/maths.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# Mathematical Operations

```{eval-rst}
.. automodule:: underworld3.maths
:members:
:show-inheritance:
```

## Integral Operations

```{eval-rst}
Expand Down
5 changes: 0 additions & 5 deletions docs/api/solvers.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Solvers

```{eval-rst}
.. automodule:: underworld3.systems.solvers
:no-members:
```

## Stokes Flow

### SNES_Stokes
Expand Down
13 changes: 0 additions & 13 deletions docs/api/swarm.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Particle Swarms

```{eval-rst}
.. automodule:: underworld3.swarm
:no-members:
```

## Swarm

```{eval-rst}
Expand All @@ -21,14 +16,6 @@
:show-inheritance:
```

## Population Control

```{eval-rst}
.. autoclass:: underworld3.swarm.PopulationControl
:members:
:show-inheritance:
```

## Index Swarm Variable

```{eval-rst}
Expand Down
5 changes: 0 additions & 5 deletions docs/api/systems_ddt.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# Time Derivatives

```{eval-rst}
.. automodule:: underworld3.systems.ddt
:no-members:
```

Time derivative operators approximate $D\phi/Dt$ or $DF/Dt$ for transient
solvers. All operators share a common interface: ``update_pre_solve(dt)``
before each timestep, ``bdf()`` for the BDF approximation in the weak form,
Expand Down
2 changes: 1 addition & 1 deletion docs/beginner/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ $$

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.

```{figure} media/UW3-StrongScalingSolvers.png
```{figure} ../media/UW3-StrongScalingSolvers.png
:name: fig-strong-scaling

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.
Expand Down
3 changes: 1 addition & 2 deletions docs/developer/UW3_Developers_MathematicalObjects.md
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,7 @@ def test_mathematical_operations():
## Planned Enhancements

### 1. Operator Overloading
```python

```text
# Future possibilities
laplacian = velocity @ nabla**2 # Operator syntax
curl = nabla × velocity # Cross product notation
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/container/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
orphan: true
---

The `Containerfile` is used to build the container and can be used with docker or podman.
At present only amd64 architecture is built, because vtk-osmesa isn't available for arm by default. This may change in future, or we could build vtk-osmesa from source (see https://docs.pyvista.org/extras/building_vtk.html)

Expand Down
24 changes: 12 additions & 12 deletions docs/developer/design/COORDINATE_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@

### Pattern Migration Cheat Sheet

```python
# ❌ DEPRECATED → ✅ RECOMMENDED
mesh.data mesh.X.coords or mesh.points
mesh.data.shape mesh.X.coords.shape
mesh.data[:, 0] mesh.X.coords[:, 0]
mesh.data.min() mesh.X.coords.min()
mesh.data.copy() mesh.X.coords.copy()

# ✅ UNCHANGED (these work exactly as before)
mesh.X[0] mesh.X[0] (symbolic x-coordinate)
x, y = mesh.X x, y = mesh.X (symbolic unpacking)
mesh.units mesh.units (coordinate units)
```text
DEPRECATED RECOMMENDED
mesh.data -> mesh.X.coords or mesh.points
mesh.data.shape -> mesh.X.coords.shape
mesh.data[:, 0] -> mesh.X.coords[:, 0]
mesh.data.min() -> mesh.X.coords.min()
mesh.data.copy() -> mesh.X.coords.copy()

UNCHANGED (these work exactly as before)
mesh.X[0] -> mesh.X[0] (symbolic x-coordinate)
x, y = mesh.X -> x, y = mesh.X (symbolic unpacking)
mesh.units -> mesh.units (coordinate units)
```

## Migration Examples by Use Case
Expand Down
4 changes: 2 additions & 2 deletions docs/developer/design/WHY_UNITS_NOT_DIMENSIONALITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- **Dimensionality**: ⚠️ Abstract physics concept ([length], [time], [mass])

### What the API Shows:
```python
```text
# User-friendly - clear what's happening
var.units = "m"
var.to("km")
Expand Down Expand Up @@ -345,7 +345,7 @@ from underworld3.utilities.units_mixin import UnitAwareMixin
- What does that even mean?

### 3. API Clarity ✅
```python
```text
# Clear and intuitive
var.units = "m"
var.to("km")
Expand Down
2 changes: 1 addition & 1 deletion docs/developer/guides/HOW-TO-WRITE-UW3-SCRIPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ def test_swarm_functionality():

If you see generated C code with symbolic expressions instead of numbers:

```c
```text
// ERROR symptom in generated code:
out[0] = 1.0/{ \eta \hspace{ 0.0006pt } }; // Should be numeric!
```
Expand Down
6 changes: 3 additions & 3 deletions docs/developer/subsystems/constitutive-models-anisotropy.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ In `underworld` tensor rotation is provided for rank 2 and rank 4 tensors by `uw

If we apply constraints to the deformation, we expect to reduce the number of independent material constants. Incompressibility should reduce the number of *independent* material constants. In an isotropic medium (or a medium with cubic symmetry), incompressibility eliminates the one volumetric material modulus (e.g. the bulk modulus). In general anisotropic media, it is not the case that changes in pressure result in uniform expansion or contraction, and an incompressibility constraint reduces the number of *independent* material constants. In the transversely isotropic case, there are five independent materia constants in general, reducing to four when the material is incompressible.

It is not a given that the stiffness matrix is trivial to construct / meaningful for incompressible anisotropy and there is some discussion here: https://rastgaragah.wordpress.com/2013/03/12/incompressibility-of-linearly-elastic-material/ (identifies the issue) and this is explained in more detail by {cite}`destradeIncompressibleLimitLinear2002`
It is not a given that the stiffness matrix is trivial to construct / meaningful for incompressible anisotropy and there is some discussion here: https://rastgaragah.wordpress.com/2013/03/12/incompressibility-of-linearly-elastic-material/ (identifies the issue) and this is explained in more detail by Destrade et al. (2002)


### Example
Expand Down Expand Up @@ -192,7 +192,7 @@ display(C_IJm_MM_iso)

## Han & Wahr, 1997 (full transverse isotropic tensor)

In the {cite}`hanAnalysisAnisotropicMantle1997` paper, the expression for incompressible transverse-isotropy is as follows
In the Han & Wahr (1997) paper, the expression for incompressible transverse-isotropy is as follows

$$\left[\begin{matrix}2 \eta_{0} + \mu_{0} & \mu_{0} & 0 & 0 & 0 & 0\\\mu_{0} & 2 \eta_{0} + \mu_{0} & 0 & 0 & 0 & 0\\0 & 0 & - 2 \Delta\eta + 2 \eta_{0} + \mu_{1} & 0 & 0 & 0\\0 & 0 & 0 & - 2 \Delta\eta + 2 \eta_{0} & 0 & 0\\0 & 0 & 0 & 0 & - 2 \Delta\eta + 2 \eta_{0} & 0\\0 & 0 & 0 & 0 & 0 & 2 \eta_{0}\end{matrix}\right]$$

Expand Down Expand Up @@ -249,7 +249,7 @@ display(C_IJm_HW_R_s2)

## Orthotropic medium

**Note** all the caveats above regarding incompressibility. The {cite}`browaeysDecompositionElasticTensor2004` elastic tensors have a bulk modulus term, so it is not completely obvious how to square the assumptions in the first two implementations with this set.
**Note** all the caveats above regarding incompressibility. The Browaeys & Chevrot (2004) elastic tensors have a bulk modulus term, so it is not completely obvious how to square the assumptions in the first two implementations with this set.

The full formulation should look like this:

Expand Down
19 changes: 6 additions & 13 deletions src/underworld3/discretisation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@
This module provides the core discretisation infrastructure for finite
element computations in Underworld3.

Classes
-------
Mesh : class
Unstructured mesh with PETSc DMPlex backend. Supports various cell
types and coordinate systems.
MeshVariable : class
Field variable defined on mesh (nodal or cell-based storage).
**Mesh** -- Unstructured mesh with PETSc DMPlex backend.

Functions
---------
checkpoint_xdmf : function
Save mesh and variables to XDMF format for visualization.
meshVariable_lookup_by_symbol : function
Find mesh variable by its symbolic representation.
**MeshVariable** -- Field variable defined on mesh (nodal or cell-based storage).

**checkpoint_xdmf** -- Save mesh and variables to XDMF format.

**meshVariable_lookup_by_symbol** -- Find mesh variable by its symbol.

See Also
--------
Expand Down
6 changes: 3 additions & 3 deletions src/underworld3/discretisation/discretisation_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1869,11 +1869,11 @@ def write_checkpoint(
index: Optional[int] = 0,
unique_id: Optional[bool] = False,
):
"""Write data in a format that can be restored for restarting the simulation
"""Write data in a format that can be restored for restarting the simulation.

The difference between this and the visualisation is 1) the parallel section needs
to be stored to reload the data correctly, and 2) the visualisation information (vertex form of fields)
is not stored. This routines uses dmplex *VectorView and *VectorLoad functionality

is not stored. This routine uses dmplex VectorView and VectorLoad functionality.
"""

# The mesh checkpoint is the same as the one required for visualisation
Expand Down
25 changes: 10 additions & 15 deletions src/underworld3/function/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@
on meshes and swarms. It bridges SymPy symbolic mathematics with PETSc
numerical evaluation.

Key Components
--------------
expression : class
User-facing symbolic expression wrapper (UWexpression).
evaluate : function
Evaluate expressions at mesh/swarm points.
global_evaluate : function
Parallel-safe evaluation gathering results across MPI ranks.
UnderworldFunction : class
Core function evaluation machinery.

Unit Conversion
---------------
convert_quantity_units, make_dimensionless, add_units
Utilities for handling physical units in expressions.
**expression** -- User-facing symbolic expression wrapper (UWexpression).

**evaluate** -- Evaluate expressions at mesh/swarm points.

**global_evaluate** -- Parallel-safe evaluation gathering results across MPI ranks.

**UnderworldFunction** -- Core function evaluation machinery.

**convert_quantity_units**, **make_dimensionless**, **add_units** --
Utilities for handling physical units in expressions.

The function module integrates with pint for optional unit-aware
computations when the mesh has an associated unit registry.
Expand Down
36 changes: 17 additions & 19 deletions src/underworld3/function/_function.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,16 @@ class UnderworldAppliedFunctionDeriv(UnderworldAppliedFunction):

class UnderworldFunction(sympy.Function):
"""
This is a metaclass, so it returns programmatic class objects rather
than instances. This basically follows the pattern of the `sympy.Function`
metaclass, with two key differences:
1. We set `UnderworldAppliedFunction` as the base class. This is really just a
dummy class (see its definition) which allows us to do calls such
as `isinstance(someobj, UnderworldAppliedFunction)` to test if a `sympy`
object is one we've defined.
2. We grab a weakref of the owning meshvariable onto the *class* itself. Note
that it's important that it's recorded onto the class (instead of the instance),
as Sympy internally sometimes uses calls such as `type(obj)(obj.args)` to
replace objects with cloned instances, and therefore 'extra' info must be
recorded onto the class so that the clones are _complete_.
Metaclass that returns programmatic class objects rather than instances.

This basically follows the pattern of the ``sympy.Function``
metaclass, with two key differences. First, we set
``UnderworldAppliedFunction`` as the base class, which allows
``isinstance(someobj, UnderworldAppliedFunction)`` checks.
Second, we grab a weakref of the owning meshvariable onto the
class itself (not the instance), because SymPy internally uses
``type(obj)(obj.args)`` to clone instances and extra info must
be on the class so that clones are complete.

Consider the calling pattern

Expand All @@ -157,16 +155,16 @@ class UnderworldFunction(sympy.Function):

Parameters
----------
name:
name : str
The name of the function.
meshvar:
meshvar : MeshVariable
The mesh variable corresponding to this function.
vtype:
The variable type (scalar,vector,etc).
component:
vtype : VarType
The variable type (scalar, vector, etc).
component : int or tuple
For vector functions, this is the component of the vector.
For example, component `1` might correspond to `v_y`.
For tensors, the component is a tuple
For example, component ``1`` might correspond to ``v_y``.
For tensors, the component is a tuple.
For scalars, this value is ignored.
"""
def __new__(cls,
Expand Down
Loading
Loading