/*{ */ #define DT_SCALE (1) // (dt*(du/dt)/u) = 1/DT_SCALE #define HDT_SCALE (10) // hdt = dt * HDT_SCALE , h[new] = n[old] + hdt * (dh/dt) #define FORCE_FLUX_H // scale h to conserve Q //#define FORCE_FLUX_U // scale u to conserve Q //#define WALK_H // else use dh/dt /* four ways: (ff = FORCE_FLUX_U, wh = walk_height) ff = 0 wh = 0 ff = 1 wh = 0 ff = 0 wh = 1 ff = 1 wh = 1 -> bad! they give slightly different results, but all seem to do very little after 100,000 steps next todo : feed a closer fit of h(r) walk_h seems to be ugly ******** # dt : 0.0000000000040074 this is 249538354045 steps in a second TOO SMALL! todo : solve dt(h) by r-integration instead --- hydr3 : like hydr2, but on a rectangular domain z is rescaled to y = z/h , 0 #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 = 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; double *h1=NULL,**u1=NULL,**w1=NULL; //allocs double *h2=NULL,**u2=NULL,**w2=NULL; double dr,dt,hdt,otwodr,otwodz,odzdz,odrdr; double *fluxr; double maxdhdt,maxdudt; /*}{ 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; /* protos **/ void dbf(void) { }; void solveU(double **nu); void forceFluxU(double **u); void forceFluxH(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; if ( h == h1 ) { nh = h2; nu = u2; nw = w2; } else { nh = h1; nu = u1; nw = w1; } conditionBoundary(); solveU(nu); u = nu; #ifdef FORCE_FLUX_U forceFluxU(u); #else #ifdef FORCE_FLUX_H forceFluxH(u); #endif #endif solveW(nw); w = nw; #ifdef WALK_H solveH_dhdr(nh); h = nh; #else solveH_dhdt(nh); h = nh; #endif } /*}{*/ void solveU(double **nu) { int ri,zi; int 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 maxdudt ) maxdudt = dtU/Uval; dtU *= dt; nu[ri][zi] = Uval + dtU; if ( (dtU / Uval) > 0.2 ) diffstoobig++; } } if ( diffstoobig > 0 ) printf("%d differentials too big!\n",diffstoobig); } void forceFluxU(double **u) { int ri,zi; double curflux,fixflux; for(ri=0;ri maxdhdt ) maxdhdt = dtH/h[ri]; 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"); 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; /** 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; dt = dz*dz / (3*visc); dt /= DT_SCALE; hdt = dt * HDT_SCALE; printf("dr: %f dz : %f dt : %f\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); 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; time = 0; timestep = save_steps_t; do { for(;timestep