/** Page containing all diagnostics functions and events of the Krabbendijke case. Note that the imported output_silces.h can be found [here](http://basilisk.fr/sandbox/vheusinkveld/myfunctions/output/sliceOf3D.h) */
#include "utils.h"
#if dimension == 3
#include "lambda2.h"
#endif
#include "output_slices.h"
/** Define variables and structures to do: diagnostics, ouput data, output movies. */
struct sDiag dia; // Diagnostics
struct sDiag {
double Ekin; // Total kinetic energy
double EkinOld; // Track changes in kin energy
double WdoneOld; // Track changes in work done
double rotVol; // Diagnosed rotor volum
double bE; // Buoyancy energy
double bEold; // Track changes in buoyancy energy
double diss; // Diagnose dissipation
};
struct sEquiDiag {
int level; // Level for which diagnostics should be done
int ii; // Keep track of how many additions are done
double dtDiag;
double startDiag;
double endDiag;
double dtOutput;
};
// Create variables to make a folder structure
struct sOutput {
double dtDiag;
double dtVisual;
double dtSlices;
double dtProfile;
double startAve;
double dtAve;
char main_dir[12];
char dir[30];
char dir_profiles[60];
char dir_slices[60];
char dir_equifields[60];
char dir_strvel[60];
char dir_refvel[60];
char dir_diffbins[60];
char dir_dts[60];
int sim_i;
};
struct sbViewSettings {
double phi; // Phi for 3D bview movie
double theta; // Theta for 3D bview movie
double sphi; // Polar angle for sliced image RED
double stheta; // Azimuthal angle for sliced image RED
};
/** Initialize structures */
struct sOutput out = {.dtDiag = 1., .dtVisual=1., .dtSlices=5., .dtProfile=60., .main_dir="results", .sim_i=0};
struct sEquiDiag ediag = {.level = 5, .ii = 0, .startDiag = 0., .dtDiag = 0., .dtOutput = 0.};
struct sbViewSettings bvsets = {.phi=0., .theta=0., .sphi=0., .stheta=0.};
event init(i = 0){
bvsets.phi = 0.;
bvsets.theta = -M_PI/6.;
bvsets.sphi = 0.;
bvsets.stheta = 0.;
}
/** Diagnosing: kinetic energy, diagnosed rotor volume, buoyancy energy, ammount of cells used.*/
event diagnostics (t+=out.dtDiag){
int n = 0.;
scalar ekin[]; // Kinetic energy field
double tempVol = 0.; // Temp volume
double tempEkin = 0.; // Temp kinetic energy
double tempDiss = 0.; // Temp dissipation
double maxVel = 0.; // Maximum velocity in fan
double bEnergy = 0.; // Buoyant energy
/** Loop over cells to get diagnostics */
foreach(reduction(+:n) reduction(+:tempVol) reduction(+:tempEkin)
reduction(max:maxVel) reduction(+:bEnergy) reduction(+:tempDiss)) {
tempVol += dv()*fan[];
if(y + Delta/2. <= rot.y0){
bEnergy += dv()*y*(b[] - STRAT(y));
}
foreach_dimension() {
ekin[] += sq(u.x[]);
}
maxVel = max(maxVel, sq(ekin[]));
ekin[] *= 0.5*rho[]*dv();
tempEkin += ekin[];
n++;
}
/** Assign values to respective global sturcture vars */
dia.diss = 1.*tempDiss;
dia.bE = 1.*bEnergy;
dia.rotVol = 1.*tempVol;
dia.Ekin = 1.*tempEkin;
if (pid() == 0){
/** Write away simulation data and case setup for main thread */
char nameOut[90];
char nameCase[90];
snprintf(nameOut, 90, "./%s/output", out.dir);
snprintf(nameCase, 90, "./%s/case", out.dir);
static FILE * fpout = fopen(nameOut, "w");
static FILE * fpca = fopen(nameCase, "w");
if(t==0.){
fprintf(fpca,"L0\tinversion\thubU\tTref\tLambda\txr\tyr\tzr\ttheta\tphit\tr\tW\tP\tcu\trampT\tmaxlvl\tminlvl\teps\n");
fprintf(fpca, "%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%d\t%d\t%g\n",
L0,TREF/gCONST*STRAT(rot.y0), WIND(rot.y0),TREF, Lambda, rot.x0, rot.y0, rot.z0, rot.theta, rot.phit, rot.R, rot.W, rot.P, rot.cu, rot.rampT, maxlevel, minlevel, eps);
fprintf(stderr,"n\tred\tEkin\tWork\tbE\n");
fprintf(fpout,"i\tt\tn\tred\tEkin\tWork\tbE\n");
}
fprintf(fpout, "%d\t%g\t%d\t%g\t%g\t%g\t%g\n",
i,t,n,(double)((1<<(maxlevel*3))/n),dia.Ekin,rot.Work, dia.bE);
fprintf(stderr, "n=%d\t%g\t%g\t%g\t%g\n",n,(double)((1<<(maxlevel*dimension))/n),dia.Ekin,rot.Work,dia.bE);
fflush(fpout);
fflush(fpca);
}
dia.EkinOld = 1.*dia.Ekin;
dia.WdoneOld = 1.*rot.Work;
dia.bEold = 1.*dia.bE;
}
#if dimension == 3
/** diagnose velocity of the passing wind machine*/
event refvelocity(t+=1) {
if(pid() == 0) {
char nameRefvel[90];
snprintf(nameRefvel, 90, "%st=%05g", out.dir_refvel, t);
FILE * fpstr = fopen(nameRefvel, "w");
fprintf(fpstr, "x,v,vx,vy,vz\n");
double length = 300.;
int ntot = 300.;
double vels1[ntot];
double xf0 = rot.x0 - length/2*cos(M_PI/6);
double yf0 = 3;
double zf0 = rot.z0 + length/2*sin(M_PI/6);
for(int n = 0; n < ntot; n++) {
double dist = length*n/ntot;
double xx = xf0 + dist*cos(-M_PI/6);
double yy = yf0;
double zz = zf0 + dist*sin(-M_PI/6);
double valx1 = interpolate(u.x, xx, yy, zz);
double valy1 = interpolate(u.y, xx, yy, zz);
double valz1 = interpolate(u.z, xx, yy, zz);
vels1[n] = sqrt(sq(valx1) + sq(valy1) + sq(valz1));
fprintf(fpstr, "%g,%g,%g,%g,%g,%g\n", xx, zz, vels1[n], valx1, valy1, valz1);
}
fclose(fpstr);
}
}
/** 'DTS' measurments*/
event dts_meas(t += 1) {
if(pid() == 0) {
char nameDtshorS[90];
snprintf(nameDtshorS, 90, "%shorS_t=%05g", out.dir_dts, t);
FILE * fpstrhorS = fopen(nameDtshorS, "w");
fprintf(fpstrhorS, "x,y,z,b\n");
double lengthhorS = 600.;
int ntothorS = 600;
double xf0S = rot.x0 - lengthhorS/2*cos(M_PI/6);
double yf0S = 1;
double zf0S = rot.z0 + lengthhorS/2*sin(M_PI/6);
for(int n = 0; n <= ntothorS; n++) {
double dist = lengthhorS*n/ntothorS;
double xx = xf0S + dist*cos(-M_PI/6);
double yy = yf0S;
double zz = zf0S + dist*sin(-M_PI/6);
double valb = interpolate(b, xx, yy, zz);
fprintf(fpstrhorS, "%g,%g,%g,%g\n", xx, yy, zz, valb);
}
fclose(fpstrhorS);
char nameDtshorL[90];
snprintf(nameDtshorL, 90, "%shorL_t=%05g", out.dir_dts, t);
FILE * fpstrhorL = fopen(nameDtshorL, "w");
fprintf(fpstrhorL, "x,y,z,b\n");
double lengthhorL = 600.;
int ntothorL = 600;
double xf0L = rot.x0 - lengthhorL/2*cos(120*M_PI/180);
double yf0L = 1;
double zf0L = rot.z0 + lengthhorL/2*sin(120*M_PI/180);
for(int n = 0; n <= ntothorL; n++) {
double dist = lengthhorL*n/ntothorL;
double xx = xf0L + dist*cos(-120*M_PI/180);
double yy = yf0L;
double zz = zf0L + dist*sin(-120*M_PI/180);
double valb = interpolate(b, xx, yy, zz);
fprintf(fpstrhorL, "%g,%g,%g,%g\n", xx, yy, zz, valb);
}
fclose(fpstrhorL);
char nameDtsver[90];
snprintf(nameDtsver, 90, "%sverS_t=%05g", out.dir_dts, t);
FILE * fpstrver = fopen(nameDtsver, "w");
fprintf(fpstrver, "x,y,z,b\n");
double lengthver = 20.;
int ntotver = 160;
for(int n = 0; n <= ntotver; n++) {
double dist = lengthver*n/ntotver;
double xx = rot.x0 + 30*cos(-M_PI/6);
double yy = dist;
double zz = rot.z0 + 30*sin(-M_PI/6);
double valb = interpolate(b, xx, yy, zz);
fprintf(fpstrver, "%g,%g,%g,%g\n", xx, yy, zz, valb);
}
fclose(fpstrver);
}
}
#endif
/** Ouputting movies in 2- or 3-D*/
#if dimension == 2
event movies(t += 0.5) {
vertex scalar omega[]; // Vorticity
scalar lev[]; // Grid depth
scalar ekinRho[]; // Kinetic energy
foreach() {
omega[] = ((u.y[1,0] - u.y[-1,0]) - (u.x[0,1] - u.x[0,-1]))/(2*Delta); // Curl(u)
ekinRho[] = 0.5*rho[]*(sq(u.x[]) + sq(u.y[]));
lev[] = level;
}
boundary ({b, lev, omega, ekinRho});
output_ppm (b, file = "ppm2mp4 ./results/buoyancy.mp4", n = 1<<maxlevel, linear = true, max=STRAT(L0), min=STRAT(0.));
output_ppm (ekinRho, file = "ppm2mp4 ./results/ekin.mp4", n = 1<<maxlevel, min = 0, max = 1.*sq(rot.cu));
output_ppm (omega, file = "ppm2mp4 ./results/vort.mp4", n = 1<<maxlevel, linear = true);
output_ppm (lev, file = "ppm2mp4 ./results/grid_depth.mp4", n = 1<<maxlevel, min = minlevel, max = maxlevel);
}
#elif dimension == 3
event movies(t += out.dtVisual) {
scalar l2[];
lambda2(u,l2);
boundary({l2});
view(fov=25, tx = 0., ty = 0., phi=M_PI/2., theta=M_PI/2., width = 800, height = 800);
translate(-rot.x0,-rot.y0,-rot.z0) {
box(notics=false);
isosurface("l2", v=-0.02, color="b", min=STRAT(0.9*roughY0h), max=STRAT(1.1*rot.y0));
draw_vof("fan", fc = {1,0,0});
}
translate(-rot.x0,0,-rot.z0){
squares("u.y", n = {0,1,0}, alpha=2, min=-1, max=1);
}
/** Save file with certain fps*/
char nameVid4[90];
snprintf(nameVid4, 90, "ppm2mp4 -r %g ./%s/visual_3d_ux.mp4", 10., out.dir);
save(nameVid4);
clear();
view(fov=25, tx = 0., ty = 0., phi=M_PI/2., theta=M_PI/2., width = 800, height = 800);
translate(-rot.x0,-rot.y0,-rot.z0) {
box(notics=false);
isosurface("l2", v=-0.02, color="b", min=STRAT(0.9*roughY0h), max=STRAT(1.1*rot.y0));
draw_vof("fan", fc = {1,0,0});
}
translate(-rot.x0,0,-rot.z0){
squares("u.y", n = {0,1,0}, alpha=2, min=-.05, max=.05);
}
/** Save file with certain fps*/
char nameVid3[90];
snprintf(nameVid3, 90, "ppm2mp4 -r %g ./%s/visual_3d_uy.mp4", 10., out.dir);
save(nameVid3);
clear();
view(fov=25, tx = 0., ty = 0., phi=M_PI/2., theta=M_PI/2., width = 800, height = 800);
translate(-rot.x0,-rot.y0,-rot.z0) {
box(notics=false);
isosurface("l2", v=-0.02, color="b", min=STRAT(roughY0h), max=STRAT(2.*rot.y0));
draw_vof("fan", fc = {1,0,0});
}
translate(-rot.x0,0,-rot.z0){
squares("b", n = {0,1,0}, alpha=2, min=0.5*STRAT(2), max=1.5*STRAT(2));
}
/** Save file with certain fps*/
char nameVid1[90];
snprintf(nameVid1, 90, "ppm2mp4 -r %g ./%s/visual_3d_b2.mp4", 10., out.dir);
save(nameVid1);
clear();
view(fov=25, tx = 0., ty = 0., phi=bvsets.phi, theta=bvsets.theta, width = 1200, height = 1200);
translate(-rot.x0,-rot.y0,-rot.z0) {
box(notics=false);
isosurface("l2", v=-0.02, color="b", min=STRAT(0.), max=STRAT(1.5*rot.y0));
draw_vof("fan", fc = {1,0,0});
}
translate(-rot.z0,-rot.y0, -L0){
squares("u.x", n = {0,0,1}, alpha=rot.z0, min=-1, max=1);
cells(n = {0,0,1}, alpha = rot.z0);
}
translate(0.,-rot.y0,-rot.z0){
squares("b", n = {1,0,0}, alpha=rot.x0, min=STRAT(0.), max=STRAT(1.5*rot.y0));
}
/** Save file with certain fps*/
char nameVid2[90];
snprintf(nameVid2, 90, "ppm2mp4 -r %g ./%s/visual_3d_b.mp4", 10., out.dir);
save(nameVid2);
clear();
}
/** Take relevant field slices and write away */
event slices(t=out.dtSlices; t+=out.dtSlices) {
char nameSlice[90];
coord slice = {1., 0., 1.};
int res = L0/2;
for(double yTemp = 0.5; yTemp<=1; yTemp+=0.5) {
slice.y = yTemp/L0;
snprintf(nameSlice, 90, "%st=%05gy=%03g", out.dir_slices, t, yTemp);
FILE * fpsli = fopen(nameSlice, "w");
output_slice(list = (scalar *){b}, fp = fpsli, n = res, linear = true, plane=slice);
fclose(fpsli);
}
for(double yTemp = 2; yTemp<=4.; yTemp+=2.) {
slice.y = yTemp/L0;
snprintf(nameSlice, 90, "%st=%05gy=%03g", out.dir_slices, t, yTemp);
FILE * fpsli = fopen(nameSlice, "w");
output_slice(list = (scalar *){b}, fp = fpsli, n = res, linear = true, plane=slice);
fclose(fpsli);
}
}
#endif
/** Usefull functions */
/** Checks if required folders exists, if not they get created. */
void sim_dir_create(){
sprintf(out.dir, "./%s/%s%02d", out.main_dir, sim_ID, out.sim_i);
sprintf(out.dir_profiles, "%s/profiles/", out.dir);
sprintf(out.dir_slices, "%s/slices/", out.dir);
sprintf(out.dir_equifields, "%s/equifields/", out.dir);
sprintf(out.dir_strvel, "%s/strvel/", out.dir);
sprintf(out.dir_refvel, "%s/refvel/", out.dir);
sprintf(out.dir_diffbins, "%s/diffbins/", out.dir);
sprintf(out.dir_dts, "%s/dts/", out.dir);
if (pid() == 0){
struct stat st = {0};
if (stat(out.main_dir, &st) == -1) {
mkdir(out.main_dir, 0777);
}
if (stat(out.dir, &st) == -1) {
mkdir(out.dir, 0777);
}
if (stat(out.dir_slices, &st) == -1) {
mkdir(out.dir_slices, 0777);
}
if (stat(out.dir_profiles, &st) == -1) {
mkdir(out.dir_profiles, 0777);
}
if (stat(out.dir_equifields, &st) == -1) {
mkdir(out.dir_equifields, 0777);
}
if (stat(out.dir_strvel, &st) == -1) {
mkdir(out.dir_strvel, 0777);
}
if (stat(out.dir_refvel, &st) == -1) {
mkdir(out.dir_refvel, 0777);
}
if (stat(out.dir_diffbins, &st) == -1) {
mkdir(out.dir_diffbins, 0777);
}
if (stat(out.dir_dts, &st) == -1) {
mkdir(out.dir_dts, 0777);
}
}
}