Partial differential equations
==============================
The Surfacefun package is capable of solving general variable-coefficient,
second-order, linear, elliptic partial differential equations on open and
closed surfaces. Consider such a PDE on a given surface :math:`\Gamma`,
.. math::
\mathcal{L}_\Gamma u(\boldsymbol{x}) = f(\boldsymbol{x}), \qquad \boldsymbol{x} \in \Gamma,
where :math:`\mathcal{L}_\Gamma` is an elliptic partial differential operator of
the form
.. math::
\mathcal{L}_\Gamma u(\boldsymbol{x}) = \sum_{i=1}^3 \sum_{j=1}^3
a_{ij}(\boldsymbol{x}) \, \partial_i^\Gamma \partial_j^\Gamma u(\boldsymbol{x}) +
\sum_{i=1}^3 b_i(\boldsymbol{x}) \,\partial_i^\Gamma u(\boldsymbol{x}) +
c(\boldsymbol{x}) u(\boldsymbol{x}),
with smooth coefficients :math:`a_{ij}`, :math:`b_i`, and :math:`c`. Here, we
identify :math:`\partial_1^\Gamma`, :math:`\partial_2^\Gamma`,
:math:`\partial_3^\Gamma` with the Cartesian :math:`x`-, :math:`y`-, and
:math:`z`-components of the surface gradient, respectively.
If :math:`\Gamma` is not a closed surface, the PDE may also be
subject to boundary conditions, e.g., :math:`u(\boldsymbol{x}) = g(\boldsymbol{x})`
for :math:`\boldsymbol{x} \in \partial\Gamma` and some function :math:`g`.
Partial differential operators in Surfacefun are specified as MATLAB structs
with properties defining the coefficients on each term appearing in
:math:`\mathcal{L}_\Gamma`. The coefficients on the second-order terms are
specified by setting ``pdo.dxx``, ``pdo.dyy``, ``pdo.dzz``, ``pdo.dxy``,
``pdo.dyx``, ``pdo.dyz``, ``pdo.dzy``, ``pdo.dxz``, and ``pdo.dzx``.
Coefficients on the first-order terms can be set via ``pdo.dx``, ``pdo.dy``,
and ``pdo.dz``. The zeroth-order coefficient is specified via ``pdo.c``. Each
coefficient may be a constant, a function handle, or a ``surfacefun``. For
instance, the Laplace-Beltrami operator can be specified via
.. code-block:: matlab
pdo = [];
pdo.dxx = 1;
pdo.dyy = 1;
pdo.dzz = 1;
or more simply as
.. code-block:: matlab
pdo = [];
pdo.lap = 1;
This sets the coefficients on the terms :math:`\partial_x^\Gamma \partial_x^\Gamma`,
:math:`\partial_y^\Gamma \partial_y^\Gamma`, and
:math:`\partial_z^\Gamma \partial_z^\Gamma` to one and the rest to zero.
Let's solve a simple Laplace--Beltrami problem on the surface of the sphere.
Since the spherical harmonics are eigenfunctions of the Laplace--Beltrami
operator on the sphere, we can construct a test problem analytically:
.. code-block:: matlab
% Make a sphere mesh
p = 16;
nref = 2;
dom = surfacemesh.sphere(p+1, nref);
% Construct the true solution and corresponding righthand side
l = 3; m = 2;
sol = spherefun.sphharm(l, m);
sol = surfacefun(@(x,y,z) sol(x,y,z), dom);
f = -l*(l+1)*sol;
% Specify the partial differential operator to be Laplace-Beltrami
pdo = [];
pdo.lap = 1;
To solve the PDE, we create a ``surfaceop``. The ``surfaceop`` object
encapsulates the factorization and solution routines corresponding to the fast
direct solver in [1].
.. code-block:: matlab
L = surfaceop(dom, pdo, f);
It turns out that the Laplace--Beltrami problem on a closed surface is rank
deficient (by one). However, it is uniquely solvable under the mean-zero
conditions
.. math::
\int_\Gamma u = \int_\Gamma f = 0.
We can impose this condition by setting
.. code-block:: matlab
L.rankdef = true;
Now we can solve the PDE:
.. code-block:: matlab
u = L.solve();
plot(u)
.. container:: output-image
.. figure:: images/lb_sphere.png
:width: 400px
:align: center
.. raw:: html
ans =
6.209136661992651e-12
Surface PDEs on surfaces of arbitrary genus may be solved using ``surfaceop``.
For example, here is the solution to a variable-coefficient surface Helmholtz
equation on a genus-1 stellarator geometry:
.. code-block:: matlab
% Construct the stellarator geometry
p = 16; nu = 8; nv = 24;
dom = surfacemesh.stellarator(p+1, nu, nv);
% Variable-coefficient surface Helmholtz equation
pdo = [];
pdo.lap = 1;
pdo.c = @(x,y,z) 300*(1-z);
f = -1;
L = surfaceop(dom, pdo, f);
u = L.solve();
plot(u), colorbar
.. container:: output-image
.. figure:: images/helmholtz.png
:width: 450px
:align: center
.. raw:: html