| [15d19f3] | 1 | /* First-order "upwind" scheme for 1-dim. advection.
|
|---|
| 2 | * Uses forward differencing in time and makes a choice of forward
|
|---|
| 3 | * or backward differencing in space based on the direction of the fluid flow.
|
|---|
| 4 | * First-order accurate in space and time.
|
|---|
| 5 | * To verify with CIVL:
|
|---|
| 6 | * civl verify upwindFirstOrder.cvl
|
|---|
| 7 | */
|
|---|
| [b444d36] | 8 |
|
|---|
| [15d19f3] | 9 | $input int n; // Number of points
|
|---|
| 10 | $assume(n >= 1);
|
|---|
| 11 | $input double h; // Distance between points
|
|---|
| 12 | $assume(0<h && h<1);
|
|---|
| 13 | $input double dt; // Duration of a time step
|
|---|
| 14 | $assume(0<dt && dt<1);
|
|---|
| 15 | $input double a; // Constant for wave velocity
|
|---|
| [3ff27cf] | 16 | $assume(a != 0);
|
|---|
| [15d19f3] | 17 | $input double u1[n]; // initial values
|
|---|
| 18 | // u:R^2->R has 2 continuous derivatives in [-1,1]x[0,100]
|
|---|
| 19 | $abstract $differentiable(2, [-1,1],[0,100]) $real u($real x, $real t);
|
|---|
| 20 | $input int step; // some arbitrary time step
|
|---|
| 21 | $assume(step >= 0);
|
|---|
| 22 |
|
|---|
| [b444d36] | 23 | double v[n];
|
|---|
| 24 | double v_new[n];
|
|---|
| 25 |
|
|---|
| 26 | void upwindForward() {
|
|---|
| [15d19f3] | 27 | /*@ loop invariant $forall (int j:1..i-1) v_new[j] == v[j] - dt*a*(v[j+1]-v[j])/h;
|
|---|
| 28 | @ loop invariant 1<=i && i<=n-1;
|
|---|
| 29 | @ loop assigns i, v_new[1..n-2];
|
|---|
| 30 | @*/
|
|---|
| [b444d36] | 31 | for (int i = 1; i < n-1; i++) {
|
|---|
| [15d19f3] | 32 | v_new[i] = v[i] - dt*a*(v[i+1] - v[i])/h;
|
|---|
| [b444d36] | 33 | }
|
|---|
| 34 | }
|
|---|
| 35 |
|
|---|
| 36 | void upwindBackward() {
|
|---|
| [15d19f3] | 37 | /*@ loop invariant $forall (int j:1..i-1) v_new[j] == v[j] - dt*a*(v[j]-v[j-1])/h;
|
|---|
| 38 | @ loop invariant 1<=i && i<=n-1;
|
|---|
| 39 | @ loop assigns i, v_new[1..n-2];
|
|---|
| 40 | @*/
|
|---|
| [b444d36] | 41 | for (int i = 1; i < n-1; i++) {
|
|---|
| [15d19f3] | 42 | v_new[i] = v[i] - dt*a*(v[i] - v[i-1])/h;
|
|---|
| [b444d36] | 43 | }
|
|---|
| 44 | }
|
|---|
| 45 |
|
|---|
| 46 | void upwind() {
|
|---|
| 47 | if (a > 0)
|
|---|
| 48 | upwindBackward();
|
|---|
| 49 | else
|
|---|
| 50 | upwindForward();
|
|---|
| [15d19f3] | 51 | /*@ loop invariant 1<=i && i<=n-1;
|
|---|
| 52 | @ loop invariant $forall (int j:1..i-1) v[j] == v_new[j];
|
|---|
| 53 | @ loop assigns i, v[1..n-2];
|
|---|
| 54 | @*/
|
|---|
| [b444d36] | 55 | for (int i = 1; i < n-1; i++) {
|
|---|
| 56 | v[i] = v_new[i];
|
|---|
| 57 | }
|
|---|
| 58 | }
|
|---|
| 59 |
|
|---|
| 60 | void main() {
|
|---|
| [15d19f3] | 61 | $assume(n*h <= 1);
|
|---|
| 62 | $assume(step*dt < 100);
|
|---|
| 63 | $assume($forall (int i:0..n-1) v[i] == u(i*h, step*dt));
|
|---|
| 64 | /*@ loop invariant 0<=i && i<=n;
|
|---|
| 65 | @ loop invariant $forall (int j:0..i-1) v[j] == u1[j];
|
|---|
| 66 | @ loop assigns i, v[0..n-1];
|
|---|
| 67 | @*/
|
|---|
| [b444d36] | 68 | for (int i = 0; i < n; i++) {
|
|---|
| 69 | v[i] = u1[i];
|
|---|
| 70 | }
|
|---|
| 71 | upwind();
|
|---|
| [15d19f3] | 72 | $assert($uniform (int i:1..n-2)
|
|---|
| 73 | (u(i*h, (step+1)*dt)-v[i])/dt - $D[u,{t,1}](i*h, step*dt) - a*$D[u,{x,1}](i*h, step*dt)
|
|---|
| 74 | == $O(dt) + $O(h));
|
|---|
| [b444d36] | 75 | }
|
|---|