"""
Solve the constant velocity scalar wave equation in an arbitrary number of dimensions.
It injects a point source with a time-dependent source time function.
"""
#Original script by Carlos da Costa:
#https://github.com/cako/fenics-scripts/blob/master/awefem/awefem.py
#
from dolfin import *
from vedo import ProgressBar, printc, download, settings
from vedo.dolfin import plot
import numpy as np

set_log_level(30)

def ricker_source(t, f=40):
    t -= 2 / f
    return (1 - 2 * (np.pi*f*t)**2) * np.exp(-(np.pi*f*t)**2)

def sine_source(t, f=40):
    return np.sin(2 * np.pi*f*t)


def awefem(mesh, t, source_loc=None):

    # Function space
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Boundary condition
    bc = DirichletBC(V, Constant(0), "on_boundary")

    # Trial and test functions
    u = TrialFunction(V)
    v = TestFunction(V)

    # Discretization
    c = 6
    dt = t[1] - t[0]
    u0 = Function(V)  # u0 = uN-1
    u1 = Function(V)  # u1 = uN1

    # Variational formulation
    F = (u - 2 * u1 + u0) * v * dx + (dt * c) ** 2 * dot(
        grad(u + 2 * u1 + u0) / 4, grad(v) ) * dx
    a, L = lhs(F), rhs(F)

    # Solver
    A, b = assemble_system(a, L)
    solver = LUSolver(A, "mumps")
    solver.parameters["symmetric"] = True
    bc.apply(A, b)

    # Solution
    u = Function(V)  # uN+1

    # Source
    if source_loc is None:
        mesh_center = np.mean(mesh.coordinates(), axis=0)
        source_loc = Point(mesh_center)
    else:
        source_loc = Point(source_loc)

    # Time stepping
    printc('\bomb Hit F1 to interrupt.', c='yellow')
    pb = ProgressBar(0, len(t))
    for i, t_ in enumerate(t[1:]):
        pb.print()
        b = assemble(L)
        delta = PointSource(V, source_loc, ricker_source(t_) * dt**2)
        delta.apply(b)
        solver.solve(u.vector(), b)

        u0.assign(u1)
        u1.assign(u)

        if t_>0.03:
            plt = plot(
                u,
                warp_zfactor=20, # set elevation along z
                vmin=.0,     # sets a minimum to the color scale
                vmax=0.003,
                cmap='rainbow', # the color map style
                alpha=1,        # transparency of the mesh
                lw=0.1,         # linewidth of mesh
                scalarbar=None,
                #lighting='plastic',
                #elevation=-.3,
                interactive=False,
            )  # continue execution
            plt.clear()
    plt.interactive()

if __name__ == "__main__":

    ot, dt, nt = 0, 1e-3, 150
    t = ot + np.arange(nt) * dt

    print("Computing wavefields over dolfin mesh")
    fpath = download("https://vedo.embl.es/examples/data/dolfin_fine.xml")
    mesh = Mesh(fpath)
    awefem(mesh, t, source_loc=(0.8, 0.8))
