API of the Scapin library
Scapin.AbstractContinuousSpatialOperator
— TypeAbstractContinuousSpatialOperator
This is the root type of all operators that have not been discretized spatially. Such operators map continuous spatial fields x : ℝᵈ → ℝⁿ
to vector fields y : ℝᵈ → ℝᵐ
. In Fourier space, these operators are defined for an infinite set of wave-numbers.
Scapin.AbstractDiscreteSpatialOperator
— TypeAbstractDiscreteSpatialOperator
This abstract type defines operators that are spatially discretized.
Such operators map vector fields x : ℝᵈ → ℝⁿ
to vector fields y : ℝᵈ → ℝᵐ
.
This type extends AbstractSpatialOperator. As such, it implements dimensionality, size and ndims.
Discrete operators operate on discrete vector fields that are represented as arrays. The size of the input arrays is (n, N[1], …, N[d])
, where N[i]
is the number of grid cells in direction i = 1, …, d
. Note that the first (fast) index of the array is the component of the vector field. Similarly, the size of the output arrays is (m, N[1], …, N[d])
.
The tuple N
is referred to as the grid size, see grid_size.
Scapin.AbstractSpatialOperator
— TypeAbstractSpatialOperator
This is the root type of all operators defined in this library.
Such operators map vector fields x : ℝᵈ → ℝⁿ
to vector fields y : ℝᵈ → ℝᵐ
.
The number of spatial dimensions, d
, is referred to as the dimensionality of the operator – see dimensionality.
The pair (m, n) == (dimension of the input vector field, dimension of the output vector field)
is referred to as the size of the operator – see size. Consequently, ndims(F) == 2
for all F::AbstractSpatialOperator
.
Base.ndims
— Methodndims(F::AbstractSpatialOperator) -> 2
Return the number of dimensions of F
– see AbstractSpatialOperator. Since this is a linear operator that maps fields onto fields, the number of dimensions is always 2.
Scapin.apply
— Methodapply(ℱ, x)
Return the grid y
that results from applying the convolution operator ℱ
to the input grid x
.
The sizes of x
and y
are
size(x) == (N..., ncols)
size(y) == (N..., nrows)
where
N = grid_size(ℱ)
and
(nrows, ncols) == size(ℱ).
Scapin.apply_fourier!
— Functionapply_fourier!(ŷ, F, k, x̂) -> ŷ
Apply in-place operator F
to x̂
in Fourier space and return the modified array ŷ
. More specifically,
ŷ[:] = F̂(k) ⋅ x̂,
where k
, x̂
and ŷ
are column vectors: k
is the vector of spatial frequencies and x̂
(resp. ŷ
) is the Fourier mode of the input (resp. output), for the spatial frequency k
. The following must hold
size(k, 1) == dimensionality(F),
size(x̂, 1) == size(F, 2),
size(ŷ, 1) == size(F, 1).
The input vector x̂
is an array of type T
or complex(T)
, where T == eltype(ℱ)
. The output vector ŷ
can always be of type complex(T)
. When the Fourier coefficient ℱ̂(k)
of the operator is real, it might make sense to allow for ŷ
to be of type real(T)
. If this is disallowed, calling this function should raise an exception.
For F::AbstractContinuousSpatialOperator,
kwould typically be a real-valued vector of wave numbers, while for
F::AbstractDiscreteSpatialOperator,
k` would be a integer-valued vector of indices.
The present method must be implemented in such a way that aliasing ŷ
with x̂
is permitted. In other words, calling apply_fourier!(x̂, ℱ, k, x̂)
must always deliver the correct answer, provided that this operation is allowed type-wise [when x̂
is of type real(T)
].
Scapin.apply_fourier
— Methodapply_fourier(F, k, x̂)
Apply operator F
to x̂
in Fourier space and return the result. The returned vector is promoted to a complex type if necessary.
See apply_fourier!
Scapin.dimensionality
— Methoddimensionality(F)
Return the number of dimensions of the physical space that F
operates on – see AbstractSpatialOperator.
The default implementation assumes that dimensionality(typeof(F))
has been defined.
Scapin.fourier_matrix!
— Methodfourier_matrix!(F̂, ℱ, k) -> F̂
Compute in-place the k
-th mode of ℱ
, ℱ̂(k)
, as a matrix F̂
.
In general, the coefficients of F̂
should be s of type complex(eltype(ℱ))
. However, the Fourier coefficients of the operator ℱ might be real, in which case, eltype(F̂) == real(eltype(ℱ))
might be allowed.
The default implementation relies on apply_fourier! to build the matrix column-by-column. It might be inefficient.
Scapin.fourier_matrix
— Methodfourier_matrix(ℱ, k)
Return the k
-th mode of ℱ
, ℱ̂(k)
, as a matrix.
The coefficients of the returned matrix are of type complex(eltype(ℱ))
. For a different output type, use fourier_matrix!.
Scapin.grid_size
— Methodgrid_size(F)
Return the size of the grid the discrete operator F
operates on.
- Size of input arrays of
F
:(size(F, 2), grid_size(F)...)
, - Size of output arrays of
F
:(size(F, 1), grid_size(F)...)
.
Scapin.Bri17
Scapin.Bri17.DiscreteGreenOperatorBri17
— TypeFourier representation of the discrete Green operator introduced in [Bri17].
Scapin.Bri17.modal_stiffness!
— Methodmodal_stiffness!(K, n, N, h, C)
Compute the modal stiffness matrix K
in place, for the spatial frequency n
.
This function returns K
.
The grid is defined by its size, N
and spacing, h
. The spatial frequency is defined by n ∈ CartesianIndices(1:N[1], …, 1:N[d])
. The (homogeneous) constitutive material is specified by C
.
The modal stiffness matrix introduced above differs from the matrix initially introduced in Ref. DOI:10.1002/nme.5263 by a factor h[1] * … * h[d]
. More precisely,
K̂{Scapin} = h[1] * … * h[d] * K̂{10.1002/nme.5263}
Such rescaling makes the relation between modal and nodal stiffness operators more natural (the former is the DFT of the latter).
Scapin.Bri17.modal_stiffness
— Methodmodal_stiffness(n, N, h, C)
Return the modal stiffness matrix K
.
See modal_stiffness!
for a description of the parameters.
Scapin.Bri17.modal_strain_displacement!
— Methodmodal_strain_displacement!(b, n, N, h)
Compute the modal strain-displacement vector b
in place, for the spatial frequency n
.
This function returns b
.
The grid is defined by its size, N
and spacing, h
. The spatial frequency is defined by n ∈ CartesianIndices(1:N[1], …, 1:N[d])
.
Scapin.Bri17.modal_strain_displacement
— Methodmodal_strain_displacement(n, N, h)
Return the modal strain-displacement vector b
.
See modal_strain_displacement!
for a description of the parameters.
Scapin.Brick
Scapin.Brick.avg_gradient_operator
— Methodavg_gradient_operator(h)
Return the cell-average of the gradient operator.
Scapin.Brick.avg_strain_displacement_operator
— Methodavg_strain_displacement_operator(h)
Return the cell average of the strain-displacement operator.
Scapin.Brick.global_stiffness_operator
— Methodglobal_stiffness_operator(N, h, μ, ν)
Return the global stiffness operator for periodic, homogeneous elasticity.
The grid size is N
, the cell size is h
. The constitutive material is homogeneous, elastic linear and isotropic with stiffness C
.
The global stiffness operator K
is a 2d+2
-dimensional array of size (d, N[1], …, N[d], d, N[1], …, N[d])
, such that the strain energy of the system reads
U = u[i, p] * K[i, p, j, q] * u[j, q] / 2,
where
i, j ∈ {1, …, d}
: component indices,p, q ∈ CartesianIndices(1:N[1], …, 1:N[d])
: node indices,u[i, p]
:i
-th component of the displacement of nodep
.
Assembly of the global stiffness opertor is done under the assumption of periodicity.
Scapin.Brick.global_strain_displacement_operator
— Methodglobal_strain_displacement_operator(N, h)
Return the global strain-displacement operator for periodic boundary conditions.
The grid is defined by its size N
and its spacing h
.
The global strain-displacement operator B
is a d+2
-dimensional array of size (d, d, N[1], …, N[d])
, such that the average strain within element p
reads
ε[i, j, p] = B[i, j, p, k, q] * u[k, q],
where
i, j, k ∈ {1, …, d}
: component indices,p, q ∈ CartesianIndices(1:N[1], …, 1:N[d])
: node indices,ε[i, j, p]
:(i, j)
-th component of the average strain in elementp
,u[k, q]
:i
-th component of the displacement of nodeq
.
Assembly of the global strain-displacement operator is done under the assumption of periodicity.
Scapin.Brick.gradient_operator
— Methodgradient_operator(x, h)
Return the gradient operator at the specified point.
This function returns a (d+1)
dimensional array D
of size (d, 2, 2, …)
. If i
is the index of a component and p
the CartesianIndex
of the node, then D[i, p]
is the partial derivative of N[p]
w.r.t. x[i]
, evaluated at x
.
h
is the size of the brick element.
Scapin.Brick.integrate
— Methodintegrate(f, h)
Return the d
-dimensional integral of f
over (0, h[1]) × (0, h[2]) × … × (0, h[d])
.
Uses 2-point Gauss-Legendre integration (tensorized over the d
dimensions). f
must take a 1-dimensional array of size d
as unique input. If avg
is true
, the function returns the N
-dimensional average.
Scapin.Brick.shape
— Methodshape(x, h)
Return the value of the shape functions of the element, at the specified point.
This function returns a d
-dimensional array N
, such that N[p]
is the shape function associated with node p
, evaluated at x
. In particular, N[p]
evaluated at node q
is δ[p, q]
(Kronecker).
Scapin.Brick.stiffness_operator
— Methodstiffness_operator(h, C)
Return the stifness operator for the brick element of size h
, and Hooke material C
.
The stiffness operator K
delivers the strain energy associated to the nodal displacements u
U = u[i, p] * K[i, p, j, q] * u[j, q] / 2,
where i, j ∈ {1, …, d}
are component indices and p, q ∈ CartesianIndices(1:2, …, 1:2)
.
Scapin.Brick.strain_displacement_operator
— Methodstrain_displacement_operator(x, h)
Return the strain-displacement operator for the d
-dimensional brick element of size h
, evaluated at point x
.
This function returns a (d+3)
dimensional array B
of size (d, d, 2, …, 2, d)
. If p
is the CartesianIndex
of the node, and i
, j
, k
are component indices then, the interpolated (i, j)
component of the strain at x
reads
ε[i, j] = Σₖ Σₚ B[i, j, k, p] * u[k, p].
Scapin.Elasticity
Scapin.Elasticity.GreenOperatorHooke
— TypeContinuous Green operator related to Hooke materials.
Scapin.Elasticity.Hooke
— TypeHooke{d,T}
Isotropic, linear elastic material.
d
— number of spatial dimensionsT
— scalar typeμ::T
— shear modulusν::T
— Poisson ratioλ::T
— first Lamé coefficient
Regardless of the number of space dimensions, d
, the stress-strain relationship reads
σ = λ⋅tr(ε)I + 2μ⋅ε.
Material stability requires that μ > 0
and -1 < ν < 1/2
; these conditions are not enforced here. In other words, unstable materials can be defined.
In the current implementation, d = 2
refers to plane strain elasticity. For plane stresses, the true Poisson ratio ν
should be replaced with the fictitious ratio ν̃ = ν / (1 + ν)
.
Scapin.Elasticity.Hooke
— MethodHooke{d,T}(μ::T, ν::T)
Create a new instance of Hooke{d,T}
with shear modulus μ
and Poisson ratio ν
.
Base.eltype
— Methodeltype(type)
Return the type of the (scalar) elements the operator of given type
operates on in the real space (as opposed to the Fourier space). Note that this type may be complex!
Scapin.Elasticity.bulk_modulus
— Methodbulk_modulus(C::Hooke)
Return the bulk modulus κ
for the specified Hooke material.
For plane strain elasticity, κ = μ / (1 - 2ν)
and, for 3d elasticity κ = 2/3 μ (1 + ν) / (1 - 2ν)
.
Scapin.Grid
Scapin.Grid.cell_vertices
— Methodcell_vertices(d)
Return the local multi-indices of vertices of the d
-dimensional brick element.
This function returns an object 𝓛
of type CartesianIndices
. An element v ∈ 𝓛
represents the vertex with coordinates (x[1], …, x[d])
x[i] = (-1)^v[i] * h[i] / 2, i = 1, …, d
Scapin.Grid.cell_vertices
— Methodcell_vertices(p, N)
Return the global multi-indices of the vertices of a grid-cell.
The cell is specified through its CartesianIndex
, p
; the size of the grid is defined by N
.
This function returns a d
-dimensional array 𝒢
of CartesianIndex
, such that 𝒢[l]
is the global index of the vertex with local index l ∈ CartesianIndices(1:2, …, 1:2)
.
Note that periodic boundary conditions are used.