/* the whole velocity field is blowing up, and then the flux is falling off in a curve something's blowing out at zi = 0 ---- there's a wiggle in h(r) with an r = 0.2 period the period seems to grow linearly with r -> it's the way zimax(r) has big steps in it. */ /* { hydr2 : approximate model. the approximation is : set P = pg(h-z) this overspecifies u and w, so now we drop the Navier-Stokes in w. note that w is NOT zero or directly connected to u now. The equations of motion are: incompressibility : dz(w) = (-1/r)*dr(ru) navier-stokes : (dt + udr + wdz)u = -v(drdz(w) - dzdz(u)) - g dr(h) boundary evolution : dt(h) = w@h - u@h dr(h) * } * { */ /*** * * note : all numbers are in cm, sec. and gm. * ***/ #include #include #include #define smartfree(ptr) if ( ptr == NULL ) ; else { free(ptr); ptr = NULL; } typedef unsigned long ulong; #ifndef PI #define PI ((double)3.14159265358979323846) #endif /** constants : **/ #define PAD 1 const double gravity = 980.0; /** CLI options **/ long save_steps_t = 100; long steps_t = 1001; long max_memory = 5; // megs /*}*{ the world: **/ /* h is height[r] * u and w are velocites [r][z] **/ double *h,**u,**w; double *h1=NULL,**u1=NULL,**w1=NULL; //allocs double *h2=NULL,**u2=NULL,**w2=NULL; double dr,dz,dt,otwodr,otwodz,odzdz,odrdr; double *fluxr; /*}*{ parameters: **/ const double flux = 20; // cm*cm*cm/s const double jetr = 0.2; // cm const double visc = 0.01; // water, gm*cm*cm/s /** computed secondary parameters: **/ double Re,Fr; double jetv,rjump; double rmin,rmax,zmax,hseed; long steps_r,steps_z; /*}*{ protos **/ void dbf(void) { }; void conditionTimeZero(void); void solveNextTmaster(void); void solveNextT(void); void saveState(int time); void saveInfoHeader(FILE *fp,char *name,int timestep); void saveVector(char *name,double *vector,int length,int timestep); void saveMatrix(char *name,double **matrix,int timestep); void saveMatrices(char *name,double **matrix1,double **matrix2,int timestep); void zintegrate(double *integralptr,double **f); double *vector(int size); double **matrix(int sizex,int sizey); void freevector(double *v); void freematrix(double **m); void cleanup(char *mess,int ret); void writestr_init(FILE *fp); void writestr_flush(void); void writestr(char *str); /*}*{* do it ***/ int main(int argc,char *argv[]) { /** get cli options **/ while(--argc) { char *arg; arg = *(++argv); while(*arg == '-' || *arg == '/') arg++; switch(*arg++) { case 'm': case 'M': while(*arg == '=' || *arg == ':') arg++; max_memory = atol(arg); fprintf(stderr,"got max_mem = %d megs\n",max_memory); break; case 's': case 'S': while(*arg == '=' || *arg == ':') arg++; save_steps_t = atol(arg); fprintf(stderr,"got save_time_steps = %d\n",save_steps_t); break; case 't': case 'T': while(*arg == '=' || *arg == ':') arg++; steps_t = atol(arg); fprintf(stderr,"got time_steps = %d\n",steps_t); break; case '?': case 'h': case 'H': fprintf(stderr,"usage : hydr [-,/] \n"); fprintf(stderr,"tags:\n"); fprintf(stderr,"\tt\tnumber of time steps\n"); fprintf(stderr,"\tm\tmaximum megs of memory to use\n"); fprintf(stderr,"\ts\ttime steps between saves\n"); break; default: fprintf(stderr,"warning: unknown tag %s\n",arg-1); break; } } /** flux,jetr,visc are the seeds; find other init-values **/ jetv = flux/(PI*jetr*jetr); Re = jetv * jetr / visc; Fr = jetv / sqrt(gravity*jetr); printf("Reynolds : %f , Froude: %f\n",Re,Fr); // prediction from trivial Godwin rjump = jetr * pow(Re,0.33333333333333333); rmin = rjump * 0.5; rmax = rjump * 20.0; zmax = (jetr * jetr)/rmin; // twice z at r = rmin printf("Godwin rjump : %f\n",rjump); printf("rmin: %f , rmax: %f , zmax: %f\n",rmin,rmax,zmax); { long memory; dr = (rmax - rmin) / 10000; for(;;) { dz = dr / 100.0; // is this ratio ok? steps_r = (rmax - rmin)/dr; steps_z = (zmax/dz); memory = (steps_r*steps_z*sizeof(double)*4) >> 20; //count megs if ( memory < max_memory ) break; dr *= 2.0; } printf("steps_r : %d steps_z : %d memory used: %d megs\n",steps_r,steps_z,memory); } //dt = (dr / jetv) / 10.0; /** do (dr/jetv) to make a dt in the right units then take 1/10 cuz dt << dr **/ /*** at time 0: dzdzU = 3jetv/hh choose a dt such that:: (dt * visc * dzdzU) = U/10 dt = U/(10*visc*dzdzU) approx h = dz ***/ dt = dz*dz / (300*visc); printf("dr: %f dz : %f dt : %f\n",dr,dz,dt); otwodr = 0.5 / dr; otwodz = 0.5 / dz; odzdz = 1.0 / (dz*dz); odrdr = 1.0 / (dr*dr); h1 = vector(steps_r); u1 = matrix(steps_r,steps_z); w1 = matrix(steps_r,steps_z); h2 = vector(steps_r); u2 = matrix(steps_r,steps_z); w2 = matrix(steps_r,steps_z); fluxr = vector(steps_r); h = h1; u = u1; w = w1; conditionTimeZero(); solveNextTmaster(); cleanup("exit",0); return 0; } void cleanup(char *mess,int ret) { freevector(fluxr); freevector(h1); freevector(h2); freematrix(u1); freematrix(u2); freematrix(w1); freematrix(w2); fprintf(stderr,"%s\n",mess); exit(ret); } /* } * { */ void solveNextTmaster(void) { int time,timestep,ri; time = 0; timestep = save_steps_t; do { for(;timestep steps_z ) { saveState(time); printf("h(%f) = %f \n",(ri*dr + rmin),h[ri]); dbf(); cleanup("h[ri] too large",10); } } solveNextT(); ++time; } timestep = 0; saveState(time); } while ( time < steps_t ); } void saveState(int time) { int ri; saveVector("h",h,steps_r,time); saveMatrix("u",u,time); saveMatrix("w",w,time); saveMatrices("uw",u,w,time); zintegrate(fluxr,u); for(ri=0;ri= zmax ) { // we're at a z-boundary if ( zi == 0 ) { dzU = ( u[ri][1] - u[ri][0] )/dz; dzdzU = ( u[ri][2] + u[ri][0] - 2*u[ri][1])/(dz*dz); } else { dzU = ( u[ri][zi] - u[ri][zi-1] )/dz; dzdzU = ( u[ri][zi] + u[ri][zi-2] - 2*u[ri][zi-1])/(dz*dz); } } else { // not at bdry: dzU = ( u[ri][zi+1] - u[ri][zi-1] )*otwodz; dzdzU = ( u[ri][zi+1] + u[ri][zi-1] - (Uval+Uval) )*odzdz; } laprU = drdrU + drU/r - Uval/(r*r); momentum = Uval*drU + Wval*dzU; viscosity = visc*(dzdzU + laprU); pressure = - gravity*drH; dtU = pressure + viscosity - momentum; dtU *= dt; nu[ri][zi] = Uval + dtU; if ( (dtU / Uval) > 0.5 && (zi*dz) < h[ri] ) printf(" differential too big!\n"); } } u = nu; w = nw; // use nu, not u /*}*{ we have u at new time. now find w. we use incompressibility: dz(w) = (-1/r)*dr(ru) = - (u/r + dru) w(z=0) = 0 */ for(ri=0;ri= steps_z ) { saveState(-1); printf("nh(%f) = %f ; oldh = %f ; ri = %d, zi = %d, newzi = %d\n",r,nh[ri],height,ri,zi,newzi); printf("drH = %f, u = %f, w = %f, dtH = %f, dt*dtH = %f\n",drH,nu[ri][zi],nw[ri][zi],dtH,dt*dtH); dbf(); cleanup("nh[ri] blown!",10); } if ( newzi > zi ) { int i; // we've opend up a new square(s): // copy the heighest value on up for(i=zi+1;i<=newzi;i++) { u[ri][i] = u[ri][zi]; w[ri][i] = w[ri][zi]; } } } /*}* swap the pointers **/ h = nh; u = nu; w = nw; } /* } * { */ void zintegrate(double *integralptr,double **f) { int ri,zi,zimax; double integral; for(ri=0;ri integralptr[ri] = integral; } } /* } * { */ void saveInfoHeader(FILE *fp,char *name,int timestep) { fprintf(fp,"# hydraulic jump %s profile\n",name); fprintf(fp,"#\n"); fprintf(fp,"# time step : %d\n",timestep); fprintf(fp,"#\n"); fprintf(fp,"# all units are in seconds, cm, and grams.\n"); fprintf(fp,"#\n"); fprintf(fp,"# Reynolds : %0.9f\n",Re); fprintf(fp,"# Froude : %0.9f\n",Fr); fprintf(fp,"# flux : %0.9f\n",flux); fprintf(fp,"# viscocity (Kinematic) : %0.9f\n",visc); fprintf(fp,"# jetr : %0.9f\n",jetr); fprintf(fp,"# jetv : %0.9f\n",jetv); fprintf(fp,"# Godwin jump R : %0.9f\n",rjump); fprintf(fp,"# zmax = h(jetr) : %0.9f\n",zmax); fprintf(fp,"# rmin : %0.9f\n",rmin); fprintf(fp,"# rmax : %0.9f\n",rmax); fprintf(fp,"# dr : %0.9f\n",dr); fprintf(fp,"# dz : %0.9f\n",dz); fprintf(fp,"# dt : %0.9f\n",dt); fprintf(fp,"# steps_r : %ld\n",steps_r); fprintf(fp,"# steps_z : %ld\n",steps_z); fprintf(fp,"# steps_t : %ld\n",steps_t); fprintf(fp,"#\n"); } void saveVector(char *name,double *vector,int length,int timestep) { FILE *fp; char str[100]; char fname[100]; sprintf(fname,"dat\\%s.%03d",name,timestep); fp = fopen(fname,"wb"); if ( ! fp ) { puts("fopen failed!"); } else { int i; saveInfoHeader(fp,name,timestep); writestr_init(fp); for(i=0;i steps_z ) zimax = steps_z; for(zi=0;zi steps_z ) zimax = steps_z; for(zi=0;zi