/*
This file is part of EZRide.
Copyright 2010 Vadim Biktashev & Andrew Foulkes.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "ezride.h"
#include
#include
static const Real zero = 0.;
/* ========================================================================= */
Real LX2, LY2, cx=0.0, cy=0.0, omega, Utip, Vtip;
Real stab_cx, stab_cy, stab_om, dt_o_2h;
Real cx_prev, cy_prev, om_prev, diff_cx, diff_cy, diff_om;
int NX2, NY2, x_inc, y_inc;
int cxdiff, cydiff, omdiff, istep, plot_step;
/* ========================================================================= */
void Step1 (void)
{
int i,j;
Real conv1,conv2,Ux,Uy,Vx,Vy;
Real x,y;
Real dudt,dvdt,du1dt,dudx,du1dx,dvdx,dudy,du1dy,dvdy;
Real small=1.e-9;
Real denom=1;
Real det;
Real Ut,U1x,U1y,U1t,Vt;
/* Find the spatial derivatives needed to determine the comoving frame displacement */
/* 2nd order upstream schemes, directions determined by previous values of cx, cy */
if (cx>0.0) {
Ux = -U(NX2+2 ,NY2 ) + (4*U(NX2+1 ,NY2 )) - (3*U(NX2 ,NY2 ));
Vx = -V(NX2+2 ,NY2 ) + (4*V(NX2+1 ,NY2 )) - (3*V(NX2 ,NY2 ));
U1x = -U(NX2+x_inc+2 ,NY2+y_inc ) + (4*U(NX2+x_inc+1 ,NY2+y_inc )) - (3*U(NX2+x_inc ,NY2+y_inc ));
} else if (cx< 0.0) {
Ux = U(NX2-2 ,NY2 ) - (4*U(NX2-1 ,NY2 )) + (3*U(NX2 ,NY2 ));
Vx = V(NX2-2 ,NY2 ) - (4*V(NX2-1 ,NY2 )) + (3*V(NX2 ,NY2 ));
U1x = U(NX2+x_inc-2 ,NY2+y_inc ) - (4*U(NX2+x_inc-1 ,NY2+y_inc )) + (3*U(NX2+x_inc ,NY2+y_inc ));
} else {
Ux = U(NX2+1,NY2) - U(NX2-1,NY2);
Vx = V(NX2+1,NY2) - V(NX2-1,NY2);
U1x = U(NX2+x_inc+1,NY2+y_inc) - U(NX2+x_inc-1,NY2+y_inc);
}
if (cy>0.0) {
Uy = -U(NX2 ,NY2+2 ) + (4*U(NX2 ,NY2+1 )) - (3*U(NX2 ,NY2 ));
Vy = -V(NX2 ,NY2+2 ) + (4*V(NX2 ,NY2+1 )) - (3*V(NX2 ,NY2 ));
U1y = -U(NX2+x_inc ,NY2+y_inc+2 ) + (4*U(NX2+x_inc ,NY2+y_inc+1 )) - (3*U(NX2+x_inc ,NY2+y_inc ));
} else if (cy<0.0) {
Uy = U(NX2 ,NY2-2 ) - (4*U(NX2 ,NY2-1 )) + (3*U(NX2 ,NY2 ));
Vy = V(NX2 ,NY2-2 ) - (4*V(NX2 ,NY2-1 )) + (3*V(NX2 ,NY2 ));
U1y = U(NX2+x_inc ,NY2+y_inc-2 ) - (4*U(NX2+x_inc ,NY2+y_inc-1 )) + (3*U(NX2+x_inc ,NY2+y_inc ));
} else {
Uy = U(NX2,NY2+1) - U(NX2,NY2-1);
Vy = V(NX2,NY2+1) - V(NX2,NY2-1);
U1y = U(NX2+x_inc,NY2+y_inc+1) - U(NX2+x_inc,NY2+y_inc-1);
}
/* Time derivatives */
Ut = Utip - U(NX2 ,NY2 );
Vt = Vtip - V(NX2 ,NY2 );
U1t = Utip - U(NX2+x_inc,NY2+y_inc);
dudt = Ut/dt; /*du(x0,y0)/dt*/
dudx = Ux/(2*grid_h); /*du(x0,y0)/dx*/
dudy = Uy/(2*grid_h); /*du(x0,y0)/dy*/
dvdt = Vt/dt; /*dv(x0,y0)/dt*/
dvdx = Vx/(2*grid_h); /*dv(x0,y0)/dx*/
dvdy = Vy/(2*grid_h); /*dv(x0,y0)/dy*/
du1dt = U1t/dt; /*du(x0+inc,y0)/dt*/
du1dx = U1x/(2*grid_h); /*dv(x0+inc,y0)/dx*/
du1dy = U1y/(2*grid_h); /*dv(x0+inc,y0)/dy*/
/* Now find the FoR displacement by solving the linear system for pinning conditions at the next time layer */
det = (dudx*dvdy) - (dudy*dvdx);
cy = (fabs(det)>small)? (((dudx*dvdt)-(dudt*dvdx))/det) : zero;
cx = (fabs(det)>small)? (((dudt*dvdy)-(dvdt*dudy))/det) : zero;
if (cx > stab_cx) cx = stab_cx;
if (cx < -stab_cx) cx = -stab_cx;
if (cy > stab_cy) cy = stab_cy;
if (cy < -stab_cy) cy = -stab_cy;
denom = (x_inc*grid_h*du1dy) - (y_inc*grid_h*du1dx);
omega = (fabs(denom)>small) ? ((du1dt-(cx*du1dx)-(cy*du1dy))/denom) : zero;
if (omega > stab_om) omega = zero;
if (omega < -stab_om) omega = zero;
if (V(x_inc+NX2,y_inc+NY2) > Vtip) omega = zero;
/* Now perform the "convection" part-step */
for (i=1;i<=NX;i++){
for (j=1;j<=NY;j++){
x = (i*grid_h)-LX2;
y = (j*grid_h)-LY2;
conv1 = cx - (y*omega);
conv2 = cy + (x*omega);
if(conv1>0) {
if (i==NX) {
Ux = -U(NX-2,j) + (4*U(NX-1,j))-(3*U(NX,j));
Vx = -V(NX-2,j) + (4*V(NX-1,j))-(3*V(NX,j));
} else if (i==NX-1) {
Ux = -U(NX-1,j) + (4*U(NX,j))-(3*U(NX-1,j));
Vx = -V(NX-1,j) + (4*V(NX,j))-(3*V(NX-1,j));
} else {
Ux = -U( i+2,j) + (4*U(i+1,j))-(3*U(i,j));
Vx = -V( i+2,j) + (4*V(i+1,j))-(3*V(i,j));
}
} else {
if (i==1) {
Ux = U( 3,j) - (4*U(2,j)) + (3*U(1,j));
Vx = V( 3,j) - (4*V(2,j)) + (3*V(1,j));
} else if (i==2) {
Ux = U( 2,j) - (4*U(1,j)) + (3*U(2,j));
Vx = V( 2,j) - (4*V(1,j)) + (3*V(2,j));
} else {
Ux = U(i-2,j) - (4*U(i-1,j)) + (3*U(i,j));
Vx = V(i-2,j) - (4*V(i-1,j)) + (3*V(i,j));
}
}
if (conv2>0) {
if (j==NY) {
Uy = -U(i,NY-2) + (4*U(i,NY-1)) - (3*U(i,NY));
Vy = -V(i,NY-2) + (4*V(i,NY-1)) - (3*V(i,NY));
} else if (j==NY-1) {
Uy = -U(i,NY-1) + (4*U(i, NY)) - (3*U(i,NY-1));
Vy = -V(i,NY-1) + (4*V(i, NY)) - (3*V(i,NY-1));
} else {
Uy = -U(i, j+2) + (4*U(i, j+1)) - (3*U(i,j));
Vy = -V(i, j+2) + (4*V(i, j+1)) - (3*V(i,j));
}
} else {
if (j==1) {
Uy = U(i, 3) - (4*U(i, 2)) + (3*U(i,1));
Vy = V(i, 3) - (4*V(i, 2)) + (3*V(i,1));
} else if (j==2) {
Uy = U(i, 2) - (4*U(i, 1)) + (3*U(i,2));
Vy = V(i, 2) - (4*V(i, 1)) + (3*V(i,2));
} else {
Uy = U(i,j-2) - (4*U(i,j-1)) + (3*U(i,j));
Vy = V(i,j-2) - (4*V(i,j-1)) + (3*V(i,j));
}
}
U1(i,j) = U(i,j) + (dt_o_2h*((conv1*Ux) + (conv2*Uy)));
V1(i,j) = V(i,j) + (dt_o_2h*((conv1*Vx) + (conv2*Vy)));
}
}
for (i=1;i<=NX;i++){
for (j=1;j<=NY;j++){
U(i,j) = U1(i,j);
V(i,j) = V1(i,j);
}
}
/* Counters that can be used to register convergence to relative equilbrium */
if(istep%plot_step==0){
if(omega!=zero){
diff_cx = cx-cx_prev;
diff_cy = cy-cy_prev;
diff_om = omega-om_prev;
if (diff_cx==0) cxdiff += 1;
else cxdiff = 0;
if (diff_cy==0) cydiff += 1;
else cydiff = 0;
if (diff_om==0) omdiff += 1;
else omdiff = 0;}
cx_prev=cx;
cy_prev=cy;
om_prev=omega;
}
}
/* ========================================================================= */