Skip to content

Commit ee915f7

Browse files
committed
Make suggested docs changes
1 parent 0c39f15 commit ee915f7

File tree

2 files changed

+24
-41
lines changed

2 files changed

+24
-41
lines changed

docs/src/matrix_fields.md

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ scalar_field_matrix
107107

108108
A FieldMatrix entry can be:
109109

110-
- An `UniformScaling`, which contains a `Number`
110+
- A `UniformScaling`, which contains a `Number`
111111
- A `DiagonalMatrixRow`, which can contain either a `Number` or a tensor (represented as a `Geometry.Axis2Tensor`)
112112
- A `ColumnwiseBandMatrixField`, where each value is a [`BandMatrixRow`](@ref) with entries of any type that can be represented using the field's base number type.
113113

@@ -162,29 +162,22 @@ An example of this is:
162162
A = MatrixFields.FieldMatrix((@name(name1), @name(name2)) => sample_entry)
163163
```
164164

165-
Now consider what happens indexing `A` with the key `(@name(name1.foo.bar.buz), @name(name2.biz.bop.fud))`.
165+
Now consider what happens when indexing `A` with the key `(@name(name1.foo.bar.buz), @name(name2.biz.bop.fud))`.
166166

167167
First, `getindex` finds a key in `A` that contains the key being indexed. In this example, `(@name(name1.foo.bar.buz), @name(name2.biz.bop.fud))` is contained within `(@name(name1), @name(name2))`, so `(@name(name1), @name(name2))` is called the "parent key" and `(@name(foo.bar.buz), @name(biz.bop.fud))` is referred to as the "internal key".
168168

169169
Next, the entry that `(@name(name1), @name(name2))` is paired with is recursively indexed
170170
by the internal key.
171171

172-
The recursive indexing of an internal entry given some entry `entry` and internal_key `internal_name_pair`
172+
The recursive indexing of an internal entry given some entry `entry` and internal key `internal_name_pair`
173173
works as follows:
174174

175175
1. If the `internal_name_pair` is blank, return `entry`
176-
2. If the element type of each band of `entry` is an `Axis2Tensor`, and `internal_name_pair` is of the form
177-
`(@name(components.data.1...), @name(components.data.2...))` (potentially with different numbers),
178-
then extract the specified component, and recurse on it with the remaining `internal_name_pair`.
176+
2. If the element type of each band of `entry` is an `Axis2Tensor`, and `internal_name_pair` is of the form `(@name(components.data.1...), @name(components.data.2...))` (potentially with different numbers), then extract the specified component, and recurse on it with the remaining `internal_name_pair`.
179177
3. If the element type of each band of `entry` is a `Geometry.AdjointAxisVector`, then recurse on the parent of the adjoint.
180-
4. If `internal_name_pair[1]` is not empty, and the first name in it is a field of the element type of each band of `entry`,
181-
extract that field from `entry`, and recurse into it with the remaining names of `internal_name_pair[1]` and all of `internal_name_pair[2]`
182-
5. If `internal_name_pair[2]` is not empty, and the first name in it is a field of the element type of each band of `entry`,
183-
extract that field from `entry`, and recurse into it with all of `internal_name_pair[1]` and the remaining names of `internal_name_pair[2]`
184-
6. At this point, if none of the previous cases are true, both `internal_name_pair[1]` and `internal_name_pair[2]` should be
185-
non-empty, and it is assumed that `entry` is being used to implicitly represent some tensor structure. If the first name in
186-
`internal_name_pair[1]` is equivalent to `internal_name_pair[2]`, then both the first names are dropped, and entry is recursed onto.
187-
If the first names are different, both the first names are dropped, and the zero of entry is recursed onto.
178+
4. If `internal_name_pair[1]` is not empty, and the first name in it is a field of the element type of each band of `entry`, extract that field from `entry`, and recurse into it with the remaining names of `internal_name_pair[1]` and all of `internal_name_pair[2]`
179+
5. If `internal_name_pair[2]` is not empty, and the first name in it is a field of the element type of each band of `entry`, extract that field from `entry`, and recurse into it with all of `internal_name_pair[1]` and the remaining names of `internal_name_pair[2]`
180+
6. At this point, if none of the previous cases are true, both `internal_name_pair[1]` and `internal_name_pair[2]` should be non-empty, and it is assumed that `entry` is being used to implicitly represent some tensor structure. If the first name in `internal_name_pair[1]` is equivalent to `internal_name_pair[2]`, then both the first names are dropped, and entry is recursed onto. If the first names are different, both the first names are dropped, and the zero of entry is recursed onto.
188181

189182
When the entry is a `ColumnWiseBandMatrixField`, indexing it will return a broadcasted object in
190183
the following situations:
@@ -224,7 +217,7 @@ A `ColumnwiseBandMatrixField` is a `Field` with a `BandMatrixRow` at each point.
224217
to represent a collection of banded matrices, where there is one band matrix for each column
225218
of the space the `Field` is on. Beyond only storing the diagonals of the band matrix, an `entry`
226219
can be optimized to use less memory. Each optimized representation can be indexed equivalently to
227-
non optimized representation, and used in addition, subtraction, Matrix-vector multiplication,
220+
non optimized representations, and used in addition, subtraction, matrix-vector multiplication,
228221
Matrix-matrix multiplication, `RecursiveApply`, and `FieldMatrixSolver`.
229222

230223
For the following sections, `space` is a column space with $N_v$ levels. A column space is
@@ -240,8 +233,8 @@ $M$ represents $\frac{\partial f}{\partial g}$, so $M_{i,j} = \frac{\partial f_i
240233

241234
Consider the case where $b_1 = 0$ and $b_2 = 0$, i.e $M$ is a diagonal matrix, and
242235
where $M = k * I$, and $k$ is of type `T_k`. This would happen if
243-
$\frac{\partial f_i}{\partial g_j} = [i=j] * k$. Instead of storing
244-
each element on the diagonal, less memory can be used by storing a single value that represents a scaling of the identity. This reduces memory usage by a factor of $N_v$.
236+
$\frac{\partial f_i}{\partial g_j} = \delta_{ij} * k$. Instead of storing
237+
each element on the diagonal, the `FieldMatrix` can store a single value that represents a scaling of the identity matrix, reducing memory usage by a factor of $N_v$:
245238

246239
```julia
247240
entry = fill(DiagonalMatrixRow(k), space)
@@ -265,21 +258,20 @@ The functions that index an entry with an internal key assume the implicit tenso
265258
when all of the following are true for `entry` where `T_k` is the element type of each band, and
266259
`(internal_key_1, internal_key_2)` is the internal key indexing `entry`.
267260

268-
- the first key in the `internal_key_1` name chain is not a fieldname of `T_k`
269-
- the first key in the `internal_key_2` name chain is not a fieldname of `T_k`
270-
- `internal_key_1` and `internal_key_2` are both not empty
261+
- the `internal_key_1` name chain is not empty and its first name is not a field of `T_k`
262+
- the `internal_key_2` name chain is not empty and its first name is not a field of `T_k`
271263

272264
For most use cases, `T_k` is a scalar.
273265

274266
If the above conditions are met, the optimization assumes that the user intends the
275267
entry to have an implicit tensor structure, with the values of type `T_k` representing a scaling of the
276-
tensor identity. If both the first and second name in the name pair are equivalent, then they index onto the diagonal,
277-
and the value is returned. Otherwise, they index off the diagonal, and a zero value
268+
identity tensor. If both the first and second names in the name pair are equivalent, then they index onto the diagonal,
269+
and the scalar value of `k` is returned. Otherwise, they index off the diagonal, and a zero value
278270
is returned.
279271

280-
This optimization is intended to be used when `T_f = T_g`, and they are both `AxisVectors`
281-
The notation $f_{n}[i]$ where $0 < n \leq N_v$ refers to the $i$ component of the element
282-
at the $n$ vertical level of $f$. In the following example, `T_f=T_g=Covariant12Vector`, and
272+
This optimization is intended to be used when `T_f = T_g`.
273+
The notation $f_{n}[i]$ where $0 < n \leq N_v$ refers to the $i$-th component of the element
274+
at the $n$-th vertical level of $f$. In the following example, `T_f` and `T_g` are both `Covariant12Vector`s, and
283275
$b_1 = b_2 = 1$, and
284276

285277
```math
@@ -310,9 +302,9 @@ J[(@name(f.components.data.:(2)), @name(g.components.data.:(1)))]
310302

311303
This can be more optimally stored with the implicit tensor structure optimization:
312304

313-
```@example 2
314-
∂f_∂g = fill(MatrixFields.TridiagonalMatrixRow(-0.5, 1.0, -0.5), space) # hide
315-
J = MatrixFields.FieldMatrix((@name(f), @name(g))=> ∂f_∂g) # hide
305+
```@setup 2
306+
∂f_∂g = fill(MatrixFields.TridiagonalMatrixRow(-0.5, 1.0, -0.5), space)
307+
J = MatrixFields.FieldMatrix((@name(f), @name(g))=> ∂f_∂g)
316308
```
317309

318310
```julia
@@ -337,15 +329,5 @@ If it is the case that
337329
\end{cases}
338330
```
339331

340-
where $k$ is a constant scalar, both the implicit tensor structure optimization and
341-
`ScalingFieldMatrixEntry` optimization can both be applied:
342-
343-
```julia
344-
∂f_∂g = fill(MatrixFields.DiagonalMatrixRow(k), space)
345-
```
346-
347-
can equivalently be represented with
348-
349-
```julia
350-
∂f_∂g = MatrixFields.DiagonalMatrixRow(k)
351-
```
332+
where $k$ is a constant scalar, the implicit tensor structure optimization and
333+
`ScalingFieldMatrixEntry` optimization can both be applied.

src/MatrixFields/field_name_dict.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,8 @@ what method can index a ClimaCore `Field` of `S` with `name_pair`.
343343
344344
The third return value is one of the following:
345345
- `Val(:view)`: indexing with a view is possible
346-
- `Val(:view_of_blocks)`: indexing with a view of blocks is possible (this is not implemented)
346+
- `Val(:view_of_blocks)`: indexing with a view of non-unfiform stride length is possible.\
347+
This is not implemented, and currently treated the same as `Val(:broadcasted_fallback)`
347348
- `Val(:broadcasted_fallback)`: indexing with a view is not possible
348349
- `Val(:broadcasted_zero)`: indexing with a view is not possible, and the `name_pair` indexes
349350
off diagonal with implicit tensor structure optimization (see MatrixFields docs)

0 commit comments

Comments
 (0)