|
294 | 294 | }, |
295 | 295 | { |
296 | 296 | "cell_type": "code", |
297 | | - "execution_count": 6, |
| 297 | + "execution_count": 2, |
298 | 298 | "metadata": {}, |
299 | 299 | "outputs": [], |
300 | 300 | "source": [ |
|
307 | 307 | }, |
308 | 308 | { |
309 | 309 | "cell_type": "code", |
310 | | - "execution_count": 7, |
| 310 | + "execution_count": 3, |
311 | 311 | "metadata": {}, |
312 | 312 | "outputs": [], |
313 | 313 | "source": [ |
314 | | - "# %load -s solver_FECS, src-advec/advec1D.py\n", |
| 314 | + "# %load -s solver_FECS src-advec/advec1D.py\n", |
315 | 315 | "def solver_FECS(I, U0, v, L, dt, C, T, user_action=None):\n", |
316 | 316 | " Nt = int(round(T/float(dt)))\n", |
317 | 317 | " t = np.linspace(0, Nt*dt, Nt+1) # Mesh points in time\n", |
|
338 | 338 | " u.data[1, :] = [I(xi) for xi in x]\n", |
339 | 339 | " \n", |
340 | 340 | " # Insert boundary condition\n", |
341 | | - " bc = [Eq(u[t_s, 0], U0)]\n", |
| 341 | + " bc = [Eq(u[t_s+1, 0], U0)]\n", |
342 | 342 | " \n", |
343 | 343 | " op = Operator([eq] + bc)\n", |
344 | | - " op.apply(time_m=1, dt=dt)\n", |
| 344 | + " op.apply(dt=dt, x_m=1, x_M=Nx-1)\n", |
| 345 | + " \n", |
345 | 346 | " if user_action is not None:\n", |
346 | 347 | " for n in range(0, Nt + 1):\n", |
347 | 348 | " user_action(u.data[n], x, t, n)\n" |
|
425 | 426 | }, |
426 | 427 | { |
427 | 428 | "cell_type": "code", |
428 | | - "execution_count": 8, |
| 429 | + "execution_count": 4, |
429 | 430 | "metadata": {}, |
430 | 431 | "outputs": [], |
431 | 432 | "source": [ |
432 | | - "# %load -s run_FECS, src-advec/advec1D.py\n", |
433 | 433 | "def run_FECS(case):\n", |
434 | 434 | " \"\"\"Special function for the FECS case.\"\"\"\n", |
435 | 435 | " if case == 'gaussian':\n", |
|
686 | 686 | "t = np.linspace(0, Nt*dt, Nt+1) # Mesh points in time\n", |
687 | 687 | "...\n", |
688 | 688 | "if scheme == 'FE':\n", |
689 | | - " u = TimeFunction(name='u', grid=grid, space_order=2, save=2)\n", |
| 689 | + " u = TimeFunction(name='u', grid=grid, space_order=2, save=Nt+1)\n", |
690 | 690 | " pde = u.dtr + v*u.dxc\n", |
691 | | - " \n", |
692 | | - " for i in range(1, Nx):\n", |
693 | | - " u[i] = u_1[i] - 0.5*C*(u_1[i+1] - u_1[i-1])\n", |
| 691 | + " ...\n", |
694 | 692 | "elif scheme == 'LF':\n", |
| 693 | + " u = ...\n", |
| 694 | + " \n", |
695 | 695 | " # Use some scheme for the first step\n", |
696 | | - " u1 = ...\n", |
697 | | - " pde1 = ...\n", |
| 696 | + " pde0 = ...\n", |
698 | 697 | " ...\n", |
699 | 698 | " \n", |
700 | | - " # Move to the LF scheme after the next step\n", |
701 | | - " u = TimeFunction(name='u', grid=grid, time_order=2, space_order=2, save=Nt+1)\n", |
702 | | - " u.data[0:2, :] = u1.data\n", |
| 699 | + " # Move to the LF scheme after the first step\n", |
703 | 700 | " pde = u.dtc + v*u.dxc\n", |
704 | 701 | " ...\n", |
705 | 702 | "```" |
|
1088 | 1085 | "cell_type": "markdown", |
1089 | 1086 | "metadata": {}, |
1090 | 1087 | "source": [ |
1091 | | - "mathcal{I}_t means that we in the first equation, involving $u_0^n$, insert $u_{N_x}^n$,\n", |
| 1088 | + "It means that we in the first equation, involving $u_0^n$, insert $u_{N_x}^n$,\n", |
1092 | 1089 | "and that we in the last equation, involving $u^{n+1}_{N_x}$ insert $u^{n+1}_0$.\n", |
1093 | | - "Normally, we can do this in the simple way that `u_1[0]` is updated as\n", |
1094 | | - "`u_1[Nx]` at the beginning of a new time level.\n", |
| 1090 | + "Normally, we can do this in the simple way that `u[t_s, 0]` is updated as\n", |
| 1091 | + "`u[t_s, Nx]` at the beginning of a new time level.\n", |
1095 | 1092 | "\n", |
1096 | 1093 | "In some schemes we may need $u^{n}_{N_x+1}$ and $u^{n}_{-1}$. Periodicity\n", |
1097 | 1094 | "then means that these values are equal to $u^n_1$ and $u^n_{N_x-1}$,\n", |
1098 | 1095 | "respectively. For the upwind scheme, it is sufficient to set\n", |
1099 | | - "`u_1[0]=u_1[Nx]` at a new time level before computing `u[1]`. This ensures\n", |
1100 | | - "that `u[1]` becomes right and at the next time level `u[0]` at the current\n", |
| 1096 | + "`u[t_s, 0]=u[t_s, Nx]` at a new time level before computing `u[t_s+1, 1]`. This ensures\n", |
| 1097 | + "that `u[t_s+1, 1]` becomes right and at the next time level `u[t_s+1, 0]` at the current\n", |
1101 | 1098 | "time level is correctly updated.\n", |
1102 | | - "For the Leapfrog scheme we must update `u[0]` and `u[Nx]` using the scheme:" |
| 1099 | + "For the Leapfrog scheme we must update `u[t_s+1, 0]` and `u[t_s+1, Nx]` using the scheme:" |
1103 | 1100 | ] |
1104 | 1101 | }, |
1105 | 1102 | { |
|
1108 | 1105 | "source": [ |
1109 | 1106 | "```python\n", |
1110 | 1107 | "pbc = [Eq(u[t_s+1, 0], u[t_s-1, 0] - C*(u[t_s, 1] - u[t_s, Nx-1]))]\n", |
1111 | | - "pbc += [Eq(u[t_s, Nx], u[t_s, 0])]\n", |
| 1108 | + "pbc += [Eq(u[t_s+1, Nx], u[t_s+1, 0])]\n", |
1112 | 1109 | "...\n", |
1113 | | - "\n", |
1114 | | - "op = Operator(bc + (pbc if periodic_bc else []) + [eq])\n", |
1115 | 1110 | "```" |
1116 | 1111 | ] |
1117 | 1112 | }, |
|
1174 | 1169 | "metadata": {}, |
1175 | 1170 | "source": [ |
1176 | 1171 | "```python\n", |
1177 | | - "dx*(0.5*u[0] + 0.5*u[Nx] + np.sum(u[1:-1]))\n", |
| 1172 | + "dx*(0.5*u.data[n][0] + 0.5*u.data[n][Nx] + np.sum(u.data[n][1:Nx]))\n", |
1178 | 1173 | "```" |
1179 | 1174 | ] |
1180 | 1175 | }, |
1181 | 1176 | { |
1182 | 1177 | "cell_type": "markdown", |
1183 | 1178 | "metadata": {}, |
1184 | 1179 | "source": [ |
1185 | | - "if `u` is an array holding the solution.\n", |
| 1180 | + "if `u` is a `TimeFunction` with the `save` parameter set to $Nx+1$ and `n` indicates a current timestep.\n", |
1186 | 1181 | "\n", |
1187 | 1182 | "### The code\n", |
1188 | 1183 | "\n", |
|
1192 | 1187 | }, |
1193 | 1188 | { |
1194 | 1189 | "cell_type": "code", |
1195 | | - "execution_count": 12, |
| 1190 | + "execution_count": 7, |
1196 | 1191 | "metadata": {}, |
1197 | 1192 | "outputs": [], |
1198 | 1193 | "source": [ |
| 1194 | + "# %load -s solver src-advec/advec1D.py\n", |
1199 | 1195 | "def solver(I, U0, v, L, dt, C, T, user_action=None,\n", |
1200 | 1196 | " scheme='FE', periodic_bc=True):\n", |
1201 | | - " Nt = int(round(T/float(dt)))\n", |
| 1197 | + " Nt = int(round(T/np.float64(dt)))\n", |
1202 | 1198 | " t = np.linspace(0, Nt*dt, Nt+1) # Mesh points in time\n", |
1203 | 1199 | " dx = v*dt/C\n", |
1204 | 1200 | " Nx = int(round(L/dx))\n", |
|
1211 | 1207 | " print('dt=%g, dx=%g, Nx=%d, C=%g' % (dt, dx, Nx, C))\n", |
1212 | 1208 | "\n", |
1213 | 1209 | " integral = np.zeros(Nt+1)\n", |
1214 | | - "\n", |
| 1210 | + " \n", |
1215 | 1211 | " grid = Grid(shape=(Nx+1,), extent=(L,), dtype=np.float64)\n", |
| 1212 | + "\n", |
1216 | 1213 | " t_s=grid.time_dim\n", |
1217 | | - " u = None\n", |
1218 | | - " pde = None\n", |
1219 | 1214 | " \n", |
1220 | 1215 | " def u(to=1, so=1):\n", |
1221 | 1216 | " u = TimeFunction(name='u', grid=grid, time_order=to, space_order=so, save=Nt+1)\n", |
|
1226 | 1221 | " pde = u.dtr + v*u.dxc\n", |
1227 | 1222 | " \n", |
1228 | 1223 | " pbc = [Eq(u[t_s+1, 0], u[t_s, 0] - 0.5*C*(u[t_s, 1] - u[t_s, Nx]))]\n", |
1229 | | - " pbc += [Eq(u[t_s, Nx], u[t_s, 0])]\n", |
| 1224 | + " pbc += [Eq(u[t_s+1, Nx], u[t_s+1, 0])]\n", |
1230 | 1225 | " \n", |
1231 | 1226 | " elif scheme == 'LF':\n", |
1232 | | - " # Use UP scheme for first timestep\n", |
1233 | | - " u1 = TimeFunction(name='u1', grid=grid, save=2)\n", |
1234 | | - " pde1 = u1.dtr + v*u1.dxl\n", |
1235 | | - " \n", |
1236 | | - " stencil1 = solve(pde1, u1.forward)\n", |
1237 | | - " eq1 = Eq(u1.forward, stencil1)\n", |
1238 | | - " \n", |
1239 | | - " # Set initial condition u(x,0) = I(x)\n", |
1240 | | - " u1.data[0, :] = [I(xi) for xi in x]\n", |
1241 | | - " \n", |
1242 | | - " bc1 = [Eq(u1[t_s+1, 0], U0)]\n", |
1243 | | - " pbc1 = [Eq(u1[t_s, 0], u1[t_s, Nx])]\n", |
1244 | | - " \n", |
1245 | | - " integral[0] = dx*(0.5*u1.data[0][0] + 0.5*u1.data[0][Nx] + np.sum(u1.data[0][1:Nx]))\n", |
1246 | | - " \n", |
1247 | | - " if user_action is not None:\n", |
1248 | | - " user_action(u1.data[0], x, t, 0)\n", |
1249 | | - " \n", |
1250 | | - " op1 = Operator(bc1 + (pbc1 if periodic_bc else []) + [eq1])\n", |
1251 | | - " op1.apply(dt=dt)\n", |
1252 | | - " \n", |
1253 | | - " integral[1] = dx*(0.5*u1.data[1][0] + 0.5*u1.data[1][Nx] + np.sum(u1.data[1][1:Nx]))\n", |
| 1227 | + " # Use UP scheme for the first timestep\n", |
| 1228 | + " u = u(to=2, so=2)\n", |
| 1229 | + " pde0 = u.dtr(fd_order=1) + v*u.dxl(fd_order=1)\n", |
1254 | 1230 | " \n", |
1255 | | - " if user_action is not None:\n", |
1256 | | - " user_action(u1.data[1], x, t, 1)\n", |
| 1231 | + " stencil0 = solve(pde0, u.forward)\n", |
| 1232 | + " eq0 = Eq(u.forward, stencil0).subs(t_s, 0)\n", |
| 1233 | + "\n", |
| 1234 | + " pbc0 = [Eq(u[t_s, 0], u[t_s, Nx]).subs(t_s, 0)]\n", |
1257 | 1235 | " \n", |
1258 | | - " print('I:', integral[1])\n", |
1259 | | - " \n", |
1260 | 1236 | " # Now continue with LF scheme\n", |
1261 | | - " u = u(to=2, so=2)\n", |
1262 | | - " u.data[0:2, :] = u1.data\n", |
1263 | 1237 | " pde = u.dtc + v*u.dxc\n", |
1264 | 1238 | " \n", |
1265 | | - " pbc = [Eq(u[t_s+1, 0], u[t_s-1, 0] - C*(u[t_s, 1] - u[t_s, Nx - 1]))]\n", |
1266 | | - " pbc += [Eq(u[t_s, Nx], u[t_s, 0])]\n", |
| 1239 | + " pbc = [Eq(u[t_s+1, 0], u[t_s-1, 0] - C*(u[t_s, 1] - u[t_s, Nx-1]))]\n", |
| 1240 | + " pbc += [Eq(u[t_s+1, Nx], u[t_s+1, 0])]\n", |
1267 | 1241 | " \n", |
1268 | 1242 | " elif scheme == 'UP':\n", |
1269 | 1243 | " u = u()\n", |
1270 | 1244 | " pde = u.dtr + v*u.dxl\n", |
1271 | 1245 | " \n", |
1272 | 1246 | " pbc = [Eq(u[t_s, 0], u[t_s, Nx])]\n", |
1273 | | - "\n", |
| 1247 | + " \n", |
| 1248 | + " elif scheme == 'LW':\n", |
| 1249 | + " u = u(so=2)\n", |
| 1250 | + " pde = u.dtr + v*u.dxc - 0.5*dt*v**2*u.dx2\n", |
| 1251 | + " \n", |
| 1252 | + " pbc = [Eq(u[t_s+1, 0], u[t_s, 0] - 0.5*C*(u[t_s, 1] - u[t_s, Nx-1]) + \\\n", |
| 1253 | + " 0.5*C**2*(u[t_s, 1] - 2*u[t_s, 0] + u[t_s, Nx-1]))]\n", |
| 1254 | + " pbc += [Eq(u[t_s+1, Nx], u[t_s+1, 0])]\n", |
| 1255 | + " \n", |
1274 | 1256 | " else:\n", |
1275 | 1257 | " raise ValueError('scheme=\"%s\" not implemented' % scheme)\n", |
1276 | 1258 | "\n", |
1277 | 1259 | " stencil = solve(pde, u.forward)\n", |
1278 | 1260 | " eq = Eq(u.forward, stencil)\n", |
1279 | 1261 | " \n", |
1280 | | - " if scheme != 'LF':\n", |
1281 | | - " # Set initial condition u(x,0) = I(x)\n", |
1282 | | - " u.data[0, :] = [I(xi) for xi in x]\n", |
| 1262 | + " bc_init = [Eq(u[t_s+1, 0], U0).subs(t_s, 0)]\n", |
| 1263 | + " \n", |
| 1264 | + " # Set initial condition u(x,0) = I(x)\n", |
| 1265 | + " u.data[0, :] = [I(xi) for xi in x]\n", |
1283 | 1266 | " \n", |
1284 | | - " # Compute the integral under the curve\n", |
1285 | | - " integral[0] = dx*(0.5*u.data[0][0] + 0.5*u.data[0][Nx] + np.sum(u.data[0][1:Nx]))\n", |
| 1267 | + " # Compute the integral under the curve\n", |
| 1268 | + " integral[0] = dx*(0.5*u.data[0][0] + 0.5*u.data[0][Nx] + np.sum(u.data[0][1:Nx]))\n", |
1286 | 1269 | " \n", |
1287 | | - " if user_action is not None:\n", |
1288 | | - " user_action(u.data[0], x, t, 0)\n", |
| 1270 | + " if user_action is not None:\n", |
| 1271 | + " user_action(u.data[0], x, t, 0)\n", |
1289 | 1272 | "\n", |
1290 | 1273 | " bc = [Eq(u[t_s+1, 0], U0)]\n", |
| 1274 | + " \n", |
| 1275 | + " if scheme == 'LF':\n", |
| 1276 | + " op = Operator((pbc0 if periodic_bc else []) + [eq0] + (bc_init if not periodic_bc else []) \\\n", |
| 1277 | + " + (pbc if periodic_bc else []) + [eq] + (bc if not periodic_bc else []))\n", |
| 1278 | + " else: \n", |
| 1279 | + " op = Operator(bc_init + (pbc if periodic_bc else []) + [eq] + (bc if not periodic_bc else []))\n", |
| 1280 | + " \n", |
| 1281 | + " op.apply(dt=dt, x_m=1, x_M=Nx if scheme == 'UP' else Nx-1)\n", |
1291 | 1282 | "\n", |
1292 | | - " op = Operator(bc + (pbc if periodic_bc else []) + [eq])\n", |
1293 | | - " op.apply(time_m=1 if scheme == 'LF' else 0, time_M=Nt-1, dt=float(dt))\n", |
1294 | | - "\n", |
1295 | | - " for n in range(2 if scheme == 'LF' else 1, Nt+1):\n", |
| 1283 | + " for n in range(1, Nt+1):\n", |
1296 | 1284 | " # Compute the integral under the curve\n", |
1297 | 1285 | " integral[n] = dx*(0.5*u.data[n][0] + 0.5*u.data[n][Nx] + np.sum(u.data[n][1:Nx]))\n", |
1298 | 1286 | "\n", |
|
1317 | 1305 | }, |
1318 | 1306 | { |
1319 | 1307 | "cell_type": "code", |
1320 | | - "execution_count": 15, |
| 1308 | + "execution_count": 8, |
1321 | 1309 | "metadata": {}, |
1322 | 1310 | "outputs": [], |
1323 | 1311 | "source": [ |
1324 | | - "# %load -s run, src-advec/advec1D.py\n", |
1325 | 1312 | "def run(scheme='UP', case='gaussian', C=1, dt=0.01):\n", |
1326 | 1313 | " \"\"\"General admin routine for explicit and implicit solvers.\"\"\"\n", |
1327 | 1314 | "\n", |
|
2397 | 2384 | }, |
2398 | 2385 | { |
2399 | 2386 | "cell_type": "code", |
2400 | | - "execution_count": 152, |
| 2387 | + "execution_count": 17, |
2401 | 2388 | "metadata": {}, |
2402 | 2389 | "outputs": [], |
2403 | 2390 | "source": [ |
|
0 commit comments