-
-
Notifications
You must be signed in to change notification settings - Fork 72
Split Q Multidimensional BCs [Frozen, pending review] #135
Conversation
…ypes from AffineBC{T,V} to AffineBC{T} because V is always created as a Vector{T}
…ome more flexible constructors for MultiDimBC
…ms and is not strictly nessecary
…etindex for padded arrays
| The non identity part of Qa is qa:= -b`₁/b0 = -β.*s[2:end]/(α+β*s[1]/Δx). The constant part is Qb = γ/(α+β*s[1]/Δx) | ||
| do the same at the other boundary (amounts to a flip of s[2:end], with the other set of boundary coeffs) | ||
| """ | ||
| struct RobinBC{T, V<:AbstractVector{T}} <: AffineBC{T,V} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leave this to AbstractVector, as an optimization down the line may be to use StaticVector here.
| Array(A) | ||
| end | ||
| #implement Neumann and Dirichlet as special cases of RobinBC | ||
| NeumannBC(α::AbstractVector{T}, dx::Union{AbstractVector{T}, T}, order = 1) where T = RobinBC([zero(T), one(T), α[1]], [zero(T), one(T), α[2]], dx, order) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason to allocate the vectors here. Should be a tuple. Let's mark this as a small improvement to make in a follow up PR.
| Qx Qy and Qz can be passed in any order, as long as there is exactly one BC operator that extends each dimension. | ||
| """ | ||
| function compose(BCs...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I see why there's a compose function
| Qx, Qy, Qz... = Neumann0BC(T::Type, (dx::Vector, dy::Vector, dz::Vector ...), approximation_order, size(u)) | ||
| where T is the element type of the domain to be extended | ||
| """ | ||
| MultiDimBC(BC::Array{B,N}, dim::Integer) where {N, B<:AtomicBC} = MultiDimDirectionalBC{gettype(BC[1]), B, dim, N+1, N}(BC) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dim may need to be a type parameter in order for it to infer well for dispatch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does something like:
foo(x, T) where T = bar{T}(x)
Work in julia? I thought that the parameters had to be inferred from argument types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`foo{T}(x) where T = ...
ChrisRackauckas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are still things that I think should get changed, but this is very good and I don't want it to go stale, so let's merge it in and open an issue to change the last few details. Very nicely done!
Similar to the other PR, but now the
MultiDimBCoperators only act along a specified axis, stored in the type information. LikewiseQ*unow returns aBoundaryPaddedArraythat extends only along the axis ofQ. There is also support for composed Q, that extends on all dimensions at once, and aComposedBoundaryPaddedArray.There is now an additional constructor which makes it easy to extend an atomic BC to act on a whole dimension, as well as a constructor which will generate all operators needed to extend an atomic BC to the whole domain.
Atomic Boundary Conditions
An atomic boundary condition can be thought of as acting on a single vector, applying boundary conditions at each end.
The currently implemented
AtomicBCs are as follows:RobinBC: Implements a robin boundary condition, to any approximation order for the derivative.
Usage:
RobinBC([αl, βl, γl], [αr, βr, γr], dx, approximation_order::Int)corresponding to a BC of the formαl*u[0] + βl*u'[0] = γl,αr*u[end+1] + βr*u'[end+1] = γr. For a uniform grid,dxshould be a value, for nonuniform it should be the vector of step sizes forx.DirichletBC and Dirichlet0BC: Implemented as specialised constructors to RobinBC.
Usage:
DirichletBC(αl, αr)corresponding to a BC of the formu[0] = αl,u[end+1] = αr.Dirichlet0BC(T::Type)gives a bc where αl and αr are eual to 0. For a uniform grid,dxshould be a value, for nonuniform it should be the vector of step sizes forx.NeumannBC and Neumann0BC: Implemented as specialised constructors to RobinBC.
Usage:
NeumannBC([αl, αr], dx, approximation_order)corresponding to a BC of the formu'[0] = αl,u'[end+1] = αr.Neumann0BC(dx, approximation_order)gives a bc where αl and αr are eual to 0. For a uniform grid,dxshould be a value, for nonuniform it should be the vector of step sizes forx.GeneralBC: A generalization of the RobinBC, including derivative terms up to any order.
Usage:
GeneralBC(αl::Vector{T}, αr::Vector{T}, dx, approximation_order)Represents a condition of the formαl[1] + αl[2]u[0] + αl[3]u'[0] + αl[4]u''[0]+... = 0, for the left boundary, andαr[1] + αr[2]u[end] + αr[3]u'[end] + αr[4]u''[end]+... = 0for the right boundary.αlandαrcan be of any length greater than 1, and don't have to be the same length in general. For a uniform grid,dxshould be a value, for nonuniform it should be the vector of step sizes forx.PeriodicBC: Wraps the domain around such that
u[0] = u[end]andu[end+1] = u[1].Usage:
PeriodicBC{T}()Boundary Conditions on Multi-Dimensional Domains
A
MultiDimBCapplies a boundary condition along the entire boundary orthoganal to a dimension of some discretized domain.As an example: If you have an array
awithsize(a) = (n, m, o), then a MultiDimBC that acts on the first dimension of a would create an extension ofsize(m,o)at both the lower and upper index end of the 1st dimension ofa.There are some constructors that make it easy to apply the same AtomicBC along the entire boundary of a domain:
You may want to apply different boundary conditions on different parts of a boundary. That can be achieved by building an
Array{AtomicBC{T}, N-1}(wherea isa Array{T, N}) of Atomic BCs withsize = size(a)[setdiff(1:N, dim)], and passing that to MultiDimBC like so:There is also an easy constructor that extends the same atomic BC to cover all boundaries at once (
amust be defined on a uniform grid if you want to use a Neumann, Neumann0, Robin or General boundary condition, these have special constructors for the non uniform grid case):On a non uniform grid, for the above mentioned boundary types, you can cover the whole boundary on all dimensions like this:
There are analogously defined constructors for the other above mentioned BCs, simply replace the usual
dxwith a tuple containing vectors of the step sizes for each dimension, and appendsize(a)to the argument signature.Another constructor for PeriodicBC:
ComposedBCOperators/BoundaryPaddedArrays
It is also possible to create an operator that extends all boundaries at once - a ComposedMultiDimBC. This supports syntax like
(Lxx + Lyy + Lzz)Qas opposed to the split representation which can be used likeLxxQx + LyyQy +LzzQz.One goes between these two representations like this:
Also works with BoundaryPaddedArrays, if Ax, Ay, and Az are padded arrays extended in each of the dimensions respectively:
compose() can accept padded arrays / bc operators in any order, as long as there is exactly 1 array/operator that extends on each dimension. An array/operator must be supplied for each dimension in order for compose to work properly.
The 2 representations are equivalent, but the composed representation is faster for some types of solve [which?].
getindexworks as expected withBoundaryPaddedArrays andComposedBoundaryPaddedArrays, for any number of dimensions. Colon indexing is supported for the BoundaryPaddedArray, but only on the extended dimension OR the other dimensions. It is not supported for the ComposedBoundaryPaddedArray.It is recomended when writing fast algorithms that operate on (Composed)BoundaryPaddedArrays to index in to the fields of the padded array directly, rather than relying on the
getindexfunction for this type as it is quite slow.Here is the BoundaryPaddedArray for reference (D is axis of extension):
And the ComposedBoundaryPaddedArray:
Concretizations are now implemented for the multi dimensional BC operators.
Per the suggestion from @ajozefiak, the dimensions of the affine parts are permuted so that they point along the dimension of extension for the operator.
Array(Q::SingleLayerMultiDimBC)- the split Q type, returns a tuple, the first element of which is an array of the shape of the boundary, filled with the linear operator parts of the respective Atomic BCs, the second element is an array of affine parts.Array(Q::ComposedMultiDimBC)returns a tuple with length equal to the number of dimensions, each element of which is a tuple as described in the paragraph above, corresponding to the BCs for each dimension.There should be a way to unpack the array of Q_Ls in to some huge block banded matrix, I'm having trouble working out how though.
Sparse concretization is also implemented with methods of
sparse()andSparseMatrixCSC()BandedMatrix()concretization is now implemented for all BCs.This is not recommended for PeriodicBC though since its matrix has entries in the upper right and lower left corners - This could be moved to the affine part, but would include the difficulties of
BridgeBC(No longer in this PR)There is a utility function
perpsize(a::AbstractArray, dim::Int)which returns the size ofaperpendicular to dimensiondim