Skip to content

Commit f153c95

Browse files
authored
Package hygiene (#82)
* package hygiene * add `Mass` and `Stiffness` types
1 parent c11d455 commit f153c95

25 files changed

+554
-558
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "CoherentStructures"
22
uuid = "0c1513b4-3a13-56f1-9cd2-8312eaec88c4"
3-
version = "0.4.4"
3+
version = "0.4.5"
44

55
[deps]
66
ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d"

docs/Manifest.toml

Lines changed: 146 additions & 119 deletions
Large diffs are not rendered by default.

docs/makeimages.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ ctx = regularTriangularGrid((100,100), [0.0,0.0],[2π,2π])
4848
pred = (x,y) -> ((x[1] - y[1]) % 2π) < 1e-9 && ((x[2] - y[2]) % 2π) < 1e-9
4949
bdata = BoundaryData(ctx,pred)
5050

51-
id2 = one(Tensors.Tensor{2,2}) # 2D identity tensor
51+
id2 = one(Tensor{2,2}) # 2D identity tensor
5252
cgfun = x -> 0.5*(id2 + dott(inv(DstandardMap(x))))
5353

5454
K = assembleStiffnessMatrix(ctx,cgfun,bdata=bdata)

docs/src/fem.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ u[20] = 2.0; u[38] = 3.0; u[56] = 4.0
162162
plot_u(ctx, u, 200, 200, bdata=bdata, colorbar=:none)
163163
```
164164

165-
To apply boundary conditions to a stiffness/mass matrix, use the `applyBCS` function. Note that `assembleStiffnessMatrix` and `assembleMassMatrix` take a `bdata` argument that does this internally.
165+
To apply boundary conditions to a stiffness/mass matrix, use the `applyBCS` function. Note
166+
that both `assemble` functions take a `bdata` argument that does this internally.
166167

167168
## Plotting and Videos
168169

@@ -172,8 +173,9 @@ The simplest way to plot is using the [`plot_u`](@ref) function. Plots and video
172173

173174
## Parallelisation
174175

175-
Many of the plotting functions support parallelism internally.
176-
Tensor fields can be constructed in parallel, and then passed to [`assembleStiffnessMatrix`](@ref). For an example that does this, see
176+
Many of the plotting functions support parallelism internally. Tensor fields can be
177+
constructed in parallel, and then passed to [`assemble(Stiffness(), _)`](@ref). For an
178+
example that does this, see
177179
TODO: Add this example
178180

179181
## FEM-API
@@ -185,8 +187,7 @@ CurrentModule = CoherentStructures
185187
### Stiffness and Mass Matrices
186188

187189
```@docs
188-
assembleStiffnessMatrix
189-
assembleMassMatrix
190+
assemble
190191
adaptiveTOCollocationStiffnessMatrix
191192
```
192193

src/CoherentStructures.jl

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,41 @@ module CoherentStructures
22

33
# use standard libraries
44
using LinearAlgebra
5-
using ProgressMeter
5+
using LinearAlgebra: checksquare
6+
import ProgressMeter
67
using SparseArrays
8+
using SparseArrays: nzvalview, dropzeros!
79
using Distributed
810
using SharedArrays: SharedArray
911
using Statistics: mean
1012

1113
# import data type packages
12-
import StaticArrays
13-
using StaticArrays: SVector, @SVector, SArray, SMatrix, @SMatrix
14-
import Tensors
15-
using Tensors: Vec, Tensor, SymmetricTensor
16-
import AxisArrays
14+
using StaticArrays: SVector, @SVector, SMatrix, @SMatrix
15+
using Tensors: Vec, Tensor, SymmetricTensor, basevec, dott, tdot, otimes, symmetric
1716
using AxisArrays: AxisArray, ClosedInterval, axisvalues
1817

19-
import DiffEqBase
20-
import OrdinaryDiffEq
21-
const ODE = OrdinaryDiffEq
22-
import Distances
23-
const Dists = Distances
24-
import NearestNeighbors
25-
const NN = NearestNeighbors
26-
import Interpolations
27-
const ITP = Interpolations
18+
using DiffEqBase: DiffEqBase, initialize!, isconstant, update_coefficients!, @..
19+
using OrdinaryDiffEq: OrdinaryDiffEq, ODEProblem, ODEFunction, ContinuousCallback,
20+
terminate!, solve, Tsit5, BS5, OrdinaryDiffEqNewtonAlgorithm, DEFAULT_LINSOLVE,
21+
alg_order, OrdinaryDiffEqMutableCache, alg_cache, @muladd, perform_step!, @unpack,
22+
unwrap_alg, is_mass_matrix_alg
23+
24+
using Distances: Distances, PreMetric, SemiMetric, Metric, Euclidean, PeriodicEuclidean,
25+
pairwise, pairwise!, colwise, colwise!, result_type
26+
27+
using NearestNeighbors: BallTree, KDTree, inrange, knn, MinkowskiMetric
28+
29+
using Interpolations: Interpolations, LinearInterpolation, CubicSplineInterpolation,
30+
interpolate, scale, BSpline, Linear, Cubic, Natural, OnGrid, Free
2831

2932
# import linear algebra related packages
30-
import LinearMaps
31-
const LMs = LinearMaps
32-
import IterativeSolvers
33-
import ArnoldiMethod
33+
using LinearMaps: LinearMap
34+
using IterativeSolvers: cg
35+
using ArnoldiMethod: partialschur, partialeigen
3436

3537
# import geometry related packages
36-
import GeometricalPredicates
37-
const GP = GeometricalPredicates
38-
import VoronoiDelaunay
39-
const VD = VoronoiDelaunay
40-
38+
using GeometricalPredicates: GeometricalPredicates, Point, AbstractPoint2D, Point2D, getx, gety
39+
using VoronoiDelaunay: DelaunayTessellation2D, findindex, isexternal, max_coord, min_coord
4140

4241
# Ferrite
4342
import Ferrite

src/FEMassembly.jl

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,45 @@
11
# Strongly inspired by an example provided on Ferrite's github page, modified and
22
# extended by Nathanael Schilling
33

4+
struct Stiffness end
5+
struct Mass end
6+
47
#Works in n=2 and n=3
5-
tensorIdentity(x::Vec{dim}, _, p) where {dim} = one(SymmetricTensor{2,dim,Float64,3(dim-1)})
8+
tensorIdentity(x::Vec{dim,T}, _, p) where {dim,T} = one(SymmetricTensor{2,dim,T})
69

710
"""
8-
assembleStiffnessMatrix(ctx, A, p=nothing; bdata=BoundaryData())
11+
assemble(Stiffness(), ctx; A=Id, p=nothing, bdata=BoundaryData())
912
1013
Assemble the stiffness-matrix for a symmetric bilinear form
1114
```math
1215
a(u,v) = \\int \\nabla u(x)\\cdot A(x)\\nabla v(x)f(x) dx.
1316
```
1417
The integral is approximated using numerical quadrature. `A` is a function that returns a
1518
`SymmetricTensor{2,dim}` object and must have one of the following signatures:
16-
* `A(x::Vector{Float64})`;
17-
* `A(x::Vec{dim})`;
18-
* `A(x::Vec{dim}, index::Int, p)`. Here, `x` is equal to `ctx.quadrature_points[index]`,
19-
and `p` is the one passed to `assembleStiffnessMatrix`.
19+
20+
* `A(x::Vector{Float64})`;
21+
* `A(x::Vec{dim})`;
22+
* `A(x::Vec{dim}, index::Int, p)`. Here, `x` is equal to `ctx.quadrature_points[index]`,
23+
and `p` is some parameter, think of some precomputed object that is indexed via `index`.
2024
2125
The ordering of the result is in dof order, except that boundary conditions from `bdata` are
2226
applied. The default is natural (homogeneous Neumann) boundary conditions.
2327
"""
24-
function assembleStiffnessMatrix(ctx::GridContext, A=tensorIdentity, p=nothing; bdata=BoundaryData())
28+
function assemble(::Stiffness, ctx::GridContext; A=tensorIdentity, p=nothing, bdata=BoundaryData())
2529
if A === tensorIdentity
26-
return _assembleStiffnessMatrix(ctx, A, p, bdata=bdata)
30+
return _assembleStiffnessMatrix(ctx, A, p, bdata = bdata)
2731
elseif !isempty(methods(A, (Vec,)))
2832
return _assembleStiffnessMatrix(ctx, (qp, i, p) -> A(qp), p, bdata=bdata)
2933
elseif !isempty(methods(A, (Vec, Int, Any)))
3034
return _assembleStiffnessMatrix(ctx, (qp, i, p) -> A(qp, i, p), p, bdata=bdata)
3135
elseif !isempty(methods(A, (Vector{Float64},)))
32-
return _assembleStiffnessMatrix(ctx, (qp, i, p) -> A(Vector{Float64}(qp)), p, bdata=bdata)
36+
return _assembleStiffnessMatrix(ctx, (qp, i, p) -> A(convert(Vector{Float64}, qp)), p, bdata=bdata)
3337
end
34-
error("Function parameter A does not accept types supported by assembleStiffnessMatrix")
38+
error("function argument `A` does not admit any of the accepted signatures")
3539
end
40+
@deprecate assembleStiffnessMatrix(ctx::GridContext, A=tensorIdentity, p=nothing; bdata=BoundaryData()) assemble(Stiffness(), ctx; A=A, p=p, bdata=bdata)
3641

37-
function _assembleStiffnessMatrix(ctx::GridContext, A, p; bdata=BoundaryData())
42+
function _assembleStiffnessMatrix(ctx, A, p; bdata=BoundaryData())
3843
cv = FEM.CellScalarValues(ctx.qr, ctx.ip, ctx.ip_geom)
3944
dh = ctx.dh
4045
K = FEM.create_sparsity_pattern(dh)
@@ -70,7 +75,7 @@ end
7075

7176

7277
"""
73-
assembleMassMatrix(ctx; bdata=BoundaryData(), lumped=false)
78+
assemble(Mass(), ctx; bdata=BoundaryData(), lumped=false)
7479
7580
Assemble the mass matrix
7681
```math
@@ -86,10 +91,10 @@ Returns a lumped mass matrix if `lumped=true`.
8691
# Example
8792
```
8893
ctx.mass_weights = map(f, ctx.quadrature_points)
89-
M = assembleMassMatrix(ctx)
94+
M = assemble(Mass(), ctx)
9095
```
9196
"""
92-
function assembleMassMatrix(ctx::GridContext; bdata=BoundaryData(), lumped=false)
97+
function assemble(::Mass, ctx::GridContext; bdata=BoundaryData(), lumped=false)
9398
cv = FEM.CellScalarValues(ctx.qr, ctx.ip, ctx.ip_geom)
9499
dh = ctx.dh
95100
M = FEM.create_sparsity_pattern(dh)
@@ -123,12 +128,12 @@ function assembleMassMatrix(ctx::GridContext; bdata=BoundaryData(), lumped=false
123128
M = applyBCS(ctx, M, bdata)
124129
return lumped ? spdiagm(0 => dropdims(reduce(+, M; dims=1); dims=1)) : M
125130
end
131+
@deprecate assembleMassMatrix(ctx::GridContext; bdata=BoundaryData(), lumped=false) assemble(Mass(), ctx; bdata=bdata, lumped=lumped)
126132

127133
"""
128-
getQuadPointsPoints(ctx)
134+
getQuadPoints(ctx)
129135
130-
Compute the coordinates of all quadrature points on a grid.
131-
Helper function.
136+
Compute the coordinates of all quadrature points on a grid. Helper function.
132137
"""
133138
function getQuadPoints(ctx::GridContext{dim}) where {dim}
134139
cv = FEM.CellScalarValues(ctx.qr, ctx.ip_geom)

src/TO.jl

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ function nonAdaptiveTOCollocation(
5050

5151
#Calculate the integral of shape function in the domain (dof order)
5252
shape_function_weights_domain_original = undoBCS(ctx_domain,
53-
vec(sum(assembleMassMatrix(ctx_domain, bdata=bdata_domain), dims=1)),
53+
vec(sum(assemble(Mass(), ctx_domain, bdata=bdata_domain), dims=1)),
5454
bdata_domain)
5555
#Calculate the integral of shape functions in the codomain (dof order)
5656
#Do not include boundary conditions here, as we end up summing over this later
57-
shape_function_weights_codomain = vec(sum(assembleMassMatrix(ctx_codomain),dims=1))
57+
shape_function_weights_codomain = vec(sum(assemble(Mass(), ctx_codomain), dims=1))
5858

5959
#This variable will hold approximate pullback (in the measure sense)
6060
#of shape_function_weights_codomain to domain via finv
@@ -102,23 +102,28 @@ function nonAdaptiveTOCollocation(
102102
end
103103

104104
"""
105-
adaptiveTOCollocationStiffnessMatrix(ctx,flow_maps,times=nothing; [quadrature_order, on_torus,on_cylinder, LL, UR, bdata, volume_preserving=true,flow_map_mode=0] )
105+
adaptiveTOCollocationStiffnessMatrix(ctx, flow_maps, times=nothing; [quadrature_order, on_torus,on_cylinder, LL, UR, bdata, volume_preserving=true, flow_map_mode=0] )
106106
107-
Calculate the matrix-representation of the bilinear form ``a(u,v) = 1/N \\sum_n^N a_1(I_hT_nu,I_hT_nv)`` where
108-
``I_h`` is pointwise interpolation of the grid obtained by doing Delaunay triangulation on images of grid points from ctx
109-
and ``T_n`` is the Transfer-operator for ``x \\mapsto flow_maps(x,times)[n]`` and ``a_1`` is the weak form of the Laplacian on the codomain. Moreover,
110-
``N`` in the equation above is equal to `length(times)` and ``t_n`` ranges over the elements of `times`.
107+
Calculate the matrix-representation of the bilinear form ``a(u,v) = 1/N \\sum_n^N a_1(I_hT_nu,I_hT_nv)``
108+
where ``I_h`` is pointwise interpolation of the grid obtained by doing Delaunay
109+
triangulation on images of grid points from `ctx` and ``T_n`` is the transfer operator for
110+
``x \\mapsto flow_maps(x, times)[n]`` and ``a_1`` is the weak form of the Laplacian on the
111+
codomain. Moreover, ``N`` in the equation above is equal to `length(times)` and ``t_n``
112+
ranges over the elements of `times`.
111113
112-
If `times==nothing`, take ``N=1`` above and use the map ``x \\mapsto flow_maps(x)` instead of the version with `t_n`.
114+
If `times==nothing`, take ``N=1`` above and use the map ``x \\mapsto flow_maps(x)`` instead
115+
of the version with `t_n`.
113116
114-
If `on_torus` is true, the Delaunay Triangulation is done on the torus.
115-
If `on_cylinder` is true, then triangulation is done on cylinder (periodic) x. In both of these cases we require `bdata` for boundary information
116-
on the original domain as well as `LL` and `UR` as lower-left and upper-right corners of the image.
117+
If `on_torus` is true, the Delaunay triangulation is done on the torus.
118+
If `on_cylinder` is true, then triangulation is done on an x-periodic cylinder. In both of
119+
these cases we require `bdata` for boundary information on the original domain as well as
120+
`LL` and `UR` as lower-left and upper-right corners of the image.
117121
118122
If `volume_preserving == false`, add a volume_correction term to ``a_1`` (See paper by Froyland & Junge).
119123
120-
If `flow_map_mode==0`, apply flow map to nodal basis function coordinates.
121-
If `flow_map_mode==1`, apply flow map to nodal basis function index number (allows for precomputed trajectories).
124+
If `flow_map_mode=0`, apply flow map to nodal basis function coordinates.
125+
If `flow_map_mode=1`, apply flow map to nodal basis function index number (allows for
126+
precomputed trajectories).
122127
"""
123128
function adaptiveTOCollocationStiffnessMatrix(ctx::GridContext{2}, flow_maps, times=nothing;
124129
quadrature_order=default_quadrature_order,
@@ -183,58 +188,52 @@ function adaptiveTOCollocationStiffnessMatrix(ctx::GridContext{2}, flow_maps, ti
183188
#the old grid
184189
new_density_nodevals = new_density_bcdofvals
185190
while length(new_density_nodevals) != new_ctx.n
186-
push!(new_density_nodevals,0.0)
191+
push!(new_density_nodevals, 0.0)
187192
end
188193

189-
new_ctx.mass_weights = [evaluate_function_from_node_or_cellvals(new_ctx,new_density_nodevals,q)
190-
for q in new_ctx.quadrature_points ]
194+
new_ctx.mass_weights = [evaluate_function_from_node_or_cellvals(new_ctx, new_density_nodevals, q)
195+
for q in new_ctx.quadrature_points]
191196
end
192-
I, J, V = findnz(assembleStiffnessMatrix(new_ctx,bdata=new_bdata))
197+
I, J, V = findnz(assemble(Stiffness(), new_ctx, bdata=new_bdata))
193198
I .= translation_table[I]
194199
J .= translation_table[J]
195200
n = ctx.n - length(bdata.periodic_dofs_from)
196-
push!(As,sparse(I,J,V,n,n))
201+
push!(As, sparse(I, J, V, n, n))
197202
end
198203
return mean(As)
199204
end
200205

201206

202207
#Reordering in the periodic case is slightly more tricky
203-
function bcdofNewToBcdofOld(
204-
old_ctx::GridContext{dim},bdata::BoundaryData,
205-
new_ctx::GridContext{dim},new_bdata::BoundaryData,K
206-
) where {dim}
207-
208-
I, J ,V = findnz(K)
209-
210-
#Here I,J are in pdof order for new_ctx
211-
212-
bcdof_to_node_new = bcdof_to_node(new_ctx,new_bdata)
213-
node_to_bcdof_old = node_to_bcdof(old_ctx,bdata)
214-
I .= node_to_bcdof_old[bcdof_to_node_new[I]]
215-
J .= node_to_bcdof_old[bcdof_to_node_new[J]]
216-
217-
old_pdof_n = old_ctx.n - length(bdata.periodic_dofs_from)
218-
219-
return sparse(I,J,V,old_pdof_n,old_pdof_n)
208+
function bcdofNewToBcdofOld(old_ctx::GridContext{dim}, bdata::BoundaryData,
209+
new_ctx::GridContext{dim}, new_bdata::BoundaryData, K) where {dim}
210+
I, J ,V = findnz(K)
211+
212+
# Here I,J are in pdof order for new_ctx
213+
bcdof_to_node_new = bcdof_to_node(new_ctx, new_bdata)
214+
node_to_bcdof_old = node_to_bcdof(old_ctx, bdata)
215+
I .= node_to_bcdof_old[bcdof_to_node_new[I]]
216+
J .= node_to_bcdof_old[bcdof_to_node_new[J]]
217+
old_pdof_n = old_ctx.n - length(bdata.periodic_dofs_from)
218+
return sparse(I, J, V, old_pdof_n, old_pdof_n)
220219
end
221220

222-
function node_to_bcdof(ctx::GridContext{dim},bdata::BoundaryData) where {dim}
223-
n_nodes = ctx.n - length(bdata.periodic_dofs_from)
224-
bdata_table = BCTable(ctx,bdata)
225-
return bdata_table[ctx.node_to_dof]
221+
function node_to_bcdof(ctx::GridContext{dim}, bdata::BoundaryData) where {dim}
222+
n_nodes = ctx.n - length(bdata.periodic_dofs_from)
223+
bdata_table = BCTable(ctx, bdata)
224+
return bdata_table[ctx.node_to_dof]
226225
end
227226

228227
function bcdof_to_node(ctx::GridContext{dim},bdata::BoundaryData) where {dim}
229-
n_nodes = ctx.n - length(bdata.periodic_dofs_from)
230-
bdata_table = BCTable(ctx,bdata)
231-
result = zeros(Int,n_nodes)
232-
for i in 1:ctx.n
233-
if result[bdata_table[ctx.node_to_dof[i]]] == 0
234-
result[bdata_table[ctx.node_to_dof[i]]] = i
235-
end
228+
n_nodes = ctx.n - length(bdata.periodic_dofs_from)
229+
bdata_table = BCTable(ctx,bdata)
230+
result = zeros(Int,n_nodes)
231+
for i in 1:ctx.n
232+
if iszero(result[bdata_table[ctx.node_to_dof[i]]])
233+
result[bdata_table[ctx.node_to_dof[i]]] = i
236234
end
237-
return result
235+
end
236+
return result
238237
end
239238

240239

@@ -274,8 +273,8 @@ function adaptiveTOFutureGrid(ctx::GridContext{dim}, flow_map;
274273
#Do volume corrections
275274
#All values are in node order for new_ctx, which is the same as bcdof order for ctx2
276275
n_nodes = length(new_nodes_in_bcdof_order)
277-
vols_new = sum(assembleMassMatrix(new_ctx, bdata=new_bdata), dims=1)[1, node_to_bcdof(new_ctx, new_bdata)[1:n_nodes]]
278-
vols_old = sum(assembleMassMatrix(ctx, bdata=bdata), dims=1)[1, 1:n_nodes]
276+
vols_new = sum(assemble(Mass(), new_ctx, bdata=new_bdata), dims=1)[1, node_to_bcdof(new_ctx, new_bdata)[1:n_nodes]]
277+
vols_old = sum(assemble(Mass(), ctx, bdata=bdata), dims=1)[1, 1:n_nodes]
279278

280279
return new_ctx, new_bdata, vols_new ./ vols_old
281280
end
@@ -319,12 +318,12 @@ function adaptiveTOCollocation(ctx::GridContext{dim}, flow_map;
319318
throw(AssertionError("Invalid projection_method"))
320319
end
321320
if volume_preserving
322-
L = sparse(I, npoints, npoints)[node_to_bcdof(ctx,bdata)[bcdof_to_node(ctx_new,bdata_new)],:]
321+
L = sparse(I, npoints, npoints)[node_to_bcdof(ctx, bdata)[bcdof_to_node(ctx_new,bdata_new)],:]
323322
result = ALPHA_bc*L
324323
else
325324
volume_change_pdof = volume_change[bcdof_to_node(ctx,bdata)]
326-
K = assembleStiffnessMatrix(ctx,bdata=bdata)
327-
M = assembleMassMatrix(ctx,bdata=bdata)
325+
K = assemble(Stiffness(), ctx, bdata = bdata)
326+
M = assemble(Mass(), ctx, bdata = bdata)
328327
volume_change_pdof = (M - 1e-2K)\(M*volume_change_pdof)
329328
volume_change = volume_change_pdof[node_to_bcdof(ctx,bdata)]
330329

0 commit comments

Comments
 (0)