/* functions common to wave_billiard.c, wave_comparison.c, mangrove.c */ void init_xyin(short int * xy_in[NX]) /* initialise table xy_in, needed when obstacles are killed */ // short int * xy_in[NX]; // { int i, j; double xy[2]; for (i=0; i NX-1) imax = NX-1; jmin = ij[1] - range; if (jmin < 0) jmin = 0; jmax = ij[1] + range; if (jmax > NY-1) jmax = NY-1; v = (double)(range*range); for (i=imin; i 0 - phi is wave height, psi is phi at time t-1 */ { int i, j; double xy[2], dist2; for (i=0; i 0.0)&&((xy_in[i][j])||(TWOSPEEDS))) phi[i][j] = INITIAL_AMP*exp(-dist2/INITIAL_VARIANCE)*cos(-sqrt(dist2)/INITIAL_WAVELENGTH); else phi[i][j] = 0.0; psi[i][j] = 0.0; } } void init_circular_wave_xplusminus(double xleft, double yleft, double xright, double yright, double *phi[NX], double *psi[NX], short int * xy_in[NX]) /* initialise field with two drops, x > 0 and x < 0 do not communicate - phi is wave height, psi is phi at time t-1 */ { int i, j; double xy[2], dist2; for (i=0; i y2) dist2 = (xy[0]-x)*(xy[0]-x) + (xy[1]-y2)*(xy[1]-y2); else dist2 = (xy[0]-x)*(xy[0]-x); if ((xy_in[i][j])||(TWOSPEEDS)) phi[i][j] += INITIAL_AMP*factor*exp(-dist2/INITIAL_VARIANCE)*cos(-sqrt(dist2)/INITIAL_WAVELENGTH); } } void damp_vertical_wave(double factor, int range, double x, double y1, double y2, double *phi[NX], double *psi[NX]) /* damp field around (x,y) - phi is wave height, psi is phi at time t-1 */ { int i, j, ij1[2], ij2[2], imin, imax, jmin, jmax; double r2, v; xy_to_ij(x, y1, ij1); xy_to_ij(x, y2, ij2); imin = ij1[0] - range; if (imin < 0) imin = 0; imax = ij2[0] + range; if (imax > NX-1) imax = NX-1; jmin = ij1[1] - range; if (jmin < 0) jmin = 0; jmax = ij2[1] + range; if (jmax > NY-1) jmax = NY-1; v = (double)(range*range); for (i=imin; i ij2[1]) r2 = (double)((i - ij2[0])*(i - ij2[0]) + (j - ij2[1])*(j - ij2[1])); else r2 = (double)((i - ij1[0])*(i - ij1[0])); factor *= 1.0 - exp(-0.5*r2/v); phi[i][j] *= factor; psi[i][j] *= factor; } } } void oscillate_linear_wave(double amplitude, double t, double x1, double y1, double x2, double y2, double *phi[NX], double *psi[NX]) /* oscillating boundary condition at (x,y), beta version */ { int i, j, ij1[2], ij2[2], imin, imax, jmin, jmax, d = 5; double xy[2], dist2; xy_to_ij(x1, y1, ij1); xy_to_ij(x2, y2, ij2); imin = ij1[0] - d; if (imin < 0) imin = 0; imax = ij2[0] + d; if (imax >= NX) imax = NX-1; jmin = ij1[1] - d; if (jmin < 0) jmin = 0; jmax = ij2[1] + d; if (jmax >= NY) jmax = NY-1; for (i = imin; i < imax; i++) for (j = jmin; j < jmax; j++) { ij_to_xy(i, j, xy); dist2 = (xy[0]-x1)*(xy[0]-x1); /* to be improved */ // dist2 = (xy[0]-x)*(xy[0]-x) + (xy[1]-y)*(xy[1]-y); // if (dist2 < 0.01) if (dist2 < 0.001) phi[i][j] = amplitude*exp(-dist2/0.001)*cos(-sqrt(dist2)/0.01)*cos(t*OMEGA); // phi[i][j] += 0.2*exp(-dist2/0.001)*cos(-sqrt(dist2)/0.01)*cos(t*OMEGA); } } void compute_gradient(double *phi[NX], double *psi[NX], double x, double y, double gradient[2]) { double velocity; int iplus, iminus, jplus, jminus, ij[2], i, j; xy_to_ij(x, y, ij); i = ij[0]; j = ij[1]; iplus = (i+1); if (iplus == NX) iplus = NX-1; iminus = (i-1); if (iminus == -1) iminus = 0; jplus = (j+1); if (jplus == NY) jplus = NY-1; jminus = (j-1); if (jminus == -1) jminus = 0; gradient[0] = (phi[iplus][j]-phi[i][j])*(phi[iplus][j]-phi[i][j]) + (phi[i][j] - phi[iminus][j])*(phi[i][j] - phi[iminus][j]); gradient[1] = (phi[i][jplus]-phi[i][j])*(phi[i][jplus]-phi[i][j]) + (phi[i][j] - phi[i][jminus])*(phi[i][j] - phi[i][jminus]); } double compute_energy(double *phi[NX], double *psi[NX], short int *xy_in[NX], int i, int j) { double velocity, energy, gradientx2, gradienty2; int iplus, iminus, jplus, jminus; velocity = (phi[i][j] - psi[i][j]); iplus = (i+1); if (iplus == NX) iplus = NX-1; iminus = (i-1); if (iminus == -1) iminus = 0; jplus = (j+1); if (jplus == NY) jplus = NY-1; jminus = (j-1); if (jminus == -1) jminus = 0; gradientx2 = (phi[iplus][j]-phi[i][j])*(phi[iplus][j]-phi[i][j]) + (phi[i][j] - phi[iminus][j])*(phi[i][j] - phi[iminus][j]); gradienty2 = (phi[i][jplus]-phi[i][j])*(phi[i][jplus]-phi[i][j]) + (phi[i][j] - phi[i][jminus])*(phi[i][j] - phi[i][jminus]); if (xy_in[i][j]) return(E_SCALE*E_SCALE*(velocity*velocity + 0.5*COURANT*COURANT*(gradientx2+gradienty2))); else if (TWOSPEEDS) return(E_SCALE*E_SCALE*(velocity*velocity + 0.5*COURANTB*COURANTB*(gradientx2+gradienty2))); else return(0.0); } void compute_energy_flux(double *phi[NX], double *psi[NX], short int *xy_in[NX], int i, int j, double *gx, double *gy, double *arg, double *module) /* computes energy flux given by c^2 norm(nabla u) du/dt*/ { double velocity, energy, gradientx, gradienty; int iplus, iminus, jplus, jminus; velocity = vabs(phi[i][j] - psi[i][j]); iplus = (i+1); if (iplus == NX) iplus = NX-1; iminus = (i-1); if (iminus == -1) iminus = 0; jplus = (j+1); if (jplus == NY) jplus = NY-1; jminus = (j-1); if (jminus == -1) jminus = 0; gradientx = (phi[iplus][j] - phi[iminus][j]); gradienty = (phi[i][jplus] - phi[i][jminus]); *arg = argument(gradientx,gradienty); if (*arg < 0.0) *arg += DPI; if (*arg > DPI) *arg -= DPI; if ((xy_in[i][j])||(TWOSPEEDS)) { *module = velocity*module2(gradientx, gradienty); *gx = velocity*gradientx; *gy = velocity*gradienty; } else { *module = 0.0; *gx = 0.0; *gy = 0.0; } // if (xy_in[i][j]) return(E_SCALE*E_SCALE*(velocity*COURANT*module2(gradientx,gradienty))); // else if (TWOSPEEDS) return(E_SCALE*E_SCALE*(velocity*COURANTB*module2(gradientx,gradienty))); } double compute_variance(double *phi[NX], double *psi[NX], short int *xy_in[NX]) /* compute the variance of the field, to adjust color scheme */ { int i, j, n = 0; double variance = 0.0; for (i=1; i NY/2) color_scheme(COLOR_SCHEME, phi[i][j], scale, time, rgb); else color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); } glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+1, j); glVertex2i(i+1, j+1); glVertex2i(i, j+1); } } glEnd (); } void draw_wave_e(double *phi[NX], double *psi[NX], double *total_energy[NX], double *color_scale[NX], short int *xy_in[NX], double scale, int time, int plot) /* draw the field, new version with total energy option */ { int i, j, iplus, iminus, jplus, jminus; double rgb[3], xy[2], x1, y1, x2, y2, velocity, field_value, energy, gradientx2, gradienty2, r2; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; i= COL_TURBO) color_scheme_asym(COLOR_SCHEME, energy, scale, time, rgb); else color_scheme(COLOR_SCHEME, energy, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) color_scheme(COLOR_SCHEME, phi[i][j], scale, time, rgb); else color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); else color_scheme(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(energy), scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; energy = LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)); color_scheme(COLOR_SCHEME, energy, scale, time, rgb); break; } } glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+1, j); glVertex2i(i+1, j+1); glVertex2i(i, j+1); } } glEnd (); } void draw_wave_highres(int size, double *phi[NX], double *psi[NX], double *total_energy[NX], short int *xy_in[NX], double scale, int time, int plot) /* draw the field, new version with total energy option */ { int i, j, iplus, iminus, jplus, jminus; double rgb[3], xy[2], x1, y1, x2, y2, velocity, energy, gradientx2, gradienty2; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; i= COL_TURBO) color_scheme_asym(COLOR_SCHEME, energy, scale, time, rgb); else color_scheme(COLOR_SCHEME, energy, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) color_scheme(COLOR_SCHEME, phi[i][j], scale, time, rgb); else color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); else color_scheme(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); // energy = LOG_SHIFT + LOG_SCALE*log(energy); // if (energy < 0.0) energy = 0.0; color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(energy), scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)), scale, time, rgb); break; } } glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+size, j); glVertex2i(i+size, j+size); glVertex2i(i, j+size); } } glEnd (); } void draw_wave_ediss(double *phi[NX], double *psi[NX], double *total_energy[NX], double *color_scale[NX], short int *xy_in[NX], double *gamma[NX], double gammamax, double scale, int time, int plot) /* draw the field with luminosity depending on damping */ { int i, j, k, iplus, iminus, jplus, jminus; double rgb[3], xy[2], x1, y1, x2, y2, velocity, field_value, energy, gradientx2, gradienty2, r2; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; i= COL_TURBO) color_scheme_asym(COLOR_SCHEME, energy, scale, time, rgb); else color_scheme(COLOR_SCHEME, energy, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) color_scheme(COLOR_SCHEME, phi[i][j], scale, time, rgb); else color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); else color_scheme(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(energy), scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)), scale, time, rgb); break; } } for (k=0; k<3; k++) rgb[k]*= 1.0 - gamma[i][j]/gammamax; glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+1, j); glVertex2i(i+1, j+1); glVertex2i(i, j+1); } } glEnd (); } void draw_wave_highres_diss(int size, double *phi[NX], double *psi[NX], double *total_energy[NX], short int *xy_in[NX], double *gamma[NX], double gammamax, double scale, int time, int plot) /* draw the field, new version with total energy option */ { int i, j, k, iplus, iminus, jplus, jminus; double rgb[3], xy[2], x1, y1, x2, y2, velocity, energy, gradientx2, gradienty2; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; i= COL_TURBO) color_scheme_asym(COLOR_SCHEME, energy, scale, time, rgb); else color_scheme(COLOR_SCHEME, energy, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) color_scheme(COLOR_SCHEME, phi[i][j], scale, time, rgb); else color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); else color_scheme(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); // energy = LOG_SHIFT + LOG_SCALE*log(energy); // if (energy < 0.0) energy = 0.0; color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(energy), scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; color_scheme(COLOR_SCHEME, LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)), scale, time, rgb); break; } } for (k=0; k<3; k++) rgb[k]*= 1.0 - gamma[i][j]/gammamax; glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+size, j); glVertex2i(i+size, j+size); glVertex2i(i, j+size); } } glEnd (); } void draw_wave_epalette(double *phi[NX], double *psi[NX], double *total_energy[NX], double *average_energy[NX], double *total_flux, double *color_scale[NX], short int *xy_in[NX], double scale, int time, int plot, int palette, int fade, double fade_value) /* same as draw_wave_e, but with color scheme specification */ { int i, j, k, iplus, iminus, jplus, jminus; double rgb[3], xy[2], x1, y1, x2, y2, velocity, field_value, energy, gradientx2, gradienty2, r2, arg, mod, flux_factor, gx, gy, mgx, mgy, ffactor; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; i= COL_TURBO) color_scheme_asym_palette(COLOR_SCHEME, palette, energy, scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, energy, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) color_scheme_palette(COLOR_SCHEME, palette, phi[i][j], scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym_palette(COLOR_SCHEME, palette, total_energy[i][j]/(double)(time+1), scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, total_energy[i][j]/(double)(time+1), scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); color_scheme_palette(COLOR_SCHEME, palette, LOG_SHIFT + LOG_SCALE*log(energy), scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; energy = LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)); color_scheme_palette(COLOR_SCHEME, palette, energy, scale, time, rgb); break; } case (P_ENERGY_FLUX): { compute_energy_flux(phi, psi, xy_in, i, j, &gx, &gy, &arg, &mod); // color_scheme_palette(C_ONEDIM_LINEAR, palette, arg/DPI, 1.0, 1, rgb); // flux_factor = tanh(mod*E_SCALE); // for (k=0; k<3; k++) rgb[k] *= flux_factor; color_scheme_asym_palette(COLOR_SCHEME, palette, mod*FLUX_SCALE, scale, time, rgb); break; } case (P_TOTAL_ENERGY_FLUX): { // ffactor = 1.0; compute_energy_flux(phi, psi, xy_in, i, j, &gx, &gy, &arg, &mod); total_flux[2*NX*NY + 2*j*NX + 2*i] += gx; total_flux[2*NX*NY + 2*j*NX + 2*i + 1] += gy; total_flux[2*j*NX + 2*i] += total_flux[2*NX*NY + 2*j*NX + 2*i]; total_flux[2*j*NX + 2*i + 1] += total_flux[2*NX*NY + 2*j*NX + 2*i + 1]; // total_flux[2*j*NX + 2*i] *= 1.0 + 1.0/(double)(time+1); // total_flux[2*j*NX + 2*i + 1] *= 1.0 + 1.0/(double)(time+1); // total_flux[2*j*NX + 2*i] *= ffactor; // total_flux[2*j*NX + 2*i + 1] *= ffactor; // total_flux[2*j*NX + 2*i] += gx; // total_flux[2*j*NX + 2*i + 1] += gy; // total_flux[2*j*NX + 2*i] *= 1.0/ffactor; // total_flux[2*j*NX + 2*i + 1] *= 1.0/ffactor; // total_flux[2*j*NX + 2*i] += 0.1*gx; // total_flux[2*j*NX + 2*i + 1] += 0.1*gy; mgx = total_flux[2*j*NX + 2*i]; mgy = total_flux[2*j*NX + 2*i + 1]; // mgx = total_flux[2*j*NX + 2*i]/sqrt((double)(time+1)); // mgy = total_flux[2*j*NX + 2*i + 1]/sqrt((double)(time+1)); // mgx = total_flux[2*j*NX + 2*i]/(1.0 + 0.1*log((double)(time+2))); // mgy = total_flux[2*j*NX + 2*i + 1]/(1.0 + 0.1*log((double)(time+2))); mod = module2(mgx, mgy); arg = argument(mgx, mgy); if (arg < 0.0) arg += DPI; color_scheme_palette(C_ONEDIM_LINEAR, palette, arg/DPI, 1.0, 1, rgb); flux_factor = tanh(mod*FLUX_SCALE); for (k=0; k<3; k++) rgb[k] *= flux_factor; // color_scheme_asym_palette(COLOR_SCHEME, palette, mod, scale, time, rgb); break; } } if (fade) for (k=0; k<3; k++) rgb[k] *= fade_value; glColor3f(rgb[0], rgb[1], rgb[2]); glVertex2i(i, j); glVertex2i(i+1, j); glVertex2i(i+1, j+1); glVertex2i(i, j+1); } } glEnd (); } double wave_value(int i, int j, double *phi[NX], double *psi[NX], double *total_energy[NX], double *average_energy[NX], double *total_flux, short int *xy_in[NX], double scale, int time, int plot, int palette, double rgb[3]) /* compute value of wave and color */ { int k; double value, velocity, energy, gradientx2, gradienty2, arg, mod, flux_factor, gx, gy, mgx, mgy; switch (plot) { case (P_AMPLITUDE): { value = phi[i][j]; color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_ENERGY): { value = compute_energy(phi, psi, xy_in, i, j); /* adjust energy to color palette */ if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym_palette(COLOR_SCHEME, palette, value, scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_MIXED): { if (j > NY/2) value = phi[i][j]; else value = compute_energy(phi, psi, xy_in, i, j); color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); total_energy[i][j] += energy; value = total_energy[i][j]/(double)(time+1); if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym_palette(COLOR_SCHEME, palette, value, scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_LOG_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy < 1.0e-20) energy = 1.0e-20; value = LOG_SHIFT + LOG_SCALE*log(energy); color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_LOG_MEAN_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); if (energy == 0.0) energy = 1.0e-20; total_energy[i][j] += energy; value = LOG_SHIFT + LOG_SCALE*log(total_energy[i][j]/(double)(time+1)); color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_ENERGY_FLUX): { compute_energy_flux(phi, psi, xy_in, i, j, &gx, &gy, &arg, &mod); // color_scheme_palette(C_ONEDIM_LINEAR, palette, arg/DPI, 1.0, 1, rgb); // flux_factor = tanh(mod*E_SCALE); // for (k=0; k<3; k++) rgb[k] *= flux_factor; value = mod*FLUX_SCALE; color_scheme_asym_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_TOTAL_ENERGY_FLUX): { compute_energy_flux(phi, psi, xy_in, i, j, &gx, &gy, &arg, &mod); total_flux[2*j*NX + 2*i] *= 0.99; total_flux[2*j*NX + 2*i + 1] *= 0.99; total_flux[2*j*NX + 2*i] += gx; total_flux[2*j*NX + 2*i + 1] += gy; // mgx = total_flux[2*j*NX + 2*i]/(double)(time+1); // mgy = total_flux[2*j*NX + 2*i + 1]/(double)(time+1); mgx = total_flux[2*j*NX + 2*i]; mgy = total_flux[2*j*NX + 2*i + 1]; // mgx = total_flux[2*j*NX + 2*i]/log((double)(time+2)); // mgy = total_flux[2*j*NX + 2*i + 1]/log((double)(time+2)); mod = module2(mgx, mgy); arg = argument(mgx, mgy); if (arg < 0.0) arg += DPI; value = arg/DPI; color_scheme_palette(C_ONEDIM_LINEAR, palette, value, 1.0, 1, rgb); flux_factor = tanh(mod*E_SCALE); for (k=0; k<3; k++) rgb[k] *= flux_factor; break; } case (P_AVERAGE_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); average_energy[i][j] = AVRG_E_FACTOR*average_energy[i][j] + (1.0 - AVRG_E_FACTOR)*energy; value = average_energy[i][j]; if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym_palette(COLOR_SCHEME, palette, value, scale, time, rgb); else color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } case (P_LOG_AVERAGE_ENERGY): { energy = compute_energy(phi, psi, xy_in, i, j); average_energy[i][j] = AVRG_E_FACTOR*average_energy[i][j] + (1.0 - AVRG_E_FACTOR)*energy; if (average_energy[i][j] == 0.0) value = LOG_SHIFT - 10.0*LOG_SCALE; else value = LOG_SHIFT + LOG_SCALE*log(average_energy[i][j]); color_scheme_palette(COLOR_SCHEME, palette, value, scale, time, rgb); break; } } return(value); } void draw_wave_profile_horizontal(double *values, int size, int average, int pnb, int fade, double fade_value) /* draw a horizontal profile of the wave, if option DRAW_WAVE_PROFILE is active */ { int i, k, ij[2]; double deltav, a, b, y; static int imin, imax, jmin, jmax, jmid, jval, d, first = 1; static double vmin[2], vmax[2], deltaj, ymin, average_vals[NX]; if (first) { imin = 100; imax = NX - 250; if (PROFILE_AT_BOTTOM) { jmin = 50; jmax = 150; } else { jmin = NY - 150; jmax = NY - 50; } jmid = (jmin + jmax)/2; jmid -= (jmid%size); xy_to_ij(0.0, WAVE_PROFILE_Y, ij); jval = ij[1]; jval -= (jval%size); d = (jmax - jmin)/10 + 1; deltaj = (double)(jmax - jmin - 2*d); ymin = (double)(jmin + d); for (i=0; i vmax[pnb]) vmax[pnb] = average_vals[i]; } else { for (i=imin; i vmax) vmax = values[i*NY+jmin]; // if (values[i*NY+jmin] < vmin) vmin = values[i*NY+jmin]; if (values[i*NY+jval] > vmax[pnb]) vmax[pnb] = values[i*NY+jval]; if (values[i*NY+jval] < vmin[pnb]) vmin[pnb] = values[i*NY+jval]; } } // if (vmax <= vmin) vmax = vmin + 0.01; if ((vmin[pnb] < 0.0)&&(vmax[pnb] > 0.0)) { if (vmax[pnb] > -vmin[pnb]) vmin[pnb] = -vmax[pnb]; else if (vmax[pnb] < -vmin[pnb]) vmax[pnb] = -vmin[pnb]; } // printf("vmin = %.3lg, vmax = %.3lg\n", vmin, vmax); deltav = vmax[pnb]-vmin[pnb]; if (deltav <= 0.0) deltav = 0.01; a = deltaj/deltav; b = ymin - a*vmin[pnb]; erase_area_ij(imin, jmin, imax, jmax); if (fade) glColor3f(fade_value, fade_value, fade_value); else glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_STRIP); for (i=imin; i ymin) glVertex2d((double)i, y); } glEnd(); glBegin(GL_LINE_LOOP); glVertex2i(imin, jmin); glVertex2i(imax, jmin); glVertex2i(imax, jmax); glVertex2i(imin, jmax); glEnd(); /* slightly decrease extramal values in case signal gets weaker */ vmax[pnb] *= 0.99; vmin[pnb] *= 0.99; } void draw_wave_profile_vertical(double *values, int size, int average, int pnb, int fade, double fade_value) /* draw a vertical profile of the wave, if option DRAW_WAVE_PROFILE is active */ { int j, k, ij[2]; double deltav, a, b, x; static int imin, imax, ival, jmin, jmax, imid, d, first = 1; static double vmin[2], vmax[2], deltai, xmin, average_vals[NY]; if (first) { jmin = 50; jmax = NY - 50; imin = NX - 150; imax = NX - 50; imid = (imin + imax)/2; imid -= (imid%size); xy_to_ij(WAVE_PROFILE_X, 0.0, ij); ival = ij[0]; ival -= (ival%size); d = (imax - imin)/10 + 1; deltai = (double)(imax - imin - 2*d); xmin = (double)(imin + d); for (j=0; j vmax[pnb]) vmax[pnb] = average_vals[j]; } else { for (j=jmin; j vmax) vmax = values[imin*NY+j]; // if (values[imin*NY+j] < vmin) vmin = values[imin*NY+j]; if (values[ival*NY+j] > vmax[pnb]) vmax[pnb] = values[ival*NY+j]; if (values[ival*NY+j] < vmin[pnb]) vmin[pnb] = values[ival*NY+j]; } /* symmetrize output */ // if ((vmin[pnb] < 0.0)&&(vmax[pnb] > 0.0)) // { // if (vmax[pnb] > -vmin[pnb]) vmin[pnb] = -vmax[pnb]; // else if (vmax[pnb] < -vmin[pnb]) vmax[pnb] = -vmin[pnb]; // } // if (vmax > -vmin) vmin = -vmax; // else if (vmax < -vmin) vmax = -vmin; } // printf("vmin = %.3lg, vmax = %.3lg\n", vmin[pnb], vmax[pnb]); deltav = vmax[pnb]-vmin[pnb]; if (deltav <= 0.0) deltav = 0.01; a = deltai/deltav; b = xmin - a*vmin[pnb]; erase_area_ij(imin, jmin, imax, jmax); if (fade) glColor3f(fade_value, fade_value, fade_value); else glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_STRIP); for (j=jmin; j= xmin) glVertex2d(x, (double)j); } glEnd(); glBegin(GL_LINE_LOOP); glVertex2i(imin, jmin); glVertex2i(imax, jmin); glVertex2i(imax, jmax); glVertex2i(imin, jmax); glEnd(); /* slightly decrease extramal values in case signal gets weaker */ vmax[pnb] *= 0.99; vmin[pnb] *= 0.99; } void draw_wave_profile(double *values, int size, int p_number, int fade, double fade_value) /* draw a profile of the wave, if option DRAW_WAVE_PROFILE is active */ { if (VERTICAL_WAVE_PROFILE) draw_wave_profile_vertical(values, size, AVERAGE_WAVE_PROFILE, p_number, fade, fade_value); if (HORIZONTAL_WAVE_PROFILE) draw_wave_profile_horizontal(values, size, AVERAGE_WAVE_PROFILE, p_number, fade, fade_value); } void draw_exit_timeseries(double xleft, double yleft, double xtest, double ytest, double *values, int size, int top, int symmetrize, int fade, double fade_value) /* draw a profile of the wave, if option DRAW_WAVE_TIMESERIES is active */ { int t, t1, s, padding = 50, nvals = TIMESERIES_NVALUES; double a, b, deltav, x, y, wmin, wmax; static int ij[2], ij_test[2], imin, imax, jmintop, jmaxtop, jminbot, jmaxbot, jmin, jmax, itest, jtest, jtesttop, jtestbot, counter[2], first = 1, window = 5; static double timeseries[TIMESERIES_NVALUES][2], average[TIMESERIES_NVALUES][2], vmin[2], vmax[2], ymin, deltaj, deltai; if (first) { xy_to_ij(xleft, yleft, ij); xy_to_ij(xtest, ytest, ij_test); jmaxtop = NY - padding; jmintop = 2*ij[1] - jmaxtop; jtesttop = ij_test[1]; // printf("jmintop = %i, jmaxtop = %i\n", jmintop, jmaxtop); xy_to_ij(xleft, -yleft, ij); xy_to_ij(xtest, -ytest, ij_test); jminbot = padding; jmaxbot = 2*ij[1] - jminbot; jtestbot = ij_test[1]; // printf("jminbot = %i, jmaxbot = %i\n", jminbot, jmaxbot); imin = ij[0]; imax = NX - padding; deltai = (double)(imax - imin)/(double)nvals; vmin[0] = 1.0e10; vmax[0] = -vmin[0]; vmin[1] = 1.0e10; vmax[1] = -vmin[1]; for (t=0; t vmax[top]) vmax[top] = timeseries[t][top]; if (timeseries[t][top] < vmin[top]) vmin[top] = timeseries[t][top]; } if (symmetrize) { if (vmax[top] > -vmin[top]) vmin[top] = -vmax[top]; else if (vmax[top] < -vmin[top]) vmax[top] = -vmin[top]; } // printf("vmin = %.3lg, vmax = %.3lg\n", vmin[top], vmax[top]); deltav = vmax[top]-vmin[top]; if (deltav <= 0.0) deltav = 0.01; a = deltaj/deltav; b = ymin - a*vmin[top]; /* compute average */ for (t=window; t nvals-1) t1 -= nvals; average[t][top] += timeseries[t1][top]*timeseries[t1][top]; } average[t][top] = sqrt(average[t][top]*0.5/(double)window); } erase_area_ij(imin, jmin, imax, jmax); if (fade) glColor3f(fade_value, 0.0, 0.0); else glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINE_STRIP); for (t=0; t= imin) glVertex2d(x, y); } glEnd(); if (symmetrize) { glBegin(GL_LINE_STRIP); for (t1=window; t1 vmax) vmax = timeseries[t]; if (timeseries[t] < vmin) vmin = timeseries[t]; } if (vmax > -vmin) vmin = -vmax; else if (vmax < -vmin) vmax = -vmin; printf("vmin = %.3lg, vmax = %.3lg\n", vmin, vmax); deltav = vmax-vmin; if (deltav <= 0.0) deltav = 0.01; a = deltaj/deltav; b = ymin - a*vmin; /* compute average */ for (t=window; t nvals-1) t1 -= nvals; average[t] += timeseries[t1]*timeseries[t1]; } average[t] = sqrt(average[t]*0.5/(double)window); } erase_area_ij(imin, jmin, imax, jmax); if (fade) glColor3f(fade_value, fade_value, fade_value); else glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_STRIP); for (t=0; t= imin) glVertex2d(x, y); } glEnd(); glBegin(GL_LINE_STRIP); for (t1=window; t1= NSTEPS) t1 = NSTEPS; // x = (double)imin + deltai*(double)t; x = (double)imin + deltai*(double)(t-ishift); y = a*(double)input_signal[t1] + b; if (t > ishift) glVertex2d(x, y); } glEnd(); // glDisable(GL_SCISSOR_TEST); glBegin(GL_LINE_LOOP); glVertex2i(imin, jmin); glVertex2i(imax, jmin); glVertex2i(imax, jmax); glVertex2i(imin, jmax); glEnd(); } void draw_wave_timeseries(double xleft, double yleft, double xtest, double ytest, double *values, int size, int fade, double fade_value) /* draw a profile of the wave, if option DRAW_WAVE_TIMESERIES is active */ { int symmetrize = 1; draw_exit_timeseries(xleft, yleft, xtest, ytest, values, size, 0, symmetrize, fade, fade_value); if (DRAW_WAVE_TIMESERIES == 2) draw_exit_timeseries(xleft, yleft, xtest, ytest, values, size, 1, symmetrize, fade, fade_value); draw_entrance_timeseries(xleft, yleft, values, size, fade, fade_value); } void draw_wave_timeseries_old(double *values, int size, int fade, double fade_value) /* draw a profile of the wave, if option DRAW_WAVE_TIMESERIES is active */ { draw_exit_timeseries_old(values, size, fade, fade_value); draw_entrance_timeseries(1.0, 1.0, values, size, fade, fade_value); } void draw_wave_highres_palette(int size, double *phi[NX], double *psi[NX], double *total_energy[NX], double *average_energy[NX], double *total_flux, short int *xy_in[NX], double scale, int time, int plot, int palette, int pnumber, int fade, double fade_value) /* same as draw_wave_highres, but with color scheme option */ { int i, j, k, iplus, iminus, jplus, jminus; double value, rgb[3], xy[2], x1, y1, x2, y2, velocity, energy, gradientx2, gradienty2, arg, mod, flux_factor, gx, gy, mgx, mgy; // double vmin, vmax, deltav; static double dtinverse = ((double)NX)/(COURANT*(XMAX-XMIN)), dx = (XMAX-XMIN)/((double)NX); double *values; if ((DRAW_WAVE_PROFILE)||(DRAW_WAVE_TIMESERIES)) values = (double *)malloc(NX*NY*sizeof(double)); glBegin(GL_QUADS); // printf("dtinverse = %.5lg\n", dtinverse); for (i=0; ii3-1)) iplus = i1; // else if ((j>=j2)&&(iplus>i2-1)) iplus = i1; // // iminus = i-1; // if ((j=j2)&&(iminusj3-1)) jplus = j1; // else if ((i>=i2)&&(jplus>j2-1)) jplus = j1; // // jminus = j-1; // if ((i=i2)&&(jminus=i2-1)&&(j>=j2-1)) return(0.0); if ((i>=i3-1)||(j>=j3-1)) return(0.0); } gradientx2 = (phi[iplus*NY+j]-phi[i*NY+j])*(phi[iplus*NY+j]-phi[i*NY+j]) + (phi[i*NY+j] - phi[iminus*NY+j])*(phi[i*NY+j] - phi[iminus*NY+j]); gradienty2 = (phi[i*NY+jplus]-phi[i*NY+j])*(phi[i*NY+jplus]-phi[i*NY+j]) + (phi[i*NY+j] - phi[i*NY+jminus])*(phi[i*NY+j] - phi[i*NY+jminus]); if (xy_in[i*NY+j]) return(E_SCALE*E_SCALE*(velocity*velocity + 0.5*COURANT*COURANT*(gradientx2+gradienty2))); else if (TWOSPEEDS) return(E_SCALE*E_SCALE*(velocity*velocity + 0.5*COURANTB*COURANTB*(gradientx2+gradienty2))); else return(0.0); } void compute_energy_flux_mod(double phi[NX*NY], double psi[NX*NY], short int xy_in[NX*NY], int i, int j, double *gx, double *gy, double *arg, double *module) /* computes energy flux given by c^2 norm(nabla u) du/dt*/ { double velocity, energy, gradientx, gradienty, max = 1.0e5, current_mod, current_arg; int iplus, iminus, jplus, jminus; if ((i == 0)||(i == NX-1)||(j == 0)||(j == NY-1)) { current_mod = 0.0; current_arg = PI; *gx = 0.0; *gy = 0.0; } else if ((xy_in[i*NY+j])||(TWOSPEEDS)) { velocity = vabs(phi[i*NY+j] - psi[i*NY+j]); // iplus = (i+1); /*if (iplus == NX) iplus = NX-1;*/ // iminus = (i-1); /*if (iminus == -1) iminus = 0;*/ // jplus = (j+1); /*if (jplus == NY) jplus = NY-1;*/ // jminus = (j-1); /*if (jminus == -1) jminus = 0;*/ gradientx = (phi[(i+1)*NY+j] - phi[(i-1)*NY+j]); gradienty = (phi[i*NY+j+1] - phi[i*NY+j-1]); if (gradientx > max) gradientx = max; else if (gradientx < -max) gradientx = -max; if (gradienty > max) gradienty = max; else if (gradienty < -max) gradienty = -max; current_mod = velocity*module2(gradientx, gradienty); if (current_mod > 1.0e-10) { current_arg = argument(gradientx,gradienty); if (current_arg < 0.0) current_arg += DPI; if (current_arg >= DPI) current_arg -= DPI; } else current_arg = PI; *gx = velocity*gradientx; *gy = velocity*gradienty; } else { current_mod = 0.0; current_arg = PI; *gx = 0.0; *gy = 0.0; } *module = current_mod; *arg = current_arg; } double compute_phase(double phi[NX*NY], double psi[NX*NY], short int xy_in[NX*NY], int i, int j) { double velocity, angle; velocity = (phi[i*NY+j] - psi[i*NY+j]); if (module2(phi[i*NY+j], velocity) < 1.0e-10) return(0.0); else if (xy_in[i*NY+j]) { angle = argument(phi[i*NY+j], PHASE_FACTOR*velocity/COURANT); if (angle < 0.0) angle += DPI; if ((i==NY/2)&&(j==NY/2)) printf("Phase = %.3lg Pi\n", angle/PI); return(angle); } else if (TWOSPEEDS) { angle = argument(phi[i*NY+j], PHASE_FACTOR*velocity/COURANTB); if (angle < 0.0) angle += DPI; return(angle); } else return(0.0); }