|
1 | 1 | { |
2 | 2 | "cells": [ |
3 | 3 | { |
4 | | - "cell_type": "raw", |
| 4 | + "cell_type": "markdown", |
5 | 5 | "metadata": {}, |
6 | 6 | "source": [ |
7 | 7 | "<!-- Equation labels as ordinary links -->\n", |
|
510 | 510 | "metadata": {}, |
511 | 511 | "outputs": [], |
512 | 512 | "source": [ |
| 513 | + "import numpy as np\n", |
| 514 | + "import sympy as sp\n", |
| 515 | + "from devito import Dimension, Constant, TimeFunction, Eq, solve, Operator\n", |
| 516 | + "\n", |
| 517 | + "\n", |
513 | 518 | "def solver(I, V, m, b, s, F, dt, T, damping='linear'):\n", |
514 | 519 | " \"\"\"\n", |
515 | 520 | " Solve m*u'' + f(u') + s(u) = F(t) for t in (0,T],\n", |
|
519 | 524 | " 'quadratic', f(u')=b*u'*abs(u').\n", |
520 | 525 | " F(t) and s(u) are Python functions.\n", |
521 | 526 | " \"\"\"\n", |
522 | | - " dt = float(dt); b = float(b); m = float(m) # avoid integer div.\n", |
| 527 | + " dt = float(dt)\n", |
| 528 | + " b = float(b)\n", |
| 529 | + " m = float(m)\n", |
523 | 530 | " Nt = int(round(T/dt))\n", |
524 | | - " u = np.zeros(Nt+1)\n", |
525 | | - " t = np.linspace(0, Nt*dt, Nt+1)\n", |
| 531 | + " t = Dimension('t', spacing=Constant('h_t'))\n", |
| 532 | + "\n", |
| 533 | + " u = TimeFunction(name='u', dimensions=(t,),\n", |
| 534 | + " shape=(Nt+1,), space_order=2)\n", |
| 535 | + "\n", |
| 536 | + " u.data[0] = I\n", |
526 | 537 | "\n", |
527 | | - " u[0] = I\n", |
528 | 538 | " if damping == 'linear':\n", |
529 | | - " u[1] = u[0] + dt*V + dt**2/(2*m)*(-b*V - s(u[0]) + F(t[0]))\n", |
| 539 | + " # dtc for central difference (default for time is forward, 1st order)\n", |
| 540 | + " eqn = m*u.dt2 + b*u.dtc + s(u) - F(u)\n", |
| 541 | + " stencil = Eq(u.forward, solve(eqn, u.forward))\n", |
530 | 542 | " elif damping == 'quadratic':\n", |
531 | | - " u[1] = u[0] + dt*V + \\\n", |
532 | | - " dt**2/(2*m)*(-b*V*abs(V) - s(u[0]) + F(t[0]))\n", |
| 543 | + " # fd_order set as backward derivative used is 1st order\n", |
| 544 | + " eqn = m*u.dt2 + b*u.dt*sp.Abs(u.dtl(fd_order=1)) + s(u) - F(u)\n", |
| 545 | + " stencil = Eq(u.forward, solve(eqn, u.forward))\n", |
| 546 | + " # First timestep needs to have the backward timestep substituted\n", |
| 547 | + " stencil_init = stencil.subs(u.backward, u.forward-2*t.spacing*V)\n", |
| 548 | + " op_init = Operator(stencil_init, name='first_timestep')\n", |
| 549 | + " op = Operator(stencil, name='main_loop')\n", |
| 550 | + " op_init.apply(h_t=dt, t_M=1)\n", |
| 551 | + " op.apply(h_t=dt, t_m=1, t_M=Nt-1)\n", |
533 | 552 | "\n", |
534 | | - " for n in range(1, Nt):\n", |
535 | | - " if damping == 'linear':\n", |
536 | | - " u[n+1] = (2*m*u[n] + (b*dt/2 - m)*u[n-1] +\n", |
537 | | - " dt**2*(F(t[n]) - s(u[n])))/(m + b*dt/2)\n", |
538 | | - " elif damping == 'quadratic':\n", |
539 | | - " u[n+1] = (2*m*u[n] - m*u[n-1] + b*u[n]*abs(u[n] - u[n-1])\n", |
540 | | - " + dt**2*(F(t[n]) - s(u[n])))/\\\n", |
541 | | - " (m + b*abs(u[n] - u[n-1]))\n", |
542 | | - " return u, t" |
| 553 | + " return u.data, np.linspace(0, Nt*dt, Nt+1)" |
543 | 554 | ] |
544 | 555 | }, |
545 | 556 | { |
|
619 | 630 | "the quadratic polynomial is reproduced by the numerical method (to\n", |
620 | 631 | "machine precision).\n", |
621 | 632 | "\n", |
622 | | - "### Catching bugs\n", |
623 | | - "\n", |
624 | | - "How good are the constant and quadratic solutions at catching\n", |
625 | | - "bugs in the implementation? Let us check that by introducing some bugs.\n", |
626 | | - "\n", |
627 | | - " * Use `m` instead of `2*m` in the denominator of `u[1]`: code works for constant\n", |
628 | | - " solution, but fails (as it should) for a quadratic one.\n", |
629 | | - "\n", |
630 | | - " * Use `b*dt` instead of `b*dt/2` in the updating formula for `u[n+1]`\n", |
631 | | - " in case of linear damping: constant and quadratic both fail.\n", |
632 | | - "\n", |
633 | | - " * Use `F[n+1]` instead of `F[n]` in case of linear or quadratic damping:\n", |
634 | | - " constant solution works, quadratic fails.\n", |
635 | | - "\n", |
636 | | - "We realize that the constant solution is very useful for catching certain bugs because\n", |
637 | | - "of its simplicity (easy to predict what the different terms in the\n", |
638 | | - "formula should evaluate to), while the quadratic solution seems\n", |
639 | | - "capable of detecting all (?) other kinds of typos in the scheme.\n", |
640 | | - "These results demonstrate why we focus so much on exact, simple polynomial\n", |
641 | | - "solutions of the numerical schemes in these writings.\n", |
642 | | - "\n", |
643 | 633 | "<!-- More: classes, cases with pendulum approx u vs sin(u), -->\n", |
644 | 634 | "<!-- making UI via parampool -->\n", |
645 | 635 | "\n", |
|
1470 | 1460 | "cell_type": "code", |
1471 | 1461 | "execution_count": 3, |
1472 | 1462 | "metadata": {}, |
1473 | | - "outputs": [], |
| 1463 | + "outputs": [ |
| 1464 | + { |
| 1465 | + "ename": "ModuleNotFoundError", |
| 1466 | + "evalue": "No module named 'scitools'", |
| 1467 | + "output_type": "error", |
| 1468 | + "traceback": [ |
| 1469 | + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 1470 | + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", |
| 1471 | + "\u001b[0;32m<ipython-input-3-b591f37272a6>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mscitools\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstd\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msympy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msym\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mvib\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msolver\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mvib_solver\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
| 1472 | + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'scitools'" |
| 1473 | + ] |
| 1474 | + } |
| 1475 | + ], |
1474 | 1476 | "source": [ |
1475 | 1477 | "# Reimplementation of vib.py using classes\n", |
1476 | 1478 | "\n", |
|
1858 | 1860 | }, |
1859 | 1861 | { |
1860 | 1862 | "cell_type": "code", |
1861 | | - "execution_count": 4, |
| 1863 | + "execution_count": null, |
1862 | 1864 | "metadata": {}, |
1863 | 1865 | "outputs": [], |
1864 | 1866 | "source": [ |
|
2191 | 2193 | ], |
2192 | 2194 | "metadata": { |
2193 | 2195 | "kernelspec": { |
2194 | | - "display_name": "Python 3", |
| 2196 | + "display_name": "devito", |
2195 | 2197 | "language": "python", |
2196 | | - "name": "python3" |
| 2198 | + "name": "devito" |
2197 | 2199 | }, |
2198 | 2200 | "language_info": { |
2199 | 2201 | "codemirror_mode": { |
|
2205 | 2207 | "name": "python", |
2206 | 2208 | "nbconvert_exporter": "python", |
2207 | 2209 | "pygments_lexer": "ipython3", |
2208 | | - "version": "3.8.3" |
| 2210 | + "version": "3.8.1" |
2209 | 2211 | } |
2210 | 2212 | }, |
2211 | 2213 | "nbformat": 4, |
|
0 commit comments