|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | +Quick demo to solve the 1D advection-diffusion with Dedalus |
| 5 | +using the pySDC interface |
| 6 | +""" |
| 7 | +# Base user imports |
| 8 | +import numpy as np |
| 9 | +import matplotlib.pyplot as plt |
| 10 | +import dedalus.public as d3 |
| 11 | + |
| 12 | +# pySDC imports |
| 13 | +from pySDC.playgrounds.dedalus.interface.problem import DedalusProblem |
| 14 | +from pySDC.playgrounds.dedalus.interface.sweeper import DedalusSweeperIMEX |
| 15 | +from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI |
| 16 | + |
| 17 | +# ----------------------------------------------------------------------------- |
| 18 | +# User parameters |
| 19 | +# ----------------------------------------------------------------------------- |
| 20 | +listK = [0, 1, 2] # list of initial wavenumber in the solution (amplitude 1) |
| 21 | +nu = 1e-2 # viscosity (unitary velocity) |
| 22 | + |
| 23 | +# -- Space discretisation |
| 24 | +xEnd = 2*np.pi # domain [0, xEnd] |
| 25 | +nX = 16 # number of points in x (periodic domain) |
| 26 | + |
| 27 | +# -- Time integration |
| 28 | +nSweeps = 4 # number of SDC iterations (sweeps) |
| 29 | +nNodes = 4 # number of SDC quadrature nodes |
| 30 | +tEnd = 2*np.pi # final simulation time (starts at 0) |
| 31 | +nSteps = 50 # number of time-steps |
| 32 | + |
| 33 | +# ----------------------------------------------------------------------------- |
| 34 | +# Solver setup |
| 35 | +# ----------------------------------------------------------------------------- |
| 36 | + |
| 37 | +# -- Dedalus space grid |
| 38 | +coords = d3.CartesianCoordinates('x') |
| 39 | +dist = d3.Distributor(coords, dtype=np.float64) |
| 40 | +xbasis = d3.RealFourier(coords['x'], size=nX, bounds=(0, xEnd)) |
| 41 | +u = dist.Field(name='u', bases=xbasis) |
| 42 | + |
| 43 | +# -- Initial solution |
| 44 | +x = xbasis.local_grid(dist, scale=1) |
| 45 | +u0 = np.sum([np.cos(k*x) for k in listK], axis=0) |
| 46 | +np.copyto(u['g'], u0) |
| 47 | +u0 = u.copy() # store initial field for later |
| 48 | + |
| 49 | +# -- Problem |
| 50 | +dx = lambda f: d3.Differentiate(f, coords['x']) |
| 51 | +problem = d3.IVP([u], namespace=locals()) |
| 52 | +problem.add_equation("dt(u) + dx(u) - nu*dx(dx(u)) = 0") |
| 53 | + |
| 54 | +nSweeps = 4 |
| 55 | +nNodes = 4 |
| 56 | +tEnd = 2*np.pi |
| 57 | +nSteps = 100 |
| 58 | +dt = tEnd / nSteps |
| 59 | + |
| 60 | +# -- pySDC controller settings |
| 61 | +description = { |
| 62 | + # Sweeper and its parameters |
| 63 | + "sweeper_class": DedalusSweeperIMEX, |
| 64 | + "sweeper_params": { |
| 65 | + "quad_type": "RADAU-RIGHT", |
| 66 | + "num_nodes": nNodes, |
| 67 | + "node_type": "LEGENDRE", |
| 68 | + "initial_guess": "copy", |
| 69 | + "do_coll_update": False, |
| 70 | + "QI": "IE", |
| 71 | + "QE": "EE", |
| 72 | + 'skip_residual_computation': |
| 73 | + ('IT_CHECK', 'IT_DOWN', 'IT_UP', 'IT_FINE', 'IT_COARSE'), |
| 74 | + }, |
| 75 | + # Step parameters |
| 76 | + "step_params": { |
| 77 | + "maxiter": 1, |
| 78 | + }, |
| 79 | + # Level parameters |
| 80 | + "level_params": { |
| 81 | + "dt": dt, |
| 82 | + "restol": -1, |
| 83 | + "nsweeps": nSweeps, |
| 84 | + }, |
| 85 | + "problem_class": DedalusProblem, |
| 86 | + "problem_params": { |
| 87 | + 'problem': problem, |
| 88 | + 'nNodes': nNodes, |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +controller = controller_nonMPI( |
| 93 | + num_procs=1, controller_params={'logger_level': 30}, |
| 94 | + description=description) |
| 95 | + |
| 96 | +prob = controller.MS[0].levels[0].prob |
| 97 | +uSol = prob.solver.state |
| 98 | +tVals = np.linspace(0, tEnd, nSteps + 1) |
| 99 | + |
| 100 | +for i in range(nSteps): |
| 101 | + uSol, _ = controller.run(u0=uSol, t0=tVals[i], Tend=tVals[i + 1]) |
| 102 | + |
| 103 | +# -- Plotting solution in real and Fourier space |
| 104 | +fig, (ax1, ax2) = plt.subplots(1, 2) |
| 105 | +fig.suptitle(rf"Advection-diffusion with $\nu={nu:1.1e}$") |
| 106 | + |
| 107 | +plt.sca(ax1) |
| 108 | +plt.title("Real space") |
| 109 | +plt.plot(u0['g'], label='$u_0$') |
| 110 | +plt.plot(u['g'], label='$u(T)$') |
| 111 | +plt.legend() |
| 112 | +plt.grid(True) |
| 113 | +plt.xlabel("$x$") |
| 114 | +plt.ylabel("$u$") |
| 115 | + |
| 116 | +plt.sca(ax2) |
| 117 | +plt.title("Coefficient space") |
| 118 | +plt.plot(u0['c'], 'o', mfc="none", label='$u_0$') |
| 119 | +plt.plot(u['c'], 's', mfc="none", ms=10, label='$u(t)$') |
| 120 | +plt.legend() |
| 121 | +plt.grid(True) |
| 122 | +plt.xlabel(r"$\kappa$") |
| 123 | +plt.ylabel("$u$") |
| 124 | + |
| 125 | +fig.set_size_inches(12, 5) |
| 126 | +plt.tight_layout() |
0 commit comments