tl;dr; How to use FEM tools to extract models needed to invert PDEs.
Context
In astrophysics, one is interested in so-called 'cosmic archeology' which involves recovering the origin of a given observation, while modelling its evolution. The idea is to be able to understand what may have caused in the past an given signature found in the data. For instance, can we explain the observed vertical velocity distribution of stars above and below the galactic disc seen by the Gaia spacecraft in terms of past satellites having hit our Milky way.
Example
As a test example let us consider a 1D diffusion equation sourced by a finite set of heat sources
source[x_, t_] =
3 BSplineBasis[3, t 4] BSplineBasis[3, (x - 1/8) 4] +
2 BSplineBasis[3, -2 + t 4] BSplineBasis[3, (x - 5/8) 4] +
BSplineBasis[3, -1 + t 4] BSplineBasis[3, (x - 2/8) 4] +
BSplineBasis[3, -1 + t 4] BSplineBasis[3, (x - 1/8) 4] +
BSplineBasis[3, -1/2 + t 4] BSplineBasis[3, (x - 4/8) 4] +
3/2 BSplineBasis[3, -3 + t 4] BSplineBasis[3, (x - 1/8) 4];
ContourPlot[source[x, t], {x, 0, 1}, {t, 0, 1}, PlotPoints -> 36,
Exclusions -> None, PlotRange -> All,
AspectRatio -> 1, Contours -> 10]
The diffusion diagram will obey
sol0 = NDSolveValue[{D[f[x, t], t] - 1/4 D[f[x, t], x, x] ==
source[x, t],
f[x, 0] == 0, f[0, t] == 0, f[1, t] == 0}, f, {x, 0, 1}, {t, 0, 2}];
ContourPlot[sol0[x, t], {x, 0, 1}, {t, 0, 1}, FrameLabel -> {x, t},
AspectRatio -> 1, PlotRange -> All, Contours -> 30, PlotPoints -> 50]
Here I have assumed arbitrarily that the edges of [0,1] did not let heat diffuse. I also assumed that initially there was no heat.
Let me first generate the corresponding data set of positing and time $(x,t)$ for later use
data = N[Flatten[
Table[{x, t, sol0[x, t]}, {x, 0, 1, 1/32}, {t, 0, 1, 1/32}], 1]];
My purpose is to invert this data set to recover the source of heating.
I other words, can I recover the first plot from the second one, if I assume I know how the heat source diffuse?
Attempt
I can define a set of spline functions which cover the $(x,t)$ space as follow:
nn = 16;
knots = Flatten[{{0, 0}, (Range[0, nn]/nn), {1, 1}}];
basis0 = Flatten@
Table[BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j,
t], {i, 0, nn}, {j, 0, nn}];
For instance, the 60th function obeys:
Plot3D[basis0[[60]], {x, 0, 1}, {t, 0, 1}, PlotRange -> All]
The image of this basis satisfies
basis = Flatten@
Table[NDSolveValue[{D[f[x, t], t] - 1/4 D[f[x, t], x, x] ==
BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j, t],
f[x, 0] == 0, f[0, t] == 0, f[1, t] == 0},
f[x, t], {x, 0, 1}, {t, 0, 1}], {i, 0, nn}, {j, 0, nn}];
Plot3D[basis[[60]], {x, 0, 1}, {t, 0, 1}, PlotRange -> All]
From this basis and the data I can generate the linear model a0
and a
relating resp. the spline coefficients to the source map and the spline coefficients heat map:
ff = Function[{x, t}, basis0 // Evaluate];
a0 = ff @@ # & /@ (Most /@ data0);
and
ff = Function[{x, t}, basis // Evaluate];
a = ff @@ # & /@ (Most /@ data);
a // Image // ImageAdjust
Let me first check that I can fit the source map with the splines:
fit0[x_, t_] =
basis0.LinearSolve[Transpose[a0].a0, Transpose[a0].(Last /@ data0)];
ContourPlot[fit0[x, t], {x, 0, 1}, {t, 0, 1}, Contours -> 20,
PlotRange -> All]
Similarly, I can define an (isotropic) penalty corresponding to $\int |\Delta T|^2 dx dt$ as
ff = Function[{x, t}, D[basis0, x, x] + D[basis0, t, t] // Evaluate];
s0 = ff @@ # & /@ (Most /@ data0);
pen = Transpose[s0].s0; pen /= Max[Flatten[Abs[pen]]];
pen // Image // ImageAdjust
A solution to the inverse problem then follows simply from inverting a
with a small roughness penalty as
sol[x_, t_] =
basis0.LinearSolve[Transpose[a].a + 10^-7 pen,
Transpose[a].(Last /@ data)];
ContourPlot[sol[x, t], {x, 0, 1}, {t, 0, 1}, Contours -> 20,
PlotRange -> All]
Question
I am fairly certain my present implementation is effectively redundant with the way NDSolve
can actually solves the differential equation using Finite Element methods. Hence my question:
Could one make use of the actual solver in
NDSolve
to formulate the inverse problem?
In other words, can we extract from the FEM toolkit FEM_a
,FEM_source
and FEM_solution
and FEM_grid
so that
FEM_solution = FEM_a FEM_source
where 'FEM_' stands for as sampled by the underlying mesh,FEM_grid
of the FEM toolkit.
This would be of interest in terms of efficiency, but also in order to address more complex and realistic inverse problems?
For Gaia data, the diffusion is in fact occurring in 3D and is anisotropic, so a robust and efficient formulation would help!
Technically I believe FEM have access to both a
and pen
so it would be great to be able to access them for the sake of solving the inverse problem.
I am guessing that this link would be a good starting point?
Comment
Note that the above implementation is partially incorrect at the top edge, because most spline basis elements are required to be zero on the boundary, whereas the correct solution should have an outgoing flux condition. This is something the FEM would handle naturally when the boundary conditions are taken care of.
Plot[{sol[x, 1], sol0[x, 1]}, {x, 0, 1}]
Note that in astronomy we unfortunately don't have access to the full diffusion diagram but only typically to a given snapshot (i.e. data on a line at fixed time, and/or possibly the time derivative on that line). So we can only extrapolate in the past up to some quite limited time horizon.
Complement 1: 1+1D code
source[x_, t_] =
3 BSplineBasis[3, t 4] BSplineBasis[3, (x - 1/8) 4] +
2 BSplineBasis[3, -2 + t 4] BSplineBasis[3, (x - 5/8) 4] +
BSplineBasis[3, -1 + t 4] BSplineBasis[3, (x - 2/8) 4] +
BSplineBasis[3, -1 + t 4] BSplineBasis[3, (x - 1/8) 4] +
BSplineBasis[3, -1/2 + t 4] BSplineBasis[3, (x - 4/8) 4] +
3/2 BSplineBasis[3, -3 + t 4] BSplineBasis[3, (x - 1/8) 4];
sol0 = NDSolveValue[{D[f[x, t], t] - 1/4 D[f[x, t], x, x] ==
source[x, t],
f[x, 0] == 0, f[0, t] == 0, f[1, t] == 0},
f, {x, 0, 1}, {t, 0, 2}];
nn = 16; knots = Flatten[{{0, 0}, (Range[0, nn]/nn), {1, 1}}];
basis0 = Flatten@
Table[BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j,
t], {i, 0, nn}, {j, 0, nn}];
basis = Flatten@
Table[NDSolveValue[{D[f[x, t], t] - 1/4 D[f[x, t], x, x] ==
BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j, t],
f[x, 0] == 0, f[0, t] == 0, f[1, t] == 0},
f[x, t], {x, 0, 1}, {t, 0, 1}], {i, 0, nn}, {j, 0, nn}];
data = N[Flatten[
Table[{x, t, sol0[x, t]}, {x, 0, 1, 1/32}, {t, 0, 1, 1/32}], 1]];
data0 = N[
Flatten[Table[{x, t, source[x, t]}, {x, 0, 1, 1/32}, {t, 0, 1,
1/32}], 1]];
ff = Function[{x, t}, basis0 // Evaluate];
a0 = ff @@ # & /@ (Most /@ data0);
ff = Function[{x, t}, basis // Evaluate];
a = ff @@ # & /@ (Most /@ data);
fit0[x_, t_] =
basis0.LinearSolve[Transpose[a0].a0,
Transpose[a0].(Last /@ data0)];
fit[x_, t_] =
basis.LinearSolve[Transpose[a].a, Transpose[a].(Last /@ data)];
ff = Function[{x, t}, D[basis0, x, x] + D[basis0, t, t] // Evaluate];
s0 = ff @@ # & /@ (Most /@ data0);
pen = Transpose[s0].s0; pen /= Max[Flatten[Abs[pen]]];
sol[x_, t_] =
basis0.LinearSolve[Transpose[a].a + 10^-7 pen,
Transpose[a].(Last /@ data)];
ContourPlot[source[x, t], {x, 0, 1}, {t, 0, 1}, Contours -> 20,
PlotRange -> All,Exclusions -> None]
ContourPlot[sol[x, t], {x, 0, 1}, {t, 0, 1}, Contours -> 20,
PlotRange -> All]
Complement 2: 2+1D codes
For the sake of completeness and to demonstrate why a more efficient implementation is needed here is the code for 2D diffusion without FEM (which for n=16 would take a white to run!).
source[x_, y_, t_] = BSplineBasis[3, t ] BSplineBasis[3, x]*
BSplineBasis[3, y]
sol0 = NDSolveValue[{D[f[x, y, t], t] - 1/4 D[f[x, y, t], x, x] -
1/4 D[f[x, y, t], y, y] == source[x, y, t], f[x, y, 0] == 0,
DirichletCondition[f[x, y, t] == 0, True]}, f, {x, 0, 1}, {y, 0, 1}, {t, 0, 1}]
nn = 2;knots = Flatten[{{0, 0}, (Range[0, nn]/nn), {1, 1}}];
basis0 = Flatten@
Table[BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j, y]
BSplineBasis[{3, knots}, k, t], {i, 0, nn}, {j, 0, nn}, {k, 0, nn}];
basis = Flatten@(Table[
ParallelTable[
NDSolveValue[{D[f[x, y, t], t] - 1/4 D[f[x, y, t], x, x] -
1/4 D[f[x, y, t], y, y] ==
BSplineBasis[{3, knots}, i, x] BSplineBasis[{3, knots}, j,
y] BSplineBasis[{3, knots}, k, t], f[x, y, 0] == 0,
DirichletCondition[f[x, y, t] == 0, True]},
f[x, y, t], {x, 0, 1}, {y, 0, 1}, {t, 0, 1}], {j, 0, nn}, {k,
0, nn}], {i, 0, nn}]);
data0 = N[Flatten[Table[{x, y, t, source[x, y, t]}, {x, 0, 1, 1/nn/2},
{y, 0,1, 1/nn/2}, {t, 0, 1, 1/nn/2}], 2]];
data = N[Flatten[
Table[{x, y, t, sol0[x, y, t]}, {x, 0, 1, 1/nn/2}, {y, 0, 1,
1/nn/2}, {t, 0, 1, 1/nn/2}], 2]];
ff = Function[{x, y, t}, basis // Evaluate];
a = ParallelMap[ff @@ # &, Most /@ data];
ff = Function[{x, y, t}, D[basis0, x, x] +
D[basis0, y, y] + D[basis0, t, t] // Evaluate];
s0 = ff @@ # & /@ (Most /@ data0);
pen = Transpose[s0].s0; pen /= Max[Flatten[Abs[pen]]];
sol[x_, y_, t_] =
basis0.LinearSolve[Transpose[a].a + 10^-9 pen,
Transpose[a].(Last /@ data)];
ContourPlot[sol[x, 1/2, t], {x, 0, 1}, {t, 0, 1}, Contours -> 20,
PlotRange -> All]
Complement 3: Background
Let
$$\mathcal{L}\psi = \rho $$
represent a (linear) partial differential equation (possibly time dependant). I will assume that there exist a basis function over which I can project $\psi$, so that $$ \psi(x)=\sum_n a_n \phi_n(x)\,,$$ where I also request that all $\phi_n(x)$ satisfy the boundary conditions of the partial differential equation ( $x$ can represent say $\mathbf{r}$ or $(\mathbf{r},t)$), i.e. the analysis is not necessary limited to stationary PDE). If I put this expansion into the PDE, multiply by $\phi_p(x)$ (or a Dirac function as a variant, see below) and integrate over $x$, I get formally $$ \mathbf{L}\cdot \mathbf{\Phi} = \mathbf{P}\,, $$ where $L_{ij}= \int d x \phi_i \mathcal{L} \phi_j $, $P_{i}= \int d x \phi_i \rho $ and ${\Phi}_i= a_i$.
I can then invert for $ \mathbf{\Phi}$ as $$ \mathbf{\Phi} =\mathbf{L}^{(-1)} \cdot\mathbf{P}\,, $$ where $\mathbf{L}^{(-1)}$ is the (possibly regularised) pseudo inverse of $\mathbf L$ (e.g. through least square). This is a possible method for solving PDEs. I am assuming (wrongly?) that linear FEM methods are a variant of this technique.
Conversely, If I start with the solved equation
$$\psi = \mathcal{L}^{-1}\rho \,. $$ I can expand $\rho$ over a basis function,$\rho=\sum_n a_n \rho_n$ , project as previously and write eventually
$$ \mathbf{P} =\mathbf{R}^{(-1)}\cdot \mathbf{\Phi}\,, $$
where $\mathbf{R}^{(-1)}$ is the (possibly regularised) pseudo inverse of $\mathbf R$, whose components are $R_{ij}= \int d x \rho_i \mathcal{L}^{-1} \rho_j $.
In my code above I have implemented something closely related to the second method, relying on NDSolve
(I use a Dirac function instead of $ \rho_i$
to simply sample the measured $\phi(x)$). The reason is I am after
recovering the source $\mathbf P$ given some knowledge of the response $\mathbf \Phi$.
My hope is that since FEM method solve the first problem they should have in store the tools to solve the second problem more efficiently?
a0
it does not seem to be used. Also your "complement" code misses a definition ofs0
. Have you had a look at the FEM programming tutorial? $\endgroup$