API of the Scapin library

Scapin.AbstractContinuousSpatialOperatorType

AbstractContinuousSpatialOperator

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.

source
Scapin.AbstractDiscreteSpatialOperatorType

AbstractDiscreteSpatialOperator

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.

source
Scapin.AbstractSpatialOperatorType

AbstractSpatialOperator

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.

source
Base.ndimsMethod

ndims(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.

source
Scapin.applyMethod
apply(ℱ, 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(ℱ).
source
Scapin.apply_fourier!Function
apply_fourier!(ŷ, F, k, x̂) -> ŷ

Apply in-place operator F to in Fourier space and return the modified array . More specifically,

ŷ[:] = F̂(k) ⋅ x̂,

where k, and are column vectors: k is the vector of spatial frequencies and (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 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.

Continuous and discrete operators

For F::AbstractContinuousSpatialOperator,kwould typically be a real-valued vector of wave numbers, while forF::AbstractDiscreteSpatialOperator,k` would be a integer-valued vector of indices.

Overriding the input vector

The present method must be implemented in such a way that aliasing with 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 is of type real(T)].

source
Scapin.apply_fourierMethod
apply_fourier(F, k, x̂)

Apply operator F to in Fourier space and return the result. The returned vector is promoted to a complex type if necessary.

See apply_fourier!

source
Scapin.fourier_matrix!Method
fourier_matrix!(F̂, ℱ, k) -> F̂

Compute in-place the k-th mode of , ℱ̂(k), as a matrix .

In general, the coefficients of 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.

Performance of the default implementation

The default implementation relies on apply_fourier! to build the matrix column-by-column. It might be inefficient.

source
Scapin.fourier_matrixMethod
fourier_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!.

source
Scapin.grid_sizeMethod
grid_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)...).
source

Scapin.Bri17

Scapin.Bri17.modal_stiffness!Method
modal_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.

Scaling of the modal stiffness matrix

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).

source
Scapin.Bri17.modal_strain_displacement!Method
modal_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]).

source

Scapin.Brick

Scapin.Brick.global_stiffness_operatorMethod
global_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 node p.
Note

Assembly of the global stiffness opertor is done under the assumption of periodicity.

source
Scapin.Brick.global_strain_displacement_operatorMethod
global_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 element p,
  • u[k, q]: i-th component of the displacement of node q.
Note

Assembly of the global strain-displacement operator is done under the assumption of periodicity.

source
Scapin.Brick.gradient_operatorMethod
gradient_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.

source
Scapin.Brick.integrateMethod
integrate(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.

source
Scapin.Brick.shapeMethod
shape(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).

source
Scapin.Brick.stiffness_operatorMethod
stiffness_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).

source
Scapin.Brick.strain_displacement_operatorMethod
strain_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].
source

Scapin.Elasticity

Scapin.Elasticity.HookeType
Hooke{d,T}

Isotropic, linear elastic material.

  • d — number of spatial dimensions
  • T — 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

Material stability requires that μ > 0 and -1 < ν < 1/2; these conditions are not enforced here. In other words, unstable materials can be defined.

Plane stresses vs. plane strains

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 + ν).

source
Base.eltypeMethod

eltype(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!

source
Scapin.Elasticity.bulk_modulusMethod
bulk_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ν).

source

Scapin.Grid

Scapin.Grid.cell_verticesMethod
cell_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

See Geometry of the reference brick element.

source
Scapin.Grid.cell_verticesMethod
cell_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.

source