`CalculustCore.Domains`

— ModuleAbstract Domain Interface

`CalculustCore.Domains.AbstractDomain`

— Type`abstract type AbstractDomain{T<:Number, D}`

`D`

-dimensional domain of type `T`

`CalculustCore.Domains.BoxedDomain`

— Type`struct ProductDomain{T, D, var"#s10305"<:Tuple{Vararg{IntervalDomain, D}}} <: CalculustCore.Domains.AbstractDomain{T, D}`

Logically rectangular product domain

`CalculustCore.Domains.DomainMap`

— Type`struct DomainMap{Tm}`

`CalculustCore.Domains.DomainMap`

— Method```
DomainMap(mapping; isseparable, isrescaling)
```

Deform `AbstractDomain`

`dom`

via mapping

`CalculustCore.Domains.IntervalDomain`

— Type`struct IntervalDomain{T, Tp} <: CalculustCore.Domains.AbstractDomain{T, 1}`

`CalculustCore.Domains.IntervalDomain`

— Method```
IntervalDomain(x0, x1; periodic, tag, boundary_tags)
```

1D open interval containing `x`

for `x0 < x < x1`

.

`CalculustCore.Domains.MappedDomain`

— Type`struct MappedDomain{T, D, TD, TM} <: CalculustCore.Domains.AbstractDomain{T, D}`

`CalculustCore.Domains.NullDomain`

— Type`struct NullDomain <: CalculustCore.Domains.AbstractDomain{Bool, -1}`

Domain representing the empty set, ∅. Dimension set to `-1`

.

`CalculustCore.Domains.PointDomain`

— Type`struct PointDomain{T<:Number} <: CalculustCore.Domains.AbstractDomain{T<:Number, 0}`

`CalculustCore.Domains.PointDomain`

— Method```
PointDomain(x; tag)
```

Zero-dimensional domain representing a point.

`CalculustCore.Domains.ProductDomain`

— Type`struct ProductDomain{T, D, Tdom} <: CalculustCore.Domains.AbstractDomain{T, D}`

`Base.ndims`

— Method```
ndims(_)
```

Dimension of domain

`CalculustCore.Domains.AnnulusDomain`

— Method```
AnnulusDomain(r0, r1)
```

Annulus domain with internal radius `r0`

, and external radius `r1`

.

`CalculustCore.Domains.BoxDomain`

— Method```
BoxDomain(endpoints; periodic_dims, tag, boundary_tags)
```

Creates a `D`

-dimensional box domain with endpoints given by `endpoints`

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

**Example**

```
julia> domain = BoxDomain(0, 1, 2, 3; periodic_dims=2)
(0, 1) × (2, 3)
julia> boundary_tags(domain)
(:D1_inf, :D1_sup, :D2_periodic, :D2_periodic)
```

`CalculustCore.Domains.ChebyshevDomain`

— Method```
ChebyshevDomain(D; kwargs...)
```

Creates a `D`

-dimensional box domain with endpoints at `-1.0`

, `1.0`

in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.FixedEndpointBoxDomain`

— Method```
FixedEndpointBoxDomain(D, x0, x1; kwargs...)
```

Creates a `D`

-dimensional box domain with the same end points in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.FourierDomain`

— Method```
FourierDomain(D; kwargs...)
```

Creates a `D`

-dimensional box domain that is periodic in all directions. The domain spans from `-π`

to `π`

in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.IdentityMap`

— Method```
IdentityMap()
```

The Identity `DomainMap`

`CalculustCore.Domains.PolarMap`

— Method```
PolarMap()
```

2D Polar transformation

`CalculustCore.Domains.UnitBoxDomain`

— Method```
UnitBoxDomain(D; kwargs...)
```

Creates a `D`

-dimensional, unit sized box domain with endpoints at `0.0`

, `1.0`

in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.UnitCubeDomain`

— Method```
UnitCubeDomain(; kwargs...)
```

Creates a unit-sized 3D cube domain spanning from `0.0`

to `1.0`

in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.UnitIntervalDomain`

— Method```
UnitIntervalDomain(; kwargs...)
```

Creates a unit-sized 1D interval domain spanning from `0.0`

to `1.0`

.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.UnitSquareDomain`

— Method```
UnitSquareDomain(; kwargs...)
```

Creates a unit-sized 2D square domain spanning from `0.0`

to `1.0`

in each dimension.

**Keyword Arguments**

`periodic_dims`

: List of periodic dimensions in`1:D`

. Defaults to none.`tag`

: Domain tag (symbol) defaults to`:Interior`

.`boundary_tags`

: List of the`2D`

boundary tags. By default, periodic boundaries are tagged`:Dk_periodic`

where`k`

refers to the`k`

th dimension, and aperiodic boundaries are tagged as`:Dk_inf`

,`:Dk_sup`

corresponding to the infimum and supremum in the`k`

th dimension.

`CalculustCore.Domains.boundaries`

— Function`boundaries(dom)`

Returns tuple of domain boundaries of `dom`

as `D-1`

domains.

Must overload.

`CalculustCore.Domains.boundary_tags`

— Method```
boundary_tags(dom)
```

Returns tuple of tags corresponding to `boundaries(dom)`

.

`CalculustCore.Domains.bounding_box`

— Function`bounding_box(dom)`

Returns bounding box of domain as a BoxDomain of the same dimension.

Must overload.

`CalculustCore.Domains.deform`

— Function```
deform(domain; ...)
deform(domain, mapping; isseparable, isrescaling)
```

Deform `domain`

via `mapping`

, which expects the function signature

`mapping(r1, ..., rD) = x1, ..., xD`

where the inputs and outputs are `NTuple{D, <:AbstractArray}`

.

**Keyword Arguments**

`isrescaling`

- Set to`true`

if`mapping`

is a rescaling operation, i.e.x1 = a1 + λ1 × x1(r1),

...,

xD = aD + λD × xD(rD)

`isseparable`

- Set to`true`

if`mapping`

is separable, i.e.x1 = x1(r1),

...,

xD = xD(rD)

TODO - make types for AffineMap, LinearMap, SeparableMap, Transation, Rotation TODO - check `static_hasmethod`

in constructor

`CalculustCore.Domains.deform`

— Method```
deform(domain, mapping)
```

Deform `domain`

via `mapping`

.

`CalculustCore.Domains.domain_tag`

— Function`domain_tag(dom)`

Returns metadata tag corresponding to the interior of domain `dom`

.

Must overload

`CalculustCore.Domains.expanse`

— Method```
expanse(dom)
```

Returns size of domain bounding box.

Overload if `expanse`

is not defined for `bounding_box(dom)`

.

`CalculustCore.Domains.isperiodic`

— Function`isperiodic(dom)`

Returns NTuple{D, Bool} indicating if the domain in periodic along each dimension.

`CalculustCore.Domains.num_boundaries`

— Method`num_boundaries(dom)`

Returns number of boundaries in domain `dom`

.

`LinearAlgebra.:×`

— MethodTake cartesian product of `AbstractDomain`

s `doms`

```
×(doms)
```

`CalculustCore.Spaces`

— ModuleAbstract interface for function spaces

`CalculustCore.Spaces.AbstractDiscretization`

— Type`abstract type AbstractDiscretization`

Spatial discretizations scheme

`CalculustCore.Spaces.AbstractSpace`

— Type`abstract type AbstractSpace{T, D}`

Function space over a `D`

-Dimensional domain

`CalculustCore.Spaces.Collocation`

— Type`struct Collocation <: CalculustCore.Spaces.AbstractDiscretization`

A `Collocation`

discretization is when the strong form of the equation is discretized as it is.

`CalculustCore.Spaces.ComposedUpdateFunction`

— Type(f1 ∘ f2)(v, u, p, t) with caching

`CalculustCore.Spaces.DeformedSpace`

— Type`struct DeformedSpace{T, D, Tspace<:CalculustCore.Spaces.AbstractSpace{T, D}, Tgrid, Tjacmat, Tjacimat, Tjac, Tjaci} <: CalculustCore.Spaces.AbstractSpace{T, D}`

Deform domain, compute Jacobian of transformation, and its inverse

given 2D mapping

x = x(r,s), y = y(r,s)

compute

dXdR = [xr xs], dRdX = [rx ry], J = det(dXdR), Jinv = det(dRdX) [yr ys] [sx sy]

`CalculustCore.Spaces.Galerkin`

— Type`struct Galerkin <: CalculustCore.Spaces.AbstractDiscretization`

The `Galerkin`

discretization is a weighted residual method where the trial space is equal to the test space.

`CalculustCore.Spaces.TransformedSpace`

— TypeLazy wrapper for transforming

`physical space -> modal space`

`Base.length`

— Method```
length(V)
```

length of vector in space

`Base.ndims`

— Method```
ndims(_)
```

Dimension of underlying domain

`Base.size`

— Method```
size(V, d)
```

get number of points in `d`

th dimension

`CalculustCore.Spaces._transp`

— Method```
_transp(v, _)
```

```
[Dx --> [Dx Dy]
Dy]
```

`CalculustCore.Spaces._transp`

— Method```
_transp(v, _)
```

```
[Dx --> [Dx' Dy']
Dy]
```

`CalculustCore.Spaces.advectionOp`

— Method```
advectionOp(
vels,
V,
discr;
vel_update_funcs,
vel_update_funcs!
)
```

Advection Operator: (v⃗⋅∇)⋅

for v,u,T in H¹₀(Ω)

(v,(u⃗⋅∇)T) = (v,ux*∂xT + uy*∂yT)

` = v' *B*(ux*∂xT + uy*∂yT)`

implemented as

(u⃗⋅∇)T = ux*∂xT + uy*∂yT

```
= [ux uy] * [Dx] T
[Dx]
```

`CalculustCore.Spaces.advectionOp`

— Method```
advectionOp(vels, V, discr, Vd; ...)
advectionOp(vels, V, discr, Vd, J; vel_update_funcs)
```

When forming nonlinear operators...

`CalculustCore.Spaces.advectionOp`

— Method```
advectionOp(vels, V, discr, Vd; ...)
advectionOp(vels, V, discr, Vd, J; vel_update_funcs)
```

`Galerkin`

discretizations suppport dealiased implementation of vector calculus operations where integration is performed in a(usually higher order) space, `Vd`

. This is referred to as over-integration. If `Vd`

is not provided, integration is done in `V`

. `J`

is the grid-to-grid interpolation operator from `V`

to `Vd`

. If `J`

is not provided, it is recomputed. If `Vd == V`

, then `J`

becomes `IdentityOperator(V)`

.

ux,uy, ∇T are interpolated to a grid with higher polynomial order for dealiasing (over-integration) so we don't commit any "variational crimes"

`CalculustCore.Spaces.biharmonicOp`

— Function`biharmonicOp(V::AbstractSpace, discr::AbstractDiscretization)`

Biharmonic Operator: Δ²

Represents the Biharmonic opeator over `V`

per discretization scheme `discr`

.

`CalculustCore.Spaces.boundary_nodes`

— Function`boundary_nodes(V::AbstractSpace)`

Get indices of boudnary nodes

`CalculustCore.Spaces.diffusionOp`

— Method`diffusionOp(ν::Number, V::AbstractSpace, discr::AbstractDiscretization)`

Diffusion operator: -νΔ

Returns the negative Laplace Operator scaled by diffusion coefficient `ν`

. `ν`

can be updated per `ν_update_func`

which expects the same signature as `SciMLOperators.ScalarOperator`

. All positional arguments besides `ν`

are passed down to `laplaceOp`

to form the negative lapalcian.

`CalculustCore.Spaces.diffusionOp`

— Method```
diffusionOp(ν, V, discr; ν_update_func)
```

Diffusion operator: -∇⋅(ν∇⋅)

Returns the diffusion operator where `ν`

is the space-varying diffusion coefficient in `V`

. `ν`

can be updated per `ν_update_func`

which expets the same signature as `SciMLOperators.DiagonalOperator`

.

It is assumed that `ν`

is a function in space `V`

. However, if `V`

is a transformed space, then `ν`

is a function in the physical space, i.e. `transform(V)`

.

`CalculustCore.Spaces.diffusionOp`

— Method```
diffusionOp(ν, V, discr, Vd; ...)
diffusionOp(ν, V, discr, Vd, J; ν_update_func)
```

`Galerkin`

discretizations suppport dealiased implementation of vector calculus operations where integration is performed in a(usually higher order) space, `Vd`

. This is referred to as over-integration. If `Vd`

is not provided, integration is done in `V`

. `J`

is the grid-to-grid interpolation operator from `V`

to `Vd`

. If `J`

is not provided, it is recomputed. If `Vd == V`

, then `J`

becomes `IdentityOperator(V)`

.

`CalculustCore.Spaces.divergenceOp`

— Function`divergenceOp(V::AbstractSpace, discr::AbstractDiscretization)`

Divergence Operator: ∇⋅

`CalculustCore.Spaces.domain`

— Function`domain(V::AbstractSpace)`

Get domain underlying `V`

`CalculustCore.Spaces.forcingOp`

— Method```
forcingOp(f, V, discr; f_update_func, f_update_func!)
```

Added forcing as an operator.

F = forcingOp(f) L = A + F

F(u) = 0 * u + M * f L(u) = A * u + M * f

`CalculustCore.Spaces.form_transform`

— Function`form_transform(V::AbstractSpace, input::AbstractVecOrMat; [kwargs...])`

Form transform operator given by `transformOp(V)`

that may be applied to the provided `input`

prototype array per keyword arguments `kwargs`

. `kwargs`

may include `p`

, the parameter set.

`CalculustCore.Spaces.global_numbering`

— Function`global_numbering(V::AbstractSpace)`

Get `AbstractArray`

of size `size(V)`

`CalculustCore.Spaces.gradientOp`

— Method`gradientOp(V::AbstractSpace{T, D}) where{T, D} -> [∂x1, ..., ∂xD]`

Gradient Operator: ∇

Returns a size `D`

`Vector`

of operators. The `d`

th operator corresponds to the linear transformation from a function to its partial derivative in the `d`

th dimension at the grid points of `V`

. Its `[ij]`

th entry is equal to the value of the derivative of the `j`

th basis function at the `i`

th grid point.

$[D]_{ij} = \partial_{x}\phi_{j}(x_i)$

`CalculustCore.Spaces.gradientOp`

— Method[Dx] * u = [rx sx] * [Dr] * u [Dy] = [ry sy] [Ds]

`CalculustCore.Spaces.hessianOp`

— Method`hessianOp(V::AbstractSpace{T, D}) where{T, D} ->`

$[∂x1∂x1 ... ∂x1∂xD, ... ∂xD∂x1 ... ∂xD∂xD ]$

Hessian Operator: ∇²

Returns a `D × D`

`Matrix`

of operators whose `[ij]`

th entry represents the transformation from a function to its second partial derivative in the `[ij]`

th directions.

`CalculustCore.Spaces.interp`

— Function`interp(points, u::AbstractVector, V::AbstractSpace)`

Interpolate function described by `u`

to points `points`

.

`CalculustCore.Spaces.interpOp`

— Function`interpOp(V1::AbstractSpace, V2::AbstractSpace)`

Grid to grid interpolation operator from `V1`

to `V2`

. Both spaces must share the same domain. Its `[ij]`

th entry is the value of the `j`

th basis function of `V1`

at the `i`

th grid point of `V2`

.

$[J]_{ij} = \phi_{j}(x_i)$

If `V1 == V2`

, we simply return the no-op `IdentityOperator(V1)`

.

`CalculustCore.Spaces.laplaceOp`

— Function`laplaceOp(V::AbstractSpace, discr::AbstractDiscretization)`

Laplace Operator: -Δ

Returns the negative Laplace operator over `V`

per discretization scheme `discr`

. As the Laplace operator (laplacian) is a negative-definitie operator, we return the negative laplacian which is a positive-definite operator.

`CalculustCore.Spaces.laplaceOp`

— Method(v,-∇² u) = (vx,ux) + (vy,uy)

```
:= a(v,u)
= v' * A * u
= (Q*R'*v)'*A_l*(Q*R'*u)
= v'*R*Q'*A_l*Q*R'*u
```

implemented as

R'R * QQ' * A*l * u*loc where A_l is

[Dr]'*[rx sx]'*[B 0]*[rx sx]*[Dr] [Ds] [ry sy] [0 B] [ry sy] [Ds]

= [Dr]' * [G11 G12]' * [Dr] [Ds] [G12 G22] [Ds]

`CalculustCore.Spaces.laplaceOp`

— Method```
laplaceOp(V, discr, Vd)
laplaceOp(V, discr, Vd, J)
```

`Galerkin`

discretizations suppport dealiased implementation of vector calculus operations where integration is performed in a(usually higher order) space, `Vd`

. This is referred to as over-integration. If `Vd`

is not provided, integration is done in `V`

. `J`

is the grid-to-grid interpolation operator from `V`

to `Vd`

. If `J`

is not provided, it is recomputed. If `Vd == V`

, then `J`

becomes `IdentityOperator(V)`

.

`CalculustCore.Spaces.laplaceOp`

— Method```
laplaceOp(V, discr)
```

For a `Galerkin`

discretization, the entries of the negative laplacian are given by

$[A]_{ij} = \int_\Omega \nabla\phi_i(x) \cdot \nabla\phi_j(x) dx$

for v,u in H¹₀(Ω)

(v,-∇² u) = (vx,ux) + (vy,uy)

` := a(v,u)`

`CalculustCore.Spaces.make_transform`

— Function```
make_transform(V; ...)
make_transform(V, input; kwargs...)
```

Returns a copy of `V`

with transform operator (given by `transformOp(V)`

) that may be applied to the provided `input`

prototype array per provided keyword arguments `kwargs`

.

`CalculustCore.Spaces.massOp`

— Function`massOp(V::AbstractSpace, discr::AbstractDiscretization)`

Mass Operator: ∫⋅dx

Represents the mass matrix for discretization scheme `discr`

.

For a `Galerkin`

discretization, the `[ij]`

th entry corresponds to the inner product of the `i`

th and `j`

th basis functions.

$[M]_{ij} = \int_\Omega \phi_i(x)\phi_j(x) dx = \langle \phi_i, \phi_j \rangle$

`CalculustCore.Spaces.massOp`

— MethodFor a `Collocation`

discretization, the mass operator returns `IdentityOperator(V)`

.

`CalculustCore.Spaces.massOp`

— Method```
massOp(V, discr, Vd)
massOp(V, discr, Vd, J)
```

`Galerkin`

discretizations suppport dealiased implementation of vector calculus operations where integration is performed in a(usually higher order) space, `Vd`

. This is referred to as over-integration. If `Vd`

is not provided, integration is done in `V`

. `J`

is the grid-to-grid interpolation operator from `V`

to `Vd`

. If `J`

is not provided, it is recomputed. If `Vd == V`

, then `J`

becomes `IdentityOperator(V)`

.

`CalculustCore.Spaces.mode_size`

— Function`mode_size(V::AbstractSpace)`

Get size of modal space. Equivalent to `size(transform(V))`

`CalculustCore.Spaces.modes`

— Function`modes(V::AbstractSpace)`

Get `NTuple{D}`

of vectors corresonding to the spectral grid

`CalculustCore.Spaces.points`

— Function`points(V::AbstractSpace)`

Get `NTuple{D}`

of vectors corresonding to the grid

`CalculustCore.Spaces.quadratures`

— Function`quadratures(V::AbstractSpace)`

Get underlying quadrature scheme

`CalculustCore.Spaces.transform`

— Function`transform(V::AbstractSpace)`

Lazily transforms between physical and modal space.

`CalculustCore.Spaces.transformOp`

— Function`transformOp(V::AbstractSpace)`

Get transform operator that takes vectors from `V`

to `transform(V)`

. To change transform operator to act on a different `AbstractVecOrMat`

subtype, call

`V = make_transform(V, input_prototype)`

`CalculustCore.Spaces.truncationOp`

— Function`truncationOp(V::AbstractSpace{T, D} , fracs::NTuple{D}) where{T, D}`

Truncation operator removes high-frequency modes in an input vector. `fracs[d]`

is the proprtion of the spectrum to be preserved in `d`

th dimension. In spectral space, the operator corresponds to diagonal scaling, where the first `fracs[d]`

of the spectrum (low frequency modes) is multiplied by unity, and the remainder (high-frequency modes) with zeros.

`CalculustCore.CalculustCore`

— Module**CalculustCore.jl**

A common interface for PDE solving

PDEs are messy: weird boundary conditions, moving domains, singular operators, you name it! And solvers more so with their discretization schemes, stability charectoristics, and performance tradeoffs. Not to mention the layers of complications added by the software stack, or computer architecture, or pre/post-processing pipelines.

Numerical PDE problems drive high-performance computing. The biggest supercomputers on the planet run physics simulations on millions of MPI ranks over years of wall-time. An optimized workflow is the difference between having a solution, or going home emptyhanded, and every ounce of performance has to be squeezed. As such, highly tuned software packages that specialize on a set class of problems dominate the market. With specializations, however, generalizability and interpoeratibility take a hit.

`CalculustCore.jl`

is written so that package authors won't need to write a method for `Δ`

(Laplacian) every time a new scheme for the gradient `∇`

(gradient) comes along. We provides abstractions over components of PDE solvers that reduce the amount of boilerplate code that any new solver would need, and improve interpoeratibility between solvers. Furthermore, a requisite for the developement of Machine Learning based PDE solvers is the ability to mix state of the art discretizations with large neural network models on a AD-compatible, accelerator-friendly test-bench. Julia's multiple-dispatch based programming model allows for abstractly-typed, composable code, that lets packages just plug-and-play. Engineers shouldn't waste their time reinventing the wheel, rather focus on what's new and interesting!

We believe switching from 'Fourier-spectral collocation method' to 'discontinuous Galerkin finite elements' should be a one-line change for the user. And users should not need to deal with inconsistent syntax between solvers for specifying boundary conditions, and forming vector-calculus operators.

Finally, `CalculustCore.jl`

is fully compatible with the `SciML.ai`

ecosystem, so after describing your problem, it should spit out the right `BoundaryValuePDEProblem`

or `ODEProblem`

that you can solve using the relevant `DiffEq`

package.

**Abstract Interfaces**

`CalculustCore.jl`

contains separate abstract interaces for multidimensional domains, vector-calculus operators, and function spaces. It is general enough that anybody can plug in their discretizations (ie define an inner-product operator, and gradient operator) and start solving boundary value problems, or time-evolution problems.

Once you plug in your discretizations, you can do a lot of cool things like apply any random deformations to the space. CalculustCore.jl translate all your vector calculus operators correctly. That means the same code could solve convection diffusion on a square as well as an annulus with no extra work and basically conserved accuracy.

`AbstractDomain`

interface

concrete types, Boundary tags

`deform`

- all the mapping stuff`\otimes`

concrete types

`IntervalDomain`

`BoxDomain`

`AbstractSpace`

interface

define these methods (grad, mass, common functions)

`deform`

`\otimes`

`transform`

`AbstractDiscretization`

interface

`GalerkinProjection`

`Collocation`

**Operator interface - SciMLOperators.jl**

`BoundaryValueProblem`

interface

Usually a rank-deficient systems

**Associated Packages**

**Roadmap**

[ ]

`AbstractDomain`

interface- [ ] Move concrete types to a separate package -
`PDEDomains.jl`

- [X] Logically rectangular domains
- [X] Deform domain
- [X] Boundary tags
- [ ] Interior tags (for multiphase flows, conjugate heat-transfer)
- [ ] Gordon Hall interpolation (transfinite interpolation)
- [ ] meshed domains
- [ ] signed distance geometries
- [ ] Time-varying domains
- [ ] Is it possibe to just use
`DomainSets.jl`

and add some metadata info?

- [ ] Move concrete types to a separate package -
[ ]

`AbstractField <: AbstractVector`

interface - special array types- [X] Spectral polynomial (nothing special needed)
- [X] transform-based spectral (fourier, cheby) (nothing special needed)
- [ ] Box/ full spectral elements

[ ] Operator interface - moved to

`SciMLOperators.jl`

- [X] linear algebra operations
- [X] lazy composition
- [X] can use array reductions
- [X] caching
- [ ] Gather-Scatter operator using
`NNlib`

- [ ] General interpolation operator on element-meshes

[ ] Spaces

[X] Deformed spaces

[ ] Tensor product spaces

[X] transformed space

[X] orthogonal polynomials -

`NodalPolynomialSpaces.jl`

[ ] Spectral with transforms

- [X] Fourier -
`FourierSpaces.jl`

- [ ] Cosine/ Sine spaces

- [X] Fourier -
[ ] Box, full spectral elements - create

`SpectralElementSpaces.jl`

[X] Create a distinction between

`Space`

, and`Discretization`

- [X] Space is how to represent functions
- [X] Discretization is how you form operators
- [ ] Rename "discretization" to "scheme" or "solve_scheme" or something. Because discretization is ambiguous. is it referring to spatial discretization? or time discretization? In this package we are using it as a "scheme" to form differential operators on a "discretized" space.
- [ ] Rename
`Galerkin`

->`GalerkinProjection`

for clarity - [ ] Flux handling in discontinuous galerkin/ finite volume
- [ ] all the shennanigans in stabalized finite elements

[ ] Boundary Condition interface (apply "this" boundary condition based on "that" domain boundary)

- [X] Dirichlet
- [X] Neumann
- [ ] Robin

[ ] Problems

[ ] Problem frontend with

`ModelingToolkit.jl`

[ ] Boundary Value Problems

- [ ] move boundary information to RHS
- [ ] dispatch to
`LinearSolve.jl`

- [ ] dispatch to
`NonlinearSolve.jl`

(after`LinearSolve.jl`

,`NonlinearSolve.jl`

integration)

[ ] Time-evolution problems

- [X] play nice with
`OrdinaryDiffEq`

- [ ] for implicit time-steppers, solve a BVP at every time step. impose boundary condition on the operator (wait for
`SciMLOperators`

,`OrdinaryDiffEq`

integration) - [ ] automatically spit out an ODEProblem

- [X] play nice with

`CalculustCore.cpu`

— Function`cpu(x)`

Transfer `x`

to CPU

`CalculustCore.gpu`

— Method`gpu(x)`

Transfer `x`

to GPU