-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #119 from JuliaGeodynamics/adm/moreDocs
Add more docs
- Loading branch information
Showing
5 changed files
with
119 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Particles interpolations | ||
|
||
For now, interpolations support only equidistant regular rectangular/cubic grids. Please file and issue if you would be interested in supporting other kind of grids. | ||
|
||
## Grid to particle | ||
|
||
Information from the grid is linearly interpolated to the particles. The one dimensional linear interpolation kernel (also referred as _lerp_) is defined as | ||
|
||
$v_{\text{p}} = t v_0 + (1 -t) v_1$ | ||
|
||
where the $t$, $v_0$, and $v_1$ are graphically described below. | ||
|
||
<img src="assets/lerp.png" width="250" /> | ||
|
||
Numerically, it is more appropriately implemented as a double [fma](https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation) as it is slightly more accurate than a naive implementation: | ||
|
||
```julia | ||
v_p = fma(t, v1, fma(-t, v0, v0)) | ||
``` | ||
|
||
Bi- and tri-linear interpolation over a rectangular or cubic cells is thus nothing else than a chain of lerp kernels along the different dimensions of the cell. For example, the bilinear interpolation requires two lerps along the left and right sides of the cell, followed by a lerp on the horizontal direction; and trilinear interpolation requires two bilinear kernels and one lerp. | ||
|
||
N-linear interpolation is implemented in a recursive way to exploit compiler optimizations and reduce boilerplate code. Since in practical terms we will do up to tri-linear interpolation the maximum recursion depth is five, so that stack will never overflow. | ||
|
||
We can interpolate an arbitrary field $F$ onto the particles with the `grid2particle` function: | ||
|
||
```julia | ||
using JustPIC, JustPIC._2D | ||
# define model domain | ||
nxcell, max_xcell, min_xcell = 24, 30, 12 | ||
nx = ny = 128 | ||
Lx = Ly = 1.0 | ||
xvi = range(0, Lx, length=n), range(0, Ly, length=n) | ||
# field F at the grid | ||
F = [y for x in xv, y in yv] | ||
# instantiate empty `CellArray` | ||
Fp, = init_cell_arrays(particles, Val(1)); | ||
# interpolate F onto Fp | ||
grid2particle!(Fp, xvi, F, particles); | ||
``` | ||
|
||
## Particle to grid | ||
|
||
Information on the particles is currently interpolated to the vertices of the grid cells with an inverse distance weighting interpolant | ||
|
||
$v_{i,j} = \frac{\sum^N_{k=1} \omega_k v_k}{\sum^n_{k=1} \omega_k}$ | ||
|
||
where the weight is $\omega_i = d^{-n}$, with $d$ being the distance between the particle and the node, and $n$ a integer number. | ||
|
||
In shared memory environments (e.g. OpenMP parallelism or GPU programming), this particular interpolation often requires the use of atomic operations due to race conditions. In `JustPIC` we do avoid using atomic operations by parallelising over the grid nodes instead of the particles, i.e. we iterated over the nodes, with an inner iteration over the `CellArrays` neighbouring the $i$-th grid node. | ||
|
||
This inteprolation is done with the `particle2grid!` function: | ||
```julia-repl | ||
julia> particle2grid!(F, Fp, xvi, particles) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,47 @@ | ||
# Memory layout | ||
# Particles | ||
|
||
## Memory layout | ||
|
||
Particles stored in `CellArray`s objects from [`CellArrays.jl`](https://github.com/omlins/CellArrays.jl) and are constantly sorted by their parent cell to avoid a loss of spatial locality with time. | ||
|
||
# Particle objects | ||
## Particle objects | ||
|
||
There are three type of `AbstractParticles` types: | ||
|
||
## Particles | ||
- `Particles` is the basic type used to advect and track information on the whole domain of our model. The dimension of the `CellArrays` has to match the dimension of the model. | ||
- `PassiveMarkers` is a set of particles where their initial position is defined by the user. These particles are only advected and are not meant to have any feedback with the simulation; their purpose is to track the history of any arbitrary field(s) throughout the simulation. | ||
- `MarkerChain` is a one or two dimensional chain of particles, used to track surfaces / interfaces. | ||
|
||
## Passive markers | ||
### Simulation particles | ||
```julia | ||
struct Particles{Backend,N,M,I,T1,T2} <: AbstractParticles | ||
coords::NTuple{N,T1} | ||
index::T2 | ||
nxcell::I | ||
max_xcell::I | ||
min_xcell::I | ||
np::I | ||
end | ||
``` | ||
Where `coords` is a tuple containing the coordinates of the particles; `index` is a `BitArray` where `true` if in the correspondent `CellArray` there is an active particle, otherwise false; `nxcell`, `min_xcell`, `max_xcell` are the initial, minimum and maximum number of particles per cell; and, `np` is the initial number of particles. | ||
|
||
### Passive markers | ||
```julia | ||
struct MarkerChain{Backend,N,M,I,T1,T2,TV} <: AbstractParticles | ||
coords::NTuple{N,T1} | ||
index::T2 | ||
cell_vertices::TV | ||
max_xcell::I | ||
min_xcell::I | ||
end | ||
``` | ||
Where `coords` is a tuple containing the coordinates of the particles; `index` is an `BitArray` where `true` if in the correspondent `CellArray` there is an active particle, otherwise false; `cell_vertices` is the lower-left corner (`(x,)` in 2D, `(x,y)` in 3D) of the cell containing those particles;and, `min_xcell`, `max_xcell` are theminimum and maximum number of particles per cell. | ||
|
||
## Marker chain | ||
### Marker chain | ||
```julia | ||
struct PassiveMarkers{Backend,T} <: AbstractParticles | ||
coords::T | ||
np::Int64 | ||
end | ||
``` | ||
Where `coords` is a tuple containing the coordinates of the particles; and `np` is the number of passive markers. |