|
| 1 | +from devito import * |
| 2 | +import os |
| 3 | +import numpy as np |
| 4 | +from examples.seismic.source import DGaussSource, TimeAxis |
| 5 | +from devito.petsc import PETScSolve |
| 6 | +from devito.petsc.initialize import PetscInitialize |
| 7 | +configuration['compiler'] = 'custom' |
| 8 | +os.environ['CC'] = 'mpicc' |
| 9 | + |
| 10 | + |
| 11 | +# PETSc implementation of devito/examples/seismic/tutorials/05_staggered_acoustic.ipynb |
| 12 | +# Test staggered grid implementation with PETSc |
| 13 | + |
| 14 | +PetscInitialize() |
| 15 | + |
| 16 | +extent = (2000., 2000.) |
| 17 | +shape = (81, 81) |
| 18 | + |
| 19 | +x = SpaceDimension( |
| 20 | + name='x', spacing=Constant(name='h_x', value=extent[0]/(shape[0]-1), dtype=np.float64) |
| 21 | +) |
| 22 | +z = SpaceDimension( |
| 23 | + name='z', spacing=Constant(name='h_z', value=extent[1]/(shape[1]-1), dtype=np.float64) |
| 24 | +) |
| 25 | + |
| 26 | +grid = Grid(extent=extent, shape=shape, dimensions=(x, z), dtype=np.float64) |
| 27 | + |
| 28 | +# Timestep size |
| 29 | +t0, tn = 0., 200. |
| 30 | +dt = 1e2*(1. / np.sqrt(2.)) / 60. |
| 31 | +time_range = TimeAxis(start=t0, stop=tn, step=dt) |
| 32 | + |
| 33 | +src = DGaussSource(name='src', grid=grid, f0=0.01, time_range=time_range, a=0.004) |
| 34 | +src.coordinates.data[:] = [1000., 1000.] |
| 35 | + |
| 36 | +# Now we create the velocity and pressure fields |
| 37 | +# NOTE/TODO: PETSc does not yet fully support VectorTimeFunctions. Ideally, |
| 38 | +# it should use the new "coupled" machinery |
| 39 | +p2 = TimeFunction(name='p2', grid=grid, staggered=NODE, space_order=2, time_order=1) |
| 40 | +vx2 = TimeFunction(name='vx2', grid=grid, staggered=(x,), space_order=2, time_order=1) |
| 41 | +vz2 = TimeFunction(name='vz2', grid=grid, staggered=(z,), space_order=2, time_order=1) |
| 42 | + |
| 43 | +t = grid.stepping_dim |
| 44 | +time = grid.time_dim |
| 45 | + |
| 46 | +# We need some initial conditions |
| 47 | +V_p = 4.0 |
| 48 | +density = 1. |
| 49 | + |
| 50 | +ro = 1/density |
| 51 | +l2m = V_p*V_p*density |
| 52 | + |
| 53 | +# The source injection term |
| 54 | +src_p_2 = src.inject(field=p2.forward, expr=src) |
| 55 | + |
| 56 | +# 2nd order acoustic according to fdelmoc |
| 57 | +v_x_2 = Eq(vx2.dt, ro * p2.dx) |
| 58 | +v_z_2 = Eq(vz2.dt, ro * p2.dz) |
| 59 | + |
| 60 | +petsc_v_x_2 = PETScSolve(v_x_2, target=vx2.forward) |
| 61 | +petsc_v_z_2 = PETScSolve(v_z_2, target=vz2.forward) |
| 62 | + |
| 63 | +p_2 = Eq(p2.dt, l2m * (vx2.forward.dx + vz2.forward.dz)) |
| 64 | + |
| 65 | +petsc_p_2 = PETScSolve(p_2, target=p2.forward, solver_parameters={'ksp_rtol': 1e-7}) |
| 66 | + |
| 67 | +with switchconfig(language='petsc'): |
| 68 | + op_2 = Operator(petsc_v_x_2 + petsc_v_z_2 + petsc_p_2 + src_p_2, opt='noop') |
| 69 | + op_2(time=src.time_range.num-1, dt=dt) |
| 70 | + |
| 71 | +norm_p2 = norm(p2) |
| 72 | +assert np.isclose(norm_p2, .35098, atol=1e-4, rtol=0) |
| 73 | + |
| 74 | + |
| 75 | +# 4th order acoustic according to fdelmoc |
| 76 | +p4 = TimeFunction(name='p4', grid=grid, staggered=NODE, space_order=4) |
| 77 | +vx4 = TimeFunction(name='vx4', grid=grid, staggered=(x,), space_order=4, time_order=1) |
| 78 | +vz4 = TimeFunction(name='vz4', grid=grid, staggered=(z,), space_order=4, time_order=1) |
| 79 | + |
| 80 | +src_p_4 = src.inject(field=p4.forward, expr=src) |
| 81 | + |
| 82 | +v_x_4 = Eq(vx4.dt, ro * p4.dx) |
| 83 | +v_z_4 = Eq(vz4.dt, ro * p4.dz) |
| 84 | + |
| 85 | +petsc_v_x_4 = PETScSolve(v_x_4, target=vx4.forward) |
| 86 | +petsc_v_z_4 = PETScSolve(v_z_4, target=vz4.forward) |
| 87 | + |
| 88 | +p_4 = Eq(p4.dt, l2m * (vx4.forward.dx + vz4.forward.dz)) |
| 89 | + |
| 90 | +petsc_p_4 = PETScSolve(p_4, target=p4.forward, solver_parameters={'ksp_rtol': 1e-7}) |
| 91 | + |
| 92 | +with switchconfig(language='petsc'): |
| 93 | + op_4 = Operator(petsc_v_x_4 + petsc_v_z_4 + petsc_p_4 + src_p_4, opt='noop') |
| 94 | + op_4(time=src.time_range.num-1, dt=dt) |
| 95 | + |
| 96 | +norm_p4 = norm(p4) |
| 97 | +assert np.isclose(norm_p4, .33736, atol=1e-4, rtol=0) |
0 commit comments