Skip to content

Commit c11aba9

Browse files
committed
Refactor Wave and Diffusion chapters to Devito-only
- Fix broken LaTeX subscripts (**{ → _{) in wave and diffu chapters - Fix Python syntax errors (missing * operators) in wave1D_fd1.qmd - Fix broken cross-references (@sec- → @eq-) in wave_app_exer.qmd - Remove NumPy implementation files from chapters and src directories - Update all file references to point to Devito implementations - Add Neumann BC, verification, and convergence sections to wave1D_devito.qmd - Update exercise solutions to use Devito solvers Deleted files: - chapters/wave/wave1D_prog.qmd, wave2D_prog.qmd - chapters/wave/exer-wave/ (exercise solutions) - chapters/diffu/exer-diffu/ (exercise solutions) - src/wave/wave1D/, wave2D/, wave2D_u0/ (NumPy solvers) - src/diffu/diffu*_u0.py, diffu1D_vc.py, etc. (NumPy solvers) All 247 tests pass, PDF builds without errors.
1 parent ab9b38c commit c11aba9

54 files changed

Lines changed: 387 additions & 12900 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

chapters/appendices/softeng2/softeng2.qmd

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,9 @@ and @sec-wave-pde2-var-c.
4242
## A solver function
4343
4444
The general initial-boundary value problem
45-
solved by finite difference methods can be implemented as shown in
46-
the following `solver` function (taken from the
47-
file [`wave1D_dn_vc.py`](https://github.com/devitocodes/devito_book/tree/main/src/wave/wave1D/wave1D_dn_vc.py)).
48-
This function builds on
49-
simpler versions described in
50-
@sec-wave-pde1-impl, @sec-wave-pde1-impl-vec,
51-
@sec-wave-pde2-Neumann, and @sec-wave-pde2-var-c.
52-
There are several quite advanced
53-
constructs that will be commented upon later.
54-
The code is lengthy, but that is because we provide a lot of
55-
flexibility with respect to input arguments,
56-
boundary conditions, and optimization
57-
(scalar versus vectorized loops).
58-
59-
```{.python include="../../../src/wave/wave1D/wave1D_dn_vc.py" start-after="def solver" end-before="def test_quadratic"}
60-
```
45+
solved by finite difference methods. For modern implementations using
46+
Devito, see @sec-wave-devito. This section covers software engineering
47+
principles that apply broadly to scientific computing.
6148
6249
## Storing simulation data in files {#sec-softeng2-wave1D-filestorage}
6350
@@ -442,9 +429,8 @@ The returned sequence `r` should converge to 2 since the error
442429
analysis in @sec-wave-pde1-analysis predicts various error measures to behave
443430
like $\Oof{\Delta t^2} + \Oof{\Delta x^2}$. We can easily run
444431
the case with standing waves and the analytical solution
445-
$u(x,t) = \cos(\frac{2\pi}{L}t)\sin(\frac{2\pi}{L}x)$. The call will
446-
be very similar to the one provided in the `test_convrate_sincos` function
447-
in @sec-wave-pde1-impl-verify-rate, see the file `src/wave/wave1D/wave1D_dn_vc.py` for details.
432+
$u(x,t) = \cos(\frac{2\pi}{L}t)\sin(\frac{2\pi}{L}x)$. See @sec-wave-devito-convergence
433+
for details on convergence rate testing with Devito.
448434
449435
Many who know about class programming prefer to organize their software
450436
in terms of classes. This gives a richer application programming interface
@@ -1221,9 +1207,7 @@ The `wave2D_u0.py` file contains a `solver` function, which calls an
12211207
in time. The function `advance_scalar` applies standard Python loops
12221208
to implement the scheme, while `advance_vectorized` performs
12231209
corresponding vectorized arithmetics with array slices. The statements
1224-
of this solver are explained in @sec-wave-2D3D-impl, in
1225-
particular @sec-wave2D3D-impl-scalar and
1226-
@sec-wave2D3D-impl-vectorized.
1210+
of this solver are explained in @sec-wave-2D3D-models.
12271211
12281212
Although vectorization can bring down the CPU time dramatically
12291213
compared with scalar code, there is still some factor 5-10 to win in
@@ -1506,9 +1490,8 @@ to a single index.
15061490
15071491
We write a Fortran subroutine `advance` in a file
15081492
[`wave2D_u0_loop_f77.f`](https://github.com/devitocodes/devito_book/tree/main/src/softeng2/wave2D_u0_loop_f77.f)
1509-
for implementing the updating formula
1510-
(@eq-wave-2D3D-impl1-2Du0-ueq-discrete) and setting the solution to zero
1511-
at the boundaries:
1493+
for implementing the updating formula (@eq-wave-2D3D-models-unp1) and
1494+
setting the solution to zero at the boundaries:
15121495
15131496
```fortran
15141497
subroutine advance(u, u_1, u_2, f, Cx2, Cy2, dt2, Nx, Ny)

chapters/diffu/diffu_devito_exercises.qmd

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -521,63 +521,51 @@ The 2D solver should also achieve second-order spatial convergence
521521
when the Fourier number is held fixed.
522522
:::
523523

524-
### Exercise 10: Comparison with Legacy Code {#exer-diffu-legacy}
524+
### Exercise 10: Performance Scaling {#exer-diffu-scaling}
525525

526-
Compare the Devito solver with the legacy NumPy implementation.
526+
Investigate how Devito's performance scales with problem size.
527527

528-
a) Run both solvers with the same parameters.
529-
b) Verify they produce the same results.
530-
c) Compare execution times.
528+
a) Run the 1D solver with increasing grid sizes (Nx = 100, 500, 1000, 5000).
529+
b) Measure and plot the execution time vs grid size.
530+
c) Determine if the scaling is linear in Nx.
531531

532532
::: {.callout-note collapse="true" title="Solution"}
533533
```python
534534
from src.diffu import solve_diffusion_1d
535-
from src.diffu.diffu1D_u0 import solver_FE_simple
536535
import numpy as np
537536
import time
537+
import matplotlib.pyplot as plt
538538

539539
# Parameters
540540
L = 1.0
541541
a = 1.0
542-
Nx = 200
543542
F = 0.5
544-
T = 0.1
543+
T = 0.01 # Short time for timing tests
545544

546-
dx = L / Nx
547-
dt = F * dx**2 / a
548-
549-
# Devito solver
550-
t0 = time.perf_counter()
551-
result_devito = solve_diffusion_1d(
552-
L=L, a=a, Nx=Nx, T=T, F=F,
553-
I=lambda x: np.sin(np.pi * x),
554-
)
555-
t_devito = time.perf_counter() - t0
556-
557-
# Legacy NumPy solver
558-
t0 = time.perf_counter()
559-
u_legacy, x_legacy, t_legacy, cpu_legacy = solver_FE_simple(
560-
I=lambda x: np.sin(np.pi * x),
561-
a=a,
562-
f=lambda x, t: 0,
563-
L=L,
564-
dt=dt,
565-
F=F,
566-
T=T,
567-
)
568-
t_numpy = time.perf_counter() - t0
545+
grid_sizes = [100, 500, 1000, 5000]
546+
times = []
569547

570-
# Compare results
571-
diff = np.max(np.abs(result_devito.u - u_legacy))
572-
print(f"Maximum difference: {diff:.2e}")
573-
print(f"Devito time: {t_devito:.4f} s")
574-
print(f"NumPy time: {t_numpy:.4f} s")
548+
for Nx in grid_sizes:
549+
t0 = time.perf_counter()
550+
result = solve_diffusion_1d(
551+
L=L, a=a, Nx=Nx, T=T, F=F,
552+
I=lambda x: np.sin(np.pi * x),
553+
)
554+
times.append(time.perf_counter() - t0)
555+
print(f"Nx={Nx}: {times[-1]:.4f} s")
575556

576-
# Note: For small problems, NumPy may be faster due to compilation
577-
# overhead. For large problems, Devito's optimized C code wins.
557+
# Plot scaling
558+
plt.figure(figsize=(8, 6))
559+
plt.loglog(grid_sizes, times, 'bo-', label='Measured')
560+
plt.loglog(grid_sizes, times[0]*(np.array(grid_sizes)/grid_sizes[0]),
561+
'r--', label='O(N)')
562+
plt.xlabel('Grid size (Nx)')
563+
plt.ylabel('Time (s)')
564+
plt.legend()
565+
plt.title('Devito 1D Diffusion Solver Scaling')
566+
plt.grid(True)
578567
```
579568

580-
For large grids, Devito's automatically generated and optimized C code
581-
typically outperforms pure Python/NumPy implementations. The advantage
582-
grows with problem size.
569+
The Devito solver typically shows linear scaling in Nx for 1D problems,
570+
as expected for an explicit scheme where each time step is O(Nx).
583571
:::

0 commit comments

Comments
 (0)