/*{ */ #define ADAPTIVE_DT #define HDT_SCALE (10) // hdt = dt * HDT_SCALE , h[new] = n[old] + hdt * (dh/dt) #define FORCE_FLUX_H_UP // scale h to conserve Q //#define FORCE_FLUX_H // scale h to conserve Q //#define FORCE_FLUX_U // scale u to conserve Q //#define SOLVE_H_R // use dh/dr #define SOLVE_H_T // use dh/dt /* # dt : 0.0000000000040074 this is 249538354045 steps in a second TOO SMALL! todo : solve dt(h) by r-integration instead --- hydr4 : adding back Pressure as a variable hydr3 : like hydr2, but on a rectangular domain z is rescaled to y = z/h , 0 #include #include #define fabs(x) ( (x) > 0 ? (x) : (-(x)) ) #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; double dt_scale = 1.0; /** CLI options **/ long save_steps_t = 10000; long steps_t = 1<<30; long max_memory = 2; // megs /* the world: **/ /* h is height[r] * u and w are velocites [r][z] **/ double *h,**u,**w,**p; double *deltah=NULL,**deltau=NULL,**deltaw=NULL; double *h1=NULL,**u1=NULL,**w1=NULL,**p1=NULL; //allocs double *h2=NULL,**u2=NULL,**w2=NULL,**p2=NULL; double dr,mindt,maxdt,dt,hdt,otwodr,otwodz,odzdz,odrdr; double *fluxr; double maxdhdt,maxdudt; int diffstoobig; /*}{ parameters: **/ const double flux = 10; // cm*cm*cm/s const double jetr = 0.1; // cm const double visc = 0.01; // water, gm*cm*cm/s /** computed secondary parameters: **/ double Re,Fr; double jetv,rjump,hjump; double rmin,rmax,hrmin,hrmax; long steps_r,steps_z,topz,topr; /* protos **/ void dbf(void) { }; void solveU(double **nu); void solveP(double **np,double **nw,double **w); void forceFluxU(double **u); void forceFluxH(double **u); void forceFluxHup(double **u); void solveW(double **nw); void solveH_dhdt(double *nh); void solveH_dhdr(double *nh); void conditionBoundary(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); /* * * solve next t * * starts with h,u,w * * returns h,u,w at new t * *************/ /*}{*/ void solveNextT(void) { double *nh,**nu,**nw,**np; if ( h == h1 ) { nh = h2; nu = u2; nw = w2; np = p2; } else { nh = h1; nu = u1; nw = w1; np = p1; } conditionBoundary(); solveU(nu); u = nu; #ifdef FORCE_FLUX_U forceFluxU(u); #else #ifdef FORCE_FLUX_H forceFluxH(u); #else #ifdef FORCE_FLUX_H_UP forceFluxHup(u); #endif #endif #endif solveW(nw); solveP(np,nw,w); p = np; w = nw; #ifdef SOLVE_H_R solveH_dhdr(nh); h = nh; #else #ifdef SOLVE_H_T solveH_dhdt(nh); h = nh; #else #endif #endif } /*}{*/ void solveU(double **nu) { int ri,zi; double r,dz,otwodz,odzdz; double dtU,drU,dzU,drdrU,dzdzU,Uval,Wval,laprU,z,drP; double momentum,viscosity,pressure; diffstoobig = 0; /* find u at new time. The equation is: dt(u) = - (udr + wdz)u -v(lapr(u) + dzdz(u)) - g dr(h) */ maxdudt = 0; for(ri=0;ri 40000000 ) dbf(); deltau[ri][zi] = dtU; nu[ri][zi] = Uval + dt*dtU; if ( fabs(dtU)/Uval > maxdudt ) maxdudt = dtU/Uval; if ( (dt*dtU / Uval) > 0.2 ) diffstoobig++; } } if ( diffstoobig > 0 ) printf("%d differentials too big!\n",diffstoobig); } void solveP(double **np,double **nw,double **w) { int ri,zi; double r,dz,otwodz,odzdz; double dtW,drW,dzW,drdrW,dzdzW,Uval,Wval,z,dzP; double momentum,viscosity; /*** -dzP = [ dt(w) + (udrw + wdzw) ] - gravity + visc*(drdr + dzdz + (1/r)dr)w ****/ for(ri=0;ri maxdhdt ) maxdhdt = dtH/h[ri]; deltah[ri] = dtH; nh[ri] = h[ri] + hdt*dtH; } } void solveH_dhdr(double *h) { int ri; double drH,uv,wv,lastdrH; /* now find h at new t **/ /** use incomp. at surface (from shallow water) */ h[-1] = (jetr*jetr/2)/(rmin-dr); h[0] = (jetr*jetr/2)/(rmin); lastdrH = 0; 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,"# Godwin jump H : %0.9f\n",hjump); fprintf(fp,"# rmin : %0.9f\n",rmin); fprintf(fp,"# rmax : %0.9f\n",rmax); fprintf(fp,"# dr : %0.16f\n",dr); fprintf(fp,"# dt : %0.16f\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,"# max[ (du/dt) / u ] : %f\n",maxdudt); fprintf(fp,"# max[ (dh/dt) / u ] : %f\n",maxdhdt); 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%d.plt",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\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"); fprintf(stderr,"\td\tset 'dt' scale\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); hjump = (jetr*jetr)/(2*rjump); rmin = rjump / 2; rmax = rjump * 5; printf("Godwin rjump : %f, rmin: %f, rmax: %f\n",rjump,rmin,rmax); { long memory; dr = (rmax - rmin) / 10000; for(;;) { steps_r = (rmax - rmin)/dr; steps_z = steps_r/2; 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); } topz = steps_z - 1; topr = steps_r - 1; /** 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 ***/ hrmin = (jetr*jetr)/(2*rmin); hrmax = (jetr*jetr)/(2*rmax); dz = hrmax/(double)topz; mindt = dz*dz / (3*visc); maxdt = dz / jetv; dt = mindt; dt *= dt_scale/100; hdt = dt * HDT_SCALE; printf("dr: %f dz : %0.10f dt : %0.16f\n",dr,dz,dt); otwodr = 0.5 / dr; odrdr = 1.0 / (dr*dr); h1 = vector(steps_r); u1 = matrix(steps_r,steps_z); w1 = matrix(steps_r,steps_z); p1 = matrix(steps_r,steps_z); h2 = vector(steps_r); u2 = matrix(steps_r,steps_z); w2 = matrix(steps_r,steps_z); p2 = matrix(steps_r,steps_z); fluxr = vector(steps_r); deltah = vector(steps_r); deltau = matrix(steps_r,steps_z); deltaw = matrix(steps_r,steps_z); h = h1; p = p1; u = u1; w = w1; conditionTimeZero(); /**/{ int ri,zi; for(ri=0;ri (dt*1.1) ) { dt *= 1.1; if ( dt > maxdt ) dt = maxdt; hdt = dt * HDT_SCALE; numsamedt = 0; } else if ( (dtcut*1.1) < dt ) { dt /= 1.1; if ( dt < mindt ) dt = mindt; hdt = dt * HDT_SCALE; numsamedt = 0; } else { if ( ++numsamedt == 1000 ) { dt *= 1.1; numsamedt = 0; } } if ( diffstoobig > 200 ) { dt /= 2; hdt /= 2; } #endif printf("t#%d, dtH = %0.0f %%, dtU = %0.0f %%, dt = %0.16f\n",time,maxdhdt,maxdudt,dt); ++time; secs += dt; } timestep = 0; printf("saving, time = %0.16f seconds\n",secs); saveState(time); } while ( time < steps_t ); } void saveState(int time) { saveVector("h",h,steps_r,time); saveMatrices("uw",u,w,time); //saveMatrix("u",u,time); //saveMatrix("w",w,time); saveMatrices("duw",deltau,deltaw,time); #ifdef SOLVE_H_DT saveVector("dh",deltah,steps_r,time); #endif #ifndef FORCE_FLUX_U #ifndef FORCE_FLUX_H #ifndef FORCE_FLUX_H_UP zintegrate(fluxr,u); { int ri; for(ri=0;ri