How to discretize equations#

Now we demonstrate how to discretize a PDE object.

Pre-coded sample objects are stored in sample attribute of phyem. Invoke these samples by

[1]:
import sys
ph_dir = '../../../../../'   # the path to dir that containing the phyem package.
sys.path.append(ph_dir)
import phyem as ph  # import the phyem package
ph.config._set_matplot_block(False)
samples = ph.samples

The partial differential equations of the canocical linear por-Hamiltonian are pre-coded. Call it through

[2]:
oph = samples.pde_canonical_pH(n=3, p=3, periodic=True)[0]  # where o on `oph` means outer

Check oph, outer oriented port-Hamiltonian, with

[3]:
oph.pr()
[3]:
<Figure size 800x600 with 1 Axes>

We can take out the knowns and label them by

[4]:
a3, b2 = oph.unknowns

We now test oph with test functions from the spaces where a3 and b2 come from, and label the test functions by \(v^3\) and \(u^2\),

[5]:
wf = oph.test_with(oph.unknowns, sym_repr=[r'v^3', r'u^2'])

Now, we apply integration by parts to the term indexed by '1-1'.

[6]:
wf = wf.derive.integration_by_parts('1-1')

We now apply a particular discretization to this weak formulation,

[7]:
td = wf.td
td.set_time_sequence()  # initialize a time sequence
td.define_abstract_time_instants('k-1', 'k-1/2', 'k')
td.differentiate('0-0', 'k-1', 'k')
td.average('0-1', b2, ['k-1', 'k'])

td.differentiate('1-0', 'k-1', 'k')
td.average('1-1', a3, ['k-1', 'k'])
dt = td.time_sequence.make_time_interval('k-1', 'k')

wf = td()

wf.unknowns = [
    a3 @ td.time_sequence['k'],
    b2 @ td.time_sequence['k'],
]

wf = wf.derive.split(
    '0-0', 'f0',
    [a3 @ td.ts['k'], a3 @ td.ts['k-1']],
    ['+', '-'],
    factors=[1/dt, 1/dt],
)

wf = wf.derive.split(
    '0-2', 'f0',
    [ph.d(b2 @ td.ts['k-1']), ph.d(b2 @ td.ts['k'])],
    ['+', '+'],
    factors=[1/2, 1/2],
)

wf = wf.derive.split(
    '1-0', 'f0',
    [b2 @ td.ts['k'], b2 @ td.ts['k-1']],
    ['+', '-'],
    factors=[1/dt, 1/dt]
)

wf = wf.derive.split(
    '1-2', 'f0',
    [a3 @ td.ts['k-1'], a3 @ td.ts['k']],
    ['+', '+'],
    factors=[1/2, 1/2],
)

wf = wf.derive.rearrange(
    {
        0: '0, 3 = 2, 1',
        1: '3, 0 = 2, 1',
    }
)

We now can write the weak formulation with matrix proxies. Before doing that, we need to

[8]:
ph.space.finite(3)
mp = wf.mp()

The matrix format of the weak formulation leads to a linear system,

[9]:
ls = mp.ls()
ls.pr()
[9]:
<Figure size 1200x600 with 1 Axes>

Note that, till this moment, everything is still abstract. To do the numerical simulation, we need to bring them to a particular implementation, for example, the msepy, standing for mimetic spectral elements python, by calling ph.fem.apply function, which will be shown in other notebooks.