Skip to article frontmatterSkip to article content

In this section, we will look at the transformations between each of the components. Recall, we have a hierarchy of dependencies starting from the coordinates, to the domain, and lastly the field. So how we do find transformations between different fields?

Coordinate Transformations

x=T(x;θ)\mathbf{x}' = \boldsymbol{T}(\mathbf{x};\theta)

For example, we can transform coordinates from Cartesian to Spherical coordinates. There are other words for this, e.g., reprojection, resample, regrid.

Most of these are related to the CRS.


Pseudo-Code

Here, we

# define field
u: Field = ...

# get domain from field
u_domain: Domain = u.domain

# transform domain
new_domain: Domain = transform(domain)

# convert old domain to new domain
u_new: Field = field_domain_transform(u, new_domain)

Here is a special case whereby we use. This example is motivated by the rioxarray package.

# get dataset
ds_u: xr.Dataset = ...

# get associated CRS
crs_u: CRS = ...

# initialize new coordinate system
transformer: Callable = init_transformer("ESPG:...")

# transform
ds_a: xr.Dataset = transformer(ds_u)

Field Operators

Now, let’s say we are given two fields

u=u(x,t)xΩuRDstTuR+a=a(x,t)xΩaRDstTaR+\begin{aligned} \vec{\boldsymbol{u}}=\vec{\boldsymbol{u}}(\mathbf{x},t) && && \mathbf{x}\in\Omega_u\subseteq\mathbb{R}^{D_s} && t\in\mathcal{T}_u\subseteq\mathbb{R}^{+} \\ \vec{\boldsymbol{a}}=\vec{\boldsymbol{a}}(\mathbf{x},t) && && \mathbf{x}\in\Omega_a\subseteq\mathbb{R}^{D_s} && t\in\mathcal{T}_a\subseteq\mathbb{R}^{+} \end{aligned}

We are interested in learning a mapping from one field to another

a(x,t)=f[u](x,t)\boldsymbol{a}(\mathbf{x},t) = \boldsymbol{f}[\boldsymbol{u}](\mathbf{x},t)

Example 1: Variable-2-Variable

For example, we could learn an absolute mapping from temperature to humidity for a given region and time, i.e.

H=f(T)H = f(T)

Notice that there are no dependencies on space and time. So we assume that there is an absolute relationship between the two variables.

Another example is to learn a mapping of temperature, T

Tt+Δt=f(T,t)T_{t+\Delta t} = f(T, t)

Discretizations

  1. Transform u to the coordinate system of a

  2. Transform u to a

Ωa=fs(Ωu)\begin{aligned} \boldsymbol{\Omega}_a &= \boldsymbol{f}_s(\boldsymbol{\Omega}_u) \\ \end{aligned}

Everything is an interpolation/regression problem…until it’s not.

Operators


Space (Inside Convex)

“Interpolation”


Space (Outside Convex Hull)

“Extrapolation”


Time (Inside Convex)

Interpolation


Time (Outside Convex)

Forecasting


Spatiotemporal (Outside Convex)


Quantity

Examples

Operators

Let’s say we are given a field.

Field 1:u=u(x),xΩuRDsField 2:a=a(x),xΩaRDs\begin{aligned} \text{Field 1}: && && \vec{\boldsymbol{u}} &= \vec{\boldsymbol{u}}(\vec{\mathbf{x}}), \hspace{5mm} \vec{\mathbf{x}}\in\boldsymbol{\Omega}_u\subseteq\mathbb{R}^{D_s} \\ \text{Field 2}: && && \vec{\boldsymbol{a}} &= \vec{\boldsymbol{a}}(\vec{\mathbf{x}}), \hspace{5mm} \vec{\mathbf{x}}\in\boldsymbol{\Omega}_a\subseteq\mathbb{R}^{D_s} \end{aligned}
# create domain
domain_u: Domain = Domain(...)
domain_a: Domain = Domain(...)

# create field
u: Field = Field(domain_u, ...)
a: Field = Field(domain_a, ...)

We have a banach space:

Banach Space U:U={u:ΩuRDu}Banach Space A:A={a:ΩaRDa}\begin{aligned} \text{Banach Space U}: && && \mathcal{U} &=\left\{ \vec{\boldsymbol{u}}: \boldsymbol{\Omega}_u \rightarrow \mathbb{R}^{D_u} \right\} \\ \text{Banach Space A}: && && \mathcal{A} &= \left\{ \vec{\boldsymbol{a}}: \boldsymbol{\Omega}_a \rightarrow \mathbb{R}^{D_a} \right\} \end{aligned}

Given some Observations

Observations:D={U,A}\begin{aligned} \text{Observations}: && && \mathcal{D} &= \left\{ \mathcal{U},\mathcal{A} \right\} \end{aligned}

We assume that there exists some operator, T\boldsymbol{T}, which maps one banach space to another.

Operator:T:UAData:D={U,T(U)}\begin{aligned} \text{Operator}: && && \boldsymbol{T} &: \mathcal{U} \rightarrow \mathcal{A}\\ \text{Data}: && && \mathcal{D} &= \left\{ \mathcal{U}, \boldsymbol{T}(\mathcal{U}) \right\} \end{aligned}

Now, we can try to find some parameterized operator that is approximately equal to the true operator, i.e., TTθ\boldsymbol{T}\approx \boldsymbol{T_\theta}.

Parameterized Operator:Tθ:U×ΘA\begin{aligned} \text{Parameterized Operator}: && && \boldsymbol{T_\theta} &: \mathcal{U} \times \mathcal{\Theta} \rightarrow \mathcal{A}\\ \end{aligned}

Empirical Risk Minimization

θ=argminθEuμ[ATθ(U,θ)22]\boldsymbol{\theta}^* = \underset{\theta}{\text{argmin}} \hspace{2mm} \mathbb{E}_{\mathcal{u}\sim\mu} \left[ ||\mathcal{A} - \boldsymbol{T_\theta}(\mathcal{U},\boldsymbol{\theta}) ||_2^2\right]

Bayesian Inference

p(MD)=1Zp(DM)p(M)p(\mathcal{M}|\mathcal{D}) = \frac{1}{Z} p(\mathcal{D}|\mathcal{M})p(\mathcal{M})

Pseudo-Code

# initialize fields
u: ContinuousField = ...
a: ContinuousField = ...

# initialize operator
operator: Callable =
params: PyTree ==

# apply operator
a_hat: ContinuousField = operator(u: Field=u, params: Params=params)

# checks
assert a_hat.domain == a.domain
assert a_hat.values == a.values

Case Omega Domain Case - Functional Output Domain Case -

Sources:


Decomposition

We can divide the operations into the following: 1) space, 2) time, and 3) quantity.


Space (Inside Convex)

Coordinate System Transformations

Example: Spherical-Cartesian-Cylindrical

Example: Geodetic

Example: Geodetic-ENU-ECEF

Same Domain

Different Domain

Unstructured Domains


Quantity


Time


Examples

Forecasting

PDE Operator

# initialize domain
domain: Domain = ...

# initialize fields
Field = Discrete & Structured & Regular
u_0: Field = Field(domain, ...)
u_t: Field = Field(domain, ...)

# initialize finite difference operator
pde_model: Model = ...
pde_params: PyTree = ...
ode_solver: Solver = ...

# apply operator
u_t_hat: DiscretizedField = ode_solver(
	pde_model, pde_params, u_0, [t0, t1], dt
)

# checks
assert u_t_hat.domain == u_t.domain
assert u_t_hat.values == u_t.values

Neural Operators

# initialize domain
domain: Domain = ...

# initialize fields
Field = Continuous & Structured & (Regular | Irregular)
u_t0: Field = Field(domain, ...)
u_t1: Field = Field(domain, ...)

# initialize fourier neural operator
operator: Model =
params: PyTree =

# apply operator
a_hat: ContinuousField = operator(u: Field=u, params: Params=params)

# checks
assert a_hat.domain == a.domain
assert a_hat.values == a.values

Spatial Domain Transformation

# initialize domains
domain_u: Domain = Domain(...)
domain_a: Domain = Domain(...)

# initialize fields
Field = (Continuous | Continuous) & Structured & (Regular | Irregular)
u: Field = Field(domain_u, ...)
a: Field = Field(domain_a, ...)

# initialize domain transformation
operator: Model = ...
params: PyTree = ...

# apply operator
domain_a_hat: Domain = operator(u, domain_a, params) 

# checks
assert u_t_hat.domain == u_t.domain
assert u_t_hat.values == u_t.values

In this section, we will break down the

Variables: Variable + Coordinates + Domain + Space Transformation: Variable I --> Variable II

Examples:

Problems:


Functional

Motivating Examples


Heterogeneous Domains

Ωu=Tθ(Ωa)\Omega_u = \boldsymbol{T_\theta}\left(\Omega_a\right)

Examples:

Simple Example

# obtain values
a: Array = ...
u: Array = ...

# initialize transformation + params
params: Params = ...
transform: Callable = ...

# apply transformation
u_hat: Array = transform(a, params)

# test to ensure it is equal
np.testing.assert_array_equal(u, u_hat)
# Domain 1
field_a: Field = Field(values_a, domain_a)
field_u: Field = Field(values_u, domain_u)

# initialize interpolator
a_to_u_f: Callable = FieldInterpolator(field_u.values, field_u.coords)

# apply interpolator
field_a_on_u: Field = a_to_u_f(field_a.values, field_a.coords)

Unpaired Domains

PDE

Geo-FNO

# Get input data
# [H,W]
X = …
# create interpolation layer
num_dims = 3 # input channel is 3: (a(x, y), x, y)
weights = random(size=(num_dims, num_outputs))  
# create grid coordinates [H,W,2]
grid = get_normalized_grid_coords(x.shape)
# Concaténate Data
# [H,W],[H,W,2] —> [H,W,3]
x = torch.cat((x, grid), dim=-1)
# Change Coordinates
# [H,W,3] —> [H,W,Dz]
x = einsum(“…c,cd->…d”, x,weights)
# Apply Operator
# [H,W,Dz] —-> [H,W,Dza]
a = Operator(X)
# Apply Inverse Operator
# [H,W,Dza] —> [H,W,C]
a = einsum(“…d,cd->…c”, x,weights)
# Apply Learned Inverse Operator
# [H,W,Dza] —> [H,W]
a = einsum(“…d,cd->…1”, x,weights_)