Wave equation — triflow 0.4.3 documentation

# Wave equation

    import functools as ft
    import multiprocessing as mp
    import logging

    import numpy as np
    from scipy.signal import gaussian

    import pylab as pl

    from triflow import Model, Simulation, schemes, displays

    %matplotlib inline

We initialize the model with the wave equation written as a system of first order differential equations.

\[\partial_{t,\,t}u = c^2 \partial_{x,\,x} u\]

which lead to

with \(c\) the velocity of the wave.

    model = Model(["c**2 * dxxu", "v"],
                   ["v", "u"], "c")

We discretize our spatial domain. `retstep=True` ask to return the spatial step.

    x, dx = np.linspace(0, 100, 500, retstep=True)

We initialize with three gaussian pulses for the initial condition

    u = (np.roll(gaussian(x.size, 10), x.size // 5) +
         np.roll(gaussian(x.size, 10), -x.size // 5) -
         gaussian(x.size, 30) * 1.5)
    v = np.zeros_like(u)

    fields = model.fields_template(x=x, u=u, v=v)

    pl.figure(figsize=(15, 4))
    pl.plot(fields.x, fields.u)
    pl.xlim(0, fields.x.max())
    pl.show()

We precise our parameters. The default scheme provide an automatic time_stepping. We want dirichlet boundary condition, so we set the periodic flag to False.

    parameters = dict(c=5, periodic=False)

This function will set the boundary condition. We will have a fixed rope at each edge.

    def dirichlet(t, fields, pars):
        # fields.u[:] = np.sin(t * 2 * np.pi * 2) * gaussian(x.size, 10) - fields.u[:]
        fields.u[0] = 0
        fields.u[-1] = 0
        fields.v[0] = 0
        fields.v[-1] = 0
        return fields, pars

We initialize the simulation, and we set a bokeh display in order to have real-time plotting.

    t = 0
    simulation = Simulation(model, t, fields, parameters,
                            dt=.1, tmax=15,
                            hook=dirichlet)

We iterate on the simulation until the end.

    pl.figure(figsize=(15, 10))
    for i, (t, fields) in enumerate(simulation):
        if i % 2 == 0:
            pl.fill_between(fields.x, fields.u + .1 * (i + 1),
                            fields.u.min() - 1,
                            color='darkred', zorder=-2 * i, alpha=.7)
            pl.plot(fields.x, fields.u + .1 * (i + 1),
                    color='white',
                    zorder=-(2 * i - 1))
        print(f"t: {t:g}".ljust(80), end='\r')
    pl.xlim(0, fields.x.max())
    pl.show()

    t: 15