/** # Diagnostics header file for the lumped parameter dirunalcycle case This file uses many of the difinitions from the case set-up for *the* diurnal cycle case of Van Hooft et al (2019). Therefore this header file should be included after all the relevant declarations. For some reason "view.h" needs to be included before those declarations in the set-up file. */ //#include "view.h" //<- Should already be included in the .c file #include "profile5b.h" //profile5c.h is better #include "profflux.h" #include "domainquan.h" #include "slicer.h" #include "lambda2.h" /** A movie is rendered with a frame each half minute. Furthermore, the movie lasts approx 2 min and shows $\lambda_2$-isosurfaces that are coloured with the local buoyancy. Also two slices of the buoyancy gradient and the grid structure at the `front`$=$`back` boundary are displayed. Finally, the surface buoyancy is visualized to reveal the near surface structures if it is not obscured by the $\Lambda_2$ surfaces. */ # if (dimension == 3) float bgc[3]; void bgcsetter (double t){ double day[3] = {126./256., 192./256., 238./256.}; double sun[3] = {253./256., 94./256., 83./256.}; double night[3] = {19./256., 24./256., 98./256.}; double m = max(sin( 2.*M_PI*t/(24*60)), -0.3); if (m > 0.){ m = sqrt(m); for (int l = 0; l<3; l++) bgc[l] = m*day[l] + (1-m)*sun[l]; }else{ m /= -0.3; for (int l = 0; l<3; l++) bgc[l] = m*night[l] + (1-m)*sun[l]; } } event bviewer3D(t+=0.5;t<=T){ double bmax = zi*sq(Nb)*1.0; double bmin = B1/Lambda; scalar gb[],lambda[]; lambda2(u,lambda); // The value of the $\lambfa_2$ isosurface varies with time. double isoval = min(pow(5./3.,(double)maxlevel-6.)*-0.4*sin(t*2*M_PI/T),-0.05); boundary({b}); foreach(){ gb[]=0; foreach_dimension() gb[]+=sq((b[1]-b[-1])/(2*Delta)); gb[]=log10(sqrt(gb[])+1.); } boundary({gb}); double avgb= 0; foreach_boundary(bottom reduction(+:avgb)) avgb += BSURF*sq(Delta); avgb/=sq(L0); double minbr = avgb - 0.1; double maxbr = avgb + 0.1; char title[100]; char des[100]; sprintf(title,"Time Since Sunrise = %02d:%02d (HH:MM)", \ (int)(t/60), (int)floor(fmod(t,60))); sprintf(des, "Lambda2 isosurface: %.2g a.u.", isoval); double shift = L0/2.; double mshift = -L0/2.; coord ny = {0, 1, 0}; //The camera rotates to show a variable perspective. double th = 1.57*sin(t*2.*M_PI/360.); // 1 cycle per 6 "hours" double ph = 0.3 + (0.6*cube(max(sin(t*2.*M_PI/360.),0.))); //"" bgcsetter(t); clear(); view(fov = 17, phi = ph,theta = th, bg = {bgc[0],bgc[1],bgc[2]}, width = 1920, height = 1080); //view(fov = 17, phi = ph, theta = th, bg = {bgc[0],bgc[1],bgc[2]}, // width = 600, height = 400); //cells(n=ny,alpha=0.0011); squares("b", n = ny,alpha = 0.001, min = minbr,max = maxbr, linear = true); cells(alpha = shift, lw = 2); squares("gb", alpha = mshift, min = 0, max=1, linear=true); isosurface("lambda", isoval, "b", min = bmin , bmax); double tc[3]; if (t < 13*60){ tc[0] = 0., tc[1] = 0., tc[2] = 0.; }else tc[0] = 1., tc[1] = 1., tc[2] = 1.; draw_string (title, pos = 3, size = 40 , lc = {tc[0],tc[1],tc[2]}, lw = 5); draw_string(des, pos = 1, size = 60, lc = {tc[0],tc[1],tc[2]}, lw = 3); save ("diurnal.mp4"); } #endif /** Each 48-th part of the simulation run, vertical profiles are outputted for some fields that have our interest. Also we dump the solution for later use to restore and analyse the solution structure in more detail with possibly new knowledge/questions. Furthermore, horizontal slices at some heights are outputted. */ event profs_and_sclices(t+=T/48.){ scalar lev[],e[],lb[],uh[],sgsbflx[]; foreach(){ sgsbflx[]=Kh.y[]*(b[0,1]-b[])/(Delta); uh[]=pow(sq(u.x[])+sq(u.z[]),0.5); lev[]=level; e[]=0; lb[]=0; foreach_dimension(){ e[]+=sq(u.x[]); lb[]+=sq((b[1]-b[-1])/(2.*Delta)); } if (lb[]>0) lb[]=sqrt(lb[]); } char fn[100]; sprintf(fn,"proft=%g",t); profile((scalar*){b,e,u,uh,lb,Evis,sgsbflx,lev},fn); sprintf(fn,"profvart=%g",t); profile_var_flx((scalar*){b,u,uh},fn); for (double yp = Y0; yp<=zi*1.1;yp+=zi/5.){ sprintf(fn,"slicebXZt=%gy=%g",t,yp); sliceXZ(fn,b,yp,maxlevel,true); sprintf(fn,"sliceuyXZt=%gy=%g",t,yp); sliceXZ(fn,u.y,yp,maxlevel,true); } sprintf(fn,"slicebXYt=%gy=%g",t,0.); sliceXY(fn,b,0,maxlevel,false); sprintf(fn,"sliceuyXYt=%gy=%g",t,0.); sliceXY(fn,u.y,0,maxlevel,false); } /** Additionally the simulation is dumped 48 times during the simulation run */ event dumper(t+=T/48){ char fn[100]; sprintf(fn,"dumpt=%g",t); dump(fn); } /** Each time unit (a physical minute) we output some global (i.e. integrated) quantities to track the evolution of the solution. The focus is a bit on the energy budgets. */ event timeseries(t+=1.){ static FILE * fpt = fopen("timeseries","w"); double H = 0, G = 0, Qs = 0,diss = 0, en = 0, bint = 0; foreach(reduction(+:H) reduction(+:G) reduction(+:Qs) reduction(+:diss) \ reduction(+:en) reduction(+:bint)){ double cv =1.; foreach_dimension() cv*=Delta; foreach_dimension(){ en += cv * sq(u.x[]); diss+=Evis[]*cv*(sq(u.x[1] - u.x[-1]) + sq(u.x[0,1] - u.x[0,-1]) + sq(u.x[0,0,1] - u.x[0,0,-1]))/sq(2.*Delta); } bint += (b[]-sq(Nb)*y)*cv; if (y= 0 ? interpolate(s, xp, yp, zp): 0.; ii++; } jj++; } #if _MPI if (pid() == 0){ //Favorite worker MPI_Reduce(MPI_IN_PLACE, &data, No*len, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); }else MPI_Reduce (&data[0], NULL, No*len, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); #endif jj = 0; if (pid() == 0){ for (double yp = miny; yp <= maxy; yp += dy){ int ii = 0; fprintf(fpt, "%g", yp); for (scalar s in list){ fprintf(fpt, "\t%g", data[ii][jj]); ii++; } fprintf(fpt, "\n"); jj++; } } fflush(fpt); } /** Each 25 time steps we output some characteristics of the solver. This aims to trace the solver's performance. */ int gc = 0; double tc = 0; event logfile(i+=25){ fprintf(ferr,"%d\t%g\n",i,t); static FILE * fpp = fopen ("perfs", "w"); if (i == 0) fprintf (fpp, "i t dt mgp.i mgp.nrelax mgu.i mgu.nrelax" "grid->tn perf.t perf.speed npe\n"); fprintf (fpp, "%d %g %g %d %d %d %d %ld %g %g %d\n", i,t, dt, mgp.i, mgp.nrelax, mgu.i, mgu.nrelax, grid->tn, perf.t, perf.speed, npe()); fflush (fpp); #if _MPI MPI_Barrier(MPI_COMM_WORLD); #endif #if TRACE static FILE * fptrace = fopen ("tracing", "w"); trace_print (fptrace, 1); #endif }