Add files via upload

This commit is contained in:
nilsberglund-orleans 2021-10-24 15:20:56 +02:00 committed by GitHub
parent 660e3d15fd
commit dadfb985ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 3207 additions and 502 deletions

1183
colormaps.c Normal file

File diff suppressed because it is too large Load Diff

130
colors_waves.c Normal file
View File

@ -0,0 +1,130 @@
#include "colormaps.c"
double color_amplitude(double value, double scale, int time)
/* transforms the wave amplitude into a double in [-1,1] to feed into color scheme */
{
return(tanh(SLOPE*value/scale)*exp(-((double)time*ATTENUATION)));
}
double color_amplitude_asym(double value, double scale, int time)
/* transforms the wave amplitude into a double in [-1,1] to feed into color scheme */
{
return(2.0*tanh(SLOPE*value/scale)*exp(-((double)time*ATTENUATION)) - 1.0);
}
void color_scheme(int scheme, double value, double scale, int time, double rgb[3]) /* color scheme */
{
double hue, y, r, amplitude;
int intpart;
/* saturation = r, luminosity = y */
switch (scheme) {
case (C_LUM):
{
hue = COLORHUE + (double)time*COLORDRIFT/(double)NSTEPS;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = LUMMEAN + amplitude*LUMAMP;
intpart = (int)y;
y -= (double)intpart;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_HUE):
{
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = 0.5;
hue = HUEMEAN + amplitude*HUEAMP;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_ONEDIM):
{
amplitude = color_amplitude(value, scale, time);
amp_to_rgb(0.5*(1.0 + amplitude), rgb);
break;
}
}
}
void color_scheme_lum(int scheme, double value, double scale, int time, double lum, double rgb[3]) /* color scheme */
{
double hue, y, r, amplitude;
int intpart;
/* saturation = r, luminosity = y */
switch (scheme) {
case (C_LUM):
{
hue = COLORHUE + (double)time*COLORDRIFT/(double)NSTEPS;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = LUMMEAN + amplitude*LUMAMP;
intpart = (int)y;
y -= (double)intpart;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_HUE):
{
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = lum;
hue = HUEMEAN + amplitude*HUEAMP;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
hsl_to_rgb(hue, r, y, rgb);
break;
}
}
}
void color_scheme_asym(int scheme, double value, double scale, int time, double rgb[3]) /* color scheme */
{
double hue, y, r, amplitude;
int intpart;
/* saturation = r, luminosity = y */
switch (scheme) {
case (C_LUM):
{
hue = COLORHUE + (double)time*COLORDRIFT/(double)NSTEPS;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = LUMMEAN + amplitude*LUMAMP;
intpart = (int)y;
y -= (double)intpart;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_HUE):
{
r = 0.9;
amplitude = color_amplitude_asym(value, scale, time);
y = 0.5;
hue = HUEMEAN + 0.8*amplitude*HUEAMP;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_ONEDIM):
{
amplitude = color_amplitude(value, scale, time);
amp_to_rgb(amplitude, rgb);
break;
}
}
}

View File

@ -30,14 +30,14 @@
#define MOVIE 0 /* set to 1 to generate movie */
// #define WINWIDTH 720 /* window width */
#define WINWIDTH 1280 /* window width */
#define WINWIDTH 720 /* window width */
// #define WINWIDTH 1280 /* window width */
#define WINHEIGHT 720 /* window height */
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
// #define XMIN -1.125
// #define XMAX 1.125 /* x interval */
// #define XMIN -2.0
// #define XMAX 2.0 /* x interval */
#define XMIN -1.125
#define XMAX 1.125 /* x interval */
#define YMIN -1.125
#define YMAX 1.125 /* y interval for 9/16 aspect ratio */
@ -65,9 +65,9 @@
// #define LAMBDA 3.75738973 /* sin(36°)/sin(9°) for 5-star shape with 90° angles */
// #define LAMBDA -1.73205080756888 /* -sqrt(3) for Reuleaux triangle */
// #define LAMBDA 1.73205080756888 /* sqrt(3) for triangle tiling plane */
#define MU 0.9 /* second parameter controlling shape of billiard */
#define MU 1.0 /* second parameter controlling shape of billiard */
#define FOCI 1 /* set to 1 to draw focal points of ellipse */
#define NPOLY 4 /* number of sides of polygon */
#define NPOLY 6 /* number of sides of polygon */
#define APOLY 0.0 /* angle by which to turn polygon, in units of Pi/2 */
#define DRAW_BILLIARD 1 /* set to 1 to draw billiard */
#define DRAW_CONSTRUCTION_LINES 1 /* set to 1 to draw additional construction lines for billiard */
@ -78,10 +78,10 @@
#define NPART 10000 /* number of particles */
#define NPARTMAX 100000 /* maximal number of particles after resampling */
#define NSTEPS 4200 /* number of frames of movie */
#define TIME 100 /* time between movie frames, for fluidity of real-time simulation */
#define NSTEPS 5000 /* number of frames of movie */
#define TIME 150 /* time between movie frames, for fluidity of real-time simulation */
#define DPHI 0.0001 /* integration step */
#define NVID 50 /* number of iterations between images displayed on screen */
#define NVID 75 /* number of iterations between images displayed on screen */
/* Decreasing TIME accelerates the animation and the movie */
/* For constant speed of movie, TIME*DPHI should be kept constant */
@ -99,12 +99,14 @@
/* color and other graphical parameters */
#define NCOLORS 12 /* number of colors */
#define COLORSHIFT 0 /* hue of initial color */
#define COLOR_PALETTE 1 /* Color palette, see list in global_pdes.c */
#define NCOLORS 6 /* number of colors */
#define COLORSHIFT 3 /* hue of initial color */
#define RAINBOW_COLOR 0 /* set to 1 to use different colors for all particles */
#define NSEG 100 /* number of segments of boundary */
#define BILLIARD_WIDTH 4 /* width of billiard */
#define FRONT_WIDTH 3 /* width of wave front */
#define FRONT_WIDTH 4 /* width of wave front */
#define BLACK 1 /* set to 1 for black background */
#define COLOR_OUTSIDE 0 /* set to 1 for colored outside */

View File

@ -36,6 +36,7 @@ double x_shooter = -0.2, y_shooter = -0.6, x_target = 0.4, y_target = 0.7;
#define D_CIRCLES 20 /* several circles */
#define D_CIRCLES_IN_RECT 21 /* several circles inside a rectangle */
#define D_CIRCLES_IN_GENUSN 22 /* several circles in polygon with identified opposite sides */
#define D_CIRCLES_IN_TORUS 23 /* several circles in a rectangle with periodic boundary conditions */
#define C_FOUR_CIRCLES 0 /* four circles almost touching each other */
#define C_SQUARE 1 /* square grid of circles */
@ -49,4 +50,17 @@ double x_shooter = -0.2, y_shooter = -0.6, x_target = 0.4, y_target = 0.7;
#define C_LASER 11 /* laser fight in a room of mirrors */
#define C_LASER_GENUSN 12 /* laser fight in a translation surface */
#define C_LASER_GENUSN 12 /* laser fight in a translation surface */
/* Color palettes */
#define COL_JET 0 /* JET color palette */
#define COL_HSLUV 1 /* HSLUV color palette (perceptually uniform) */
#define COL_TURBO 10 /* TURBO color palette (by Anton Mikhailov) */
#define COL_VIRIDIS 11 /* Viridis color palette */
#define COL_MAGMA 12 /* Magma color palette */
#define COL_INFERNO 13 /* Inferno color palette */
#define COL_PLASMA 14 /* Plasma color palette */

View File

@ -1,5 +1,8 @@
/* Global variables and parameters for wave_billiard, heat and schrodinger */
// #include "hsluv.c"
/* Basic math */
#define PI 3.141592654
@ -33,13 +36,17 @@
#define D_TWO_PARABOLAS 19 /* two facing parabolic antennas */
#define D_CIRCLES 20 /* several circles */
#define D_CIRCLES_IN_RECT 201 /* several circles in a rectangle */
#define D_FOUR_PARABOLAS 31 /* four parabolas with axes in NSEW directions */
#define D_POLY_PARABOLAS 32 /* polygon with parabolic sides */
#define D_PENROSE 33 /* Penrose illumination problem */
#define D_PENROSE 33 /* Penrose unilluminable room */
#define D_HYPERBOLA 34 /* one branch of hyperbola */
#define D_TOKARSKY 35 /* Tokarsky unilluminable room */
#define NMAXCIRCLES 1000 /* total number of circles (must be at least NCX*NCY for square grid) */
#define D_ISOSPECTRAL 37 /* isospectral billiards */
#define NMAXCIRCLES 600 /* total number of circles (must be at least NCX*NCY for square grid) */
#define C_SQUARE 0 /* square grid of circles */
#define C_HEX 1 /* hexagonal/triangular grid of circles */
@ -48,7 +55,7 @@
#define C_RAND_POISSON 4 /* random Poisson point process */
#define C_CLOAK 5 /* invisibility cloak */
#define C_CLOAK_A 6 /* first optimized invisibility cloak */
#define C_LASER 7 /* laser fight in a room of mirrors */
#define C_POISSON_DISC 8 /* Poisson disc sampling */
#define C_GOLDEN_MEAN 10 /* pattern based on vertical shifts by golden mean */
@ -102,6 +109,18 @@
#define C_LUM 0 /* color scheme modifies luminosity (with slow drift of hue) */
#define C_HUE 1 /* color scheme modifies hue */
#define C_PHASE 2 /* color scheme shows phase */
#define C_ONEDIM 3 /* use preset 1d color scheme (for Turbo, Viridis, Magma, Inferno, Plasma) */
/* Color palettes */
#define COL_JET 0 /* JET color palette */
#define COL_HSLUV 1 /* HSLUV color palette (perceptually uniform) */
#define COL_TURBO 10 /* TURBO color palette (by Anton Mikhailov) */
#define COL_VIRIDIS 11 /* Viridis color palette */
#define COL_MAGMA 12 /* Magma color palette */
#define COL_INFERNO 13 /* Inferno color palette */
#define COL_PLASMA 14 /* Plasma color palette */
double circlex[NMAXCIRCLES], circley[NMAXCIRCLES], circlerad[NMAXCIRCLES]; /* position and radius of circular scatterers */

14
heat.c
View File

@ -80,6 +80,17 @@
#define NGRIDX 15 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard in sub_wave.c */
@ -153,11 +164,10 @@
// #define HUEAMP -130.0 /* amplitude of variation of hue for color scheme C_HUE */
#include "hsluv.c"
#include "global_pdes.c"
#include "sub_wave.c"
double courant2; /* Courant parameter squared */
double dx2; /* spatial step size squared */
double intstep; /* integration step */

View File

@ -49,8 +49,10 @@
#define WINWIDTH 1280 /* window width */
#define WINHEIGHT 720 /* window height */
#define NX 1280 /* number of grid points on x axis */
#define NY 720 /* number of grid points on y axis */
#define NX 640 /* number of grid points on x axis */
#define NY 360 /* number of grid points on y axis */
// #define NX 1280 /* number of grid points on x axis */
// #define NY 720 /* number of grid points on y axis */
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
@ -63,6 +65,7 @@
#define B_DOMAIN 20 /* choice of domain shape, see list in global_pdes.c */
// #define CIRCLE_PATTERN 1 /* pattern of circles, see list in global_pdes.c */
#define CIRCLE_PATTERN 8 /* pattern of circles, see list in global_pdes.c */
#define P_PERCOL 0.25 /* probability of having a circle in C_RAND_PERCOL arrangement */
@ -80,6 +83,17 @@
#define NGRIDX 15 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard below */
@ -90,18 +104,24 @@
#define OSCILLATE_TOPBOT 1 /* set to 1 to enforce a planar wave on top and bottom boundary */
#define X_SHIFT -0.9 /* x range on which to apply OSCILLATE_TOPBOT */
#define OMEGA 0.002 /* frequency of periodic excitation */
#define K_BC 3.0 /* spatial period of periodic excitation in y direction */
#define KX_BC 30.0 /* spatial period of periodic excitation in x direction */
#define KY_BC 10.0 /* spatial period of periodic excitation in y direction */
#define OMEGA 0.00133333333 /* frequency of periodic excitation */
#define K_BC 3.0 /* spatial period of periodic excitation in y direction */
#define KX_BC 10.0 /* spatial period of periodic excitation in x direction */
#define KY_BC 3.3333 /* spatial period of periodic excitation in y direction */
// #define KX_BC 20.0 /* spatial period of periodic excitation in x direction */
// #define KY_BC 6.66666 /* spatial period of periodic excitation in y direction */
// #define OMEGA 0.002 /* frequency of periodic excitation */
// #define K_BC 3.0 /* spatial period of periodic excitation in y direction */
// #define KX_BC 30.0 /* spatial period of periodic excitation in x direction */
// #define KY_BC 10.0 /* spatial period of periodic excitation in y direction */
#define AMPLITUDE 1.0 /* amplitude of periodic excitation */
#define COURANT 0.02 /* Courant number */
#define COURANTB 0.01 /* Courant number in medium B */
#define COURANTB 0.015 /* Courant number in medium B */
// #define COURANTB 0.00666 /* Courant number in medium B */
#define GAMMA 2.0e-6 /* damping factor in wave equation */
#define GAMMAB 2.5e-4 /* damping factor in wave equation */
// #define GAMMAB 5.0e-4 /* damping factor in wave equation */
// #define GAMMAB 1.0e-4 /* damping factor in wave equation */
#define GAMMA 3.0e-6 /* damping factor in wave equation */
#define GAMMAB 5.0e-4 /* damping factor in wave equation */
// #define GAMMA 2.0e-6 /* damping factor in wave equation */
// #define GAMMAB 2.5e-4 /* damping factor in wave equation */
#define GAMMA_SIDES 1.0e-4 /* damping factor on boundary */
#define GAMMA_TOPBOT 1.0e-6 /* damping factor on boundary */
#define KAPPA 0.0 /* "elasticity" term enforcing oscillations */
@ -119,8 +139,8 @@
/* Parameters for length and speed of simulation */
// #define NSTEPS 1000 /* number of frames of movie */
#define NSTEPS 4500 /* number of frames of movie */
#define NSTEPS 1000 /* number of frames of movie */
// #define NSTEPS 5500 /* number of frames of movie */
#define NVID 60 /* number of iterations between images displayed on screen */
#define NSEG 100 /* number of segments of boundary */
#define INITIAL_TIME 100 /* time after which to start saving frames */
@ -167,42 +187,40 @@
#define MANGROVE_HUE_MIN 180.0 /* color of original mangrove */
#define MANGROVE_HUE_MAX -50.0 /* color of saturated mangrove */
// #define MANGROVE_EMAX 5.0e-3 /* max energy for mangrove to survive */
#define MANGROVE_EMAX 1.1e-3 /* max energy for mangrove to survive */
#define MANGROVE_EMAX 1.5e-3 /* max energy for mangrove to survive */
#define RANDOM_RADIUS 1 /* set to 1 for random circle radius */
#define ERODE_MANGROVES 0 /* set to 1 for mangroves to be eroded */
#define ERODE_MANGROVES 1 /* set to 1 for mangroves to be eroded */
#define RECOVER_MANGROVES 1 /* set to 1 to allow mangroves to recover */
#define MOVE_MANGROVES 1 /* set to 1 for mobile mangroves */
#define DETACH_MANGROVES 1 /* set to 1 for mangroves to be able to detach */
#define INERTIA 1 /* set to 1 for taking inertia into account */
#define REPELL_MANGROVES 1 /* set to 1 for mangroves to repell each other */
#define DT_MANGROVE 0.1 /* time step for mangrove displacement */
#define KSPRING 0.25 /* spring constant of mangroves */
#define KWAVE 2.0 /* constant in force due to wave gradient */
#define KSPRING 0.05 /* spring constant of mangroves */
#define KWAVE 4.0 /* constant in force due to wave gradient */
#define KREPEL 5.0 /* constant in repelling force between mangroves */
#define REPEL_RADIUS 1.1 /* radius in which repelling force acts (in units of mangrove radius) */
#define DXMAX 0.02 /* max displacement of mangrove in one time step */
#define L_DETACH 0.2 /* spring length beyond which mangroves detach */
#define DAMP_MANGROVE 0.2 /* damping coefficient of mangroves */
#define L_DETACH 0.25 /* spring length beyond which mangroves detach */
#define DAMP_MANGROVE 0.1 /* damping coefficient of mangroves */
#define MANGROVE_MASS 1.5 /* mass of mangrove of radius MU */
#define HASHX 25 /* size of hashgrid in x direction */
#define HASHY 15 /* size of hashgrid in y direction */
#define HASHMAX 10 /* maximal number of mangroves per hashgrid cell */
#define HASHGRID_PADDING 0.1 /* padding of hashgrid outside simulation window */
/* For debugging purposes only */
#define FLOOR 1 /* set to 1 to limit wave amplitude to VMAX */
#define VMAX 10.0 /* max value of wave amplitude */
#include "hsluv.c"
#include "global_pdes.c"
#include "sub_wave.c"
#include "wave_common.c"
double courant2, courantb2; /* Courant parameters squared */
double circle_energy[NMAXCIRCLES]; /* energy dissipated by the circles */
double circley_wrapped[NMAXCIRCLES]; /* position of circle centers wrapped vertically */
double anchor_x[NMAXCIRCLES]; /* points moving circles are attached to */
double anchor_y[NMAXCIRCLES]; /* points moving circles are attached to */
double vx[NMAXCIRCLES]; /* x velocity of circles */
double vy[NMAXCIRCLES]; /* y velocity of circles */
double circlerad_initial[NMAXCIRCLES]; /* initial circle radii */
double mass_inverse[NMAXCIRCLES]; /* inverse of mangrove mass */
short int circle_attached[NMAXCIRCLES]; /* has value 1 if the circle is attached to its anchor */
/*********************/
/* animation part */
@ -411,15 +429,109 @@ void evolve_wave(double *phi[NX], double *psi[NX], double *phi_tmp[NX], double *
evolve_wave_half(phi_tmp, psi_tmp, phi, psi, xy_in);
}
void hash_xy_to_ij(double x, double y, int ij[2])
{
static int first = 1;
static double lx, ly;
int i, j;
if (first)
{
lx = XMAX - XMIN + 2.0*HASHGRID_PADDING;
ly = YMAX - YMIN + 2.0*HASHGRID_PADDING;
first = 0;
}
i = (int)((double)HASHX*(x - XMIN + HASHGRID_PADDING)/lx);
j = (int)((double)HASHY*(y - YMIN + HASHGRID_PADDING)/ly);
if (i<0) i = 0;
if (i>=HASHX) i = HASHX-1;
if (j<0) j = 0;
if (j>=HASHY) j = HASHY-1;
ij[0] = i;
ij[1] = j;
// printf("Mapped (%.3f,%.3f) to (%i, %i)\n", x, y, ij[0], ij[1]);
}
void compute_repelling_force(int i, int j, double force[2])
/* compute repelling force of mangrove j on mangrove i */
{
double x1, y1, x2, y2, distance, r, f;
x1 = circlex[i];
y1 = circley[i];
x2 = circlex[j];
y2 = circley[j];
distance = module2(x2 - x1, y2 - y1);
r = circlerad[i] + circlerad[j];
if (r <= 0.0) r = 0.001*MU;
f = KREPEL/(0.001 + distance*distance);
if ((distance > 0.0)&&(distance < REPEL_RADIUS*r))
{
force[0] = f*(x1 - x2)/distance;
force[1] = f*(y1 - y2)/distance;
}
else
{
force[0] = 0.0;
force[1] = 0.0;
}
}
void update_hashgrid(int* mangrove_hashx, int* mangrove_hashy, int* hashgrid_number, int* hashgrid_mangroves)
{
int i, j, k, n, m, ij[2], max = 0;
printf("Updating hashgrid_number\n");
for (i=0; i<HASHX*HASHY; i++) hashgrid_number[i] = 0;
printf("Updated hashgrid_number\n");
/* place each mangrove in hash grid */
for (k=1; k<ncircles; k++)
// if (circleactive[k])
{
// printf("placing circle %i\t", k);
hash_xy_to_ij(circlex[k], circley[k], ij);
i = ij[0]; j = ij[1];
// printf("ij = (%i, %i)\t", i, j);
n = hashgrid_number[i*HASHY + j];
m = i*HASHY*HASHMAX + j*HASHMAX + n;
// printf("n = %i, m = %i\n", n, m);
if (m < HASHX*HASHY*HASHMAX) hashgrid_mangroves[m] = k;
else printf("Too many mangroves in hash cell, try increasing HASHMAX\n");
hashgrid_number[i*HASHY + j]++;
mangrove_hashx[k] = i;
mangrove_hashy[k] = j;
if (n > max) max = n;
// printf("Placed mangrove %i at (%i,%i) in hashgrid\n", k, ij[0], ij[1]);
// printf("%i mangroves at (%i,%i)\n", hashgrid_number[ij[0]][ij[1]], ij[0], ij[1]);
}
printf("Maximal number of mangroves per hash cell: %i\n", max);
}
void animation()
{
double time, scale, diss, rgb[3], hue, y, dissip, ej, gradient[2], dx, dy, dt, xleft, xright, length;
double time, scale, diss, rgb[3], hue, y, dissip, ej, gradient[2], dx, dy, dt, xleft, xright,
length, fx, fy, force[2];
double *phi[NX], *psi[NX], *phi_tmp[NX], *psi_tmp[NX];
short int *xy_in[NX], redraw = 0;
int i, j, s, ij[2];
int i, j, k, n, s, ij[2], i0, iplus, iminus, j0, jplus, jminus, p, q;
static int imin, imax;
static short int first = 1;
double *circleenergy, *circley_wrapped, *anchor_x, *anchor_y, *vx, *vy, *circlerad_initial, *mass_inverse;
short int *circle_attached;
int *mangrove_hashx, *mangrove_hashy, *hashgrid_number, *hashgrid_mangroves;
/* Since NX and NY are big, it seemed wiser to use some memory allocation here */
for (i=0; i<NX; i++)
@ -431,6 +543,21 @@ void animation()
xy_in[i] = (short int *)malloc(NY*sizeof(short int));
}
circleenergy = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* energy dissipated by the circles */
circley_wrapped = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* position of circle centers wrapped vertically */
anchor_x = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* points moving circles are attached to */
anchor_y = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* points moving circles are attached to */
vx = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* x velocity of circles */
vy = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* y velocity of circles */
circlerad_initial = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* initial circle radii */
mass_inverse = (double *)malloc(NMAXCIRCLES*sizeof(double)); /* inverse of mangrove mass */
circle_attached = (short int *)malloc(NMAXCIRCLES*sizeof(short int)); /* has value 1 if the circle is attached to its anchor */
mangrove_hashx = (int *)malloc(NMAXCIRCLES*sizeof(int)); /* hash grid positions of mangroves */
mangrove_hashy = (int *)malloc(NMAXCIRCLES*sizeof(int)); /* hash grid positions of mangroves */
hashgrid_number = (int *)malloc(HASHX*HASHY*sizeof(int)); /* total number of mangroves in each hash grid cell */
hashgrid_mangroves = (int *)malloc(HASHX*HASHY*HASHMAX*sizeof(int)); /* numbers of mangoves in each hash grid cell */
/* initialise positions and radii of circles */
if (B_DOMAIN == D_CIRCLES) init_circle_config();
@ -455,13 +582,14 @@ void animation()
/* initialise mangroves */
for (i=0; i < ncircles; i++)
{
circle_energy[i] = 0.0;
circleenergy[i] = 0.0;
y = circley[i];
if (y >= YMAX) y -= circlerad[i];
if (y <= YMIN) y += circlerad[i];
// if (y >= YMAX) y -= (YMAX - YMIN);
// if (y <= YMIN) y += (YMAX - YMIN);
circley_wrapped[i] = y;
// circleactive[i] = 1;
if (RANDOM_RADIUS) circlerad[i] = circlerad[i]*(0.75 + 0.5*((double)rand()/RAND_MAX));
@ -483,6 +611,9 @@ void animation()
}
}
/* initialise hash table for interacting mangroves */
if (REPELL_MANGROVES) update_hashgrid(mangrove_hashx, mangrove_hashy, hashgrid_number, hashgrid_mangroves);
if (first) /* compute box limits where circles are reset */
{
/* find leftmost and rightmost circle */
@ -515,7 +646,7 @@ void animation()
for (i=0; i<=INITIAL_TIME + NSTEPS; i++)
{
//printf("%d\n",i);
printf("Computing frame %d\n",i);
/* compute the variance of the field to adjust color scheme */
/* the color depends on the field divided by sqrt(1 + variance) */
if (SCALE)
@ -525,83 +656,24 @@ void animation()
}
else scale = 1.0;
printf("Drawing wave\n");
draw_wave(phi, psi, xy_in, scale, i, PLOT);
printf("Evolving wave\n");
for (j=0; j<NVID; j++)
{
// printf("%i ", j);
evolve_wave(phi, psi, phi_tmp, psi_tmp, xy_in);
// if (i % 10 == 9) oscillate_linear_wave(0.2*scale, 0.15*(double)(i*NVID + j), -1.5, YMIN, -1.5, YMAX, phi, psi);
}
/* compute energy dissipated in obstacles */
if (ERODE_MANGROVES) for (j=0; j<ncircles; j++)
{
dissip = compute_dissipation(phi, psi, xy_in, circlex[j], circley_wrapped[j]);
/* make sure the dissipation does not grow too fast because of round-off/blow-up */
if (dissip > 0.1*MANGROVE_EMAX)
{
dissip = 0.1*MANGROVE_EMAX;
printf("Flooring dissipation!\n");
}
if (circleactive[j])
{
circle_energy[j] += dissip;
ej = circle_energy[j];
if (ej <= MANGROVE_EMAX)
{
if (ej > 0.0)
{
hue = MANGROVE_HUE_MIN + (MANGROVE_HUE_MAX - MANGROVE_HUE_MIN)*ej/MANGROVE_EMAX;
if (hue < 0.0) hue += 360.0;
}
else hue = MANGROVE_HUE_MIN;
hsl_to_rgb(hue, 0.9, 0.5, rgb);
if (j%NGRIDY == 0) printf("Circle %i, energy %.5lg, hue %.5lg\n", j, ej, hue);
draw_colored_circle(circlex[j], circley[j], circlerad[j], NSEG, rgb);
/* shrink mangrove */
if (ej > 0.0)
{
// circlerad[j] -= MU*ej*ej/(MANGROVE_EMAX*MANGROVE_EMAX);
// if (circlerad[j] < 0.0) circlerad[j] = 0.0;
circlerad[j] = circlerad_initial[j]*(1.0 - ej*ej/(MANGROVE_EMAX*MANGROVE_EMAX));
redraw = 1;
}
else circlerad[j] = circlerad_initial[j];
}
else /* remove mangrove */
{
circleactive[j] = 0;
/* reinitialize table xy_in */
redraw = 1;
}
}
else /* allow disabled mangroves to recover */
{
circle_energy[j] -= 0.15*dissip;
// circlerad[j] += 0.005*MU;
// if (circlerad[j] > MU) circlerad[j] = MU;
// if ((circle_energy[j] < 0.0)&&(circlerad[j] > 0.0))
if (circle_energy[j] < 0.0)
{
circleactive[j] = 1;
// circlerad[j] = circlerad[j]*(0.75 + 0.5*((double)rand()/RAND_MAX));
circlerad[j] = circlerad_initial[j];
circle_energy[j] = -MANGROVE_EMAX;
/* reinitialize table xy_in */
redraw = 1;
}
}
// printf("Circle %i, energy %.5lg\n", j, circle_energy[j]);
}
/* move mangroves */
if (MOVE_MANGROVES) for (j=0; j<ncircles; j++) if (circleactive[j])
{
compute_gradient(phi, psi, circlex[j], circley_wrapped[j], gradient);
// printf("gradient = (%.3lg, %.3lg)\t", gradient[0], gradient[1]);
// if (j%NGRIDY == 0) printf("gradient (%.3lg, %.3lg)\n", gradient[0], gradient[1]);
// if (j%NGRIDY == 0) printf("circle %i (%.3lg, %.3lg) -> ", j, circlex[j], circley[j]);
@ -617,11 +689,41 @@ void animation()
dy += DT_MANGROVE*(-KSPRING*(circley_wrapped[j] - anchor_y[j]));
}
/* compute repelling force from other mangroves */
if (REPELL_MANGROVES)
{
/* determine neighboring grid points */
i0 = mangrove_hashx[j];
iminus = i0 - 1; if (iminus < 0) iminus = 0;
iplus = i0 + 1; if (iplus >= HASHX) iplus = HASHX-1;
j0 = mangrove_hashy[j];
jminus = j0 - 1; if (jminus < 0) jminus = 0;
jplus = j0 + 1; if (jplus >= HASHY) jplus = HASHY-1;
fx = 0.0;
fy = 0.0;
for (p=iminus; p<= iplus; p++)
for (q=jminus; q<= jplus; q++)
for (k=0; k<hashgrid_number[p*HASHY+q]; k++)
if (circleactive[hashgrid_mangroves[p*HASHY*HASHMAX + q*HASHMAX + k]])
{
compute_repelling_force(j, hashgrid_mangroves[p*HASHY*HASHMAX + q*HASHMAX + k], force);
fx += force[0];
fy += force[1];
}
// if (fx*fx + fy*fy > 0.001) printf("Force on mangrove %i: (%.3f, %.3f)\n", j, fx, fy);
dx += DT_MANGROVE*fx;
dy += DT_MANGROVE*fy;
}
/* detach mangrove if spring is too long */
if (DETACH_MANGROVES)
{
length = module2(circlex[j] - anchor_x[j], circley_wrapped[j] - anchor_y[j]);
if (j%NGRIDY == 0) printf("spring length %.i: %.3lg\n", j, length);
// if (j%NGRIDY == 0) printf("spring length %.i: %.3lg\n", j, length);
// if (length > L_DETACH) circle_attached[j] = 0;
if (length*mass_inverse[j] > L_DETACH) circle_attached[j] = 0;
}
@ -638,9 +740,9 @@ void animation()
circlex[j] += vx[j]*DT_MANGROVE;
circley[j] += vy[j]*DT_MANGROVE;
circley_wrapped[j] += vy[j]*DT_MANGROVE;
if (j%NGRIDY == 0)
printf("circle %.i: (dx,dy) = (%.3lg,%.3lg), (vx,vy) = (%.3lg,%.3lg)\n",
j, circlex[j]-anchor_x[j], circley[j]-anchor_y[j], vx[j], vy[j]);
// if (j%NGRIDY == 0)
// printf("circle %.i: (dx,dy) = (%.3lg,%.3lg), (vx,vy) = (%.3lg,%.3lg)\n",
// j, circlex[j]-anchor_x[j], circley[j]-anchor_y[j], vx[j], vy[j]);
}
else
{
@ -655,10 +757,148 @@ void animation()
if (circley_wrapped[j] >= YMAX) circley_wrapped[j] = YMAX;
// if (j%NGRIDY == 0) printf("(%.3lg, %.3lg)\n", circlex[j], circley[j]);
redraw = 1;
}
/* test for debugging */
if (1) for (j=0; j<ncircles; j++)
{
dissip = compute_dissipation(phi, psi, xy_in, circlex[j], circley_wrapped[j]);
/* make sure the dissipation does not grow too fast because of round-off/blow-up */
if (dissip > 0.1*MANGROVE_EMAX)
{
dissip = 0.1*MANGROVE_EMAX;
printf("Flooring dissipation!\n");
}
if (circleactive[j])
{
circleenergy[j] += dissip;
ej = circleenergy[j];
// printf("ej = %.3f\n", ej);
if (ej <= MANGROVE_EMAX)
{
if (ej > 0.0)
{
hue = MANGROVE_HUE_MIN + (MANGROVE_HUE_MAX - MANGROVE_HUE_MIN)*ej/MANGROVE_EMAX;
if (hue < 0.0) hue += 360.0;
}
else hue = MANGROVE_HUE_MIN;
hsl_to_rgb(hue, 0.9, 0.5, rgb);
// if (j%NGRIDY == 0) printf("Circle %i, energy %.5lg, hue %.5lg\n", j, ej, hue);
draw_colored_circle(circlex[j], circley[j], circlerad[j], NSEG, rgb);
/* shrink mangrove */
if ((ERODE_MANGROVES)&&(ej > 0.0))
{
circlerad[j] = circlerad_initial[j]*(1.0 - ej*ej/(MANGROVE_EMAX*MANGROVE_EMAX));
redraw = 1;
}
else circlerad[j] = circlerad_initial[j];
}
else /* remove mangrove */
{
circleactive[j] = 0;
/* reinitialize table xy_in */
redraw = 1;
}
}
else if (RECOVER_MANGROVES) /* allow disabled mangroves to recover */
{
circleenergy[j] -= 0.15*dissip;
printf("Circle %i energy %.3lg\n", j, circleenergy[j]);
if (circleenergy[j] < 0.0)
{
printf("Reactivating circle %i?\n", j);
/* THE PROBLEM occurs when circleactive[0] is set to 1 again */
if (j>0) circleactive[j] = 1;
circlerad[j] = circlerad_initial[j];
circleenergy[j] = -MANGROVE_EMAX;
/* reinitialize table xy_in */
redraw = 1;
}
}
}
/* compute energy dissipated in obstacles */
/* if (ERODE_MANGROVES) for (j=0; j<ncircles; j++)
{
// printf("j = %i\t", j);
dissip = compute_dissipation(phi, psi, xy_in, circlex[j], circley_wrapped[j]);
printf("dissip = %.3f\t", dissip);
/* make sure the dissipation does not grow too fast because of round-off/blow-up */
// if (dissip > 0.1*MANGROVE_EMAX)
// {
// dissip = 0.1*MANGROVE_EMAX;
// printf("Flooring dissipation!\n");
// }
//
// if (circleactive[j])
// {
// circleenergy[j] += dissip;
// ej = circleenergy[j];
// printf("ej = %.3f\n", ej);
// if (ej <= MANGROVE_EMAX)
// {
// if (ej > 0.0)
// {
// hue = MANGROVE_HUE_MIN + (MANGROVE_HUE_MAX - MANGROVE_HUE_MIN)*ej/MANGROVE_EMAX;
// if (hue < 0.0) hue += 360.0;
// }
// else hue = MANGROVE_HUE_MIN;
// hsl_to_rgb(hue, 0.9, 0.5, rgb);
// if (j%NGRIDY == 0) printf("Circle %i, energy %.5lg, hue %.5lg\n", j, ej, hue);
// draw_colored_circle(circlex[j], circley[j], circlerad[j], NSEG, rgb);
//
// /* shrink mangrove */
// if (ej > 0.0)
// {
// circlerad[j] -= MU*ej*ej/(MANGROVE_EMAX*MANGROVE_EMAX);
// if (circlerad[j] < 0.0) circlerad[j] = 0.0;
// circlerad[j] = circlerad_initial[j]*(1.0 - ej*ej/(MANGROVE_EMAX*MANGROVE_EMAX));
// redraw = 1;
// }
// else circlerad[j] = circlerad_initial[j];
// }
// else /* remove mangrove */
// {
// circleactive[j] = 0;
/* reinitialize table xy_in */
// redraw = 1;
// }
// }
// else /* allow disabled mangroves to recover */
// {
// circleenergy[j] -= 0.15*dissip;
// printf("ej = %.3f\n", circleenergy[j]);
// circlerad[j] += 0.005*MU;
// if (circlerad[j] > MU) circlerad[j] = MU;
// if ((circleenergy[j] < 0.0)&&(circlerad[j] > 0.0))
// if (circleenergy[j] < 0.0)
// {
// circleactive[j] = 1;
// circlerad[j] = circlerad[j]*(0.75 + 0.5*((double)rand()/RAND_MAX));
// circlerad[j] = circlerad_initial[j];
// circleenergy[j] = -MANGROVE_EMAX;
/* reinitialize table xy_in */
// redraw = 1;
// }
// }
// printf("Circle %i, energy %.5lg\n", j, circleenergy[j]);
// }
printf("Updating hashgrid\n");
if (REPELL_MANGROVES) update_hashgrid(mangrove_hashx, mangrove_hashy, hashgrid_number, hashgrid_mangroves);
printf("Drawing billiard\n");
draw_billiard();
glutSwapBuffers();
@ -666,7 +906,7 @@ void animation()
if (redraw)
{
printf("Reinitializing xy_in\n");
init_xyin_xrange(xy_in, imin, NX-1);
init_xyin_xrange(xy_in, imin, NX);
// init_xyin_xrange(xy_in, imin, imax);
}
redraw = 0;
@ -701,6 +941,21 @@ void animation()
free(psi_tmp[i]);
free(xy_in[i]);
}
free(circleenergy);
free(circley_wrapped);
free(anchor_x);
free(anchor_y);
free(vx);
free(vy);
free(circlerad_initial);
free(mass_inverse);
free(circle_attached);
free(mangrove_hashx);
free(mangrove_hashy);
free(hashgrid_number);
free(hashgrid_mangroves);
}

View File

@ -32,13 +32,18 @@
#define MOVIE 0 /* set to 1 to generate movie */
#define WINWIDTH 1280 /* window width */
// #define WINWIDTH 1280 /* window width */
#define WINWIDTH 720 /* window width */
#define WINHEIGHT 720 /* window height */
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
#define YMIN -1.125
#define YMAX 1.125 /* y interval for 9/16 aspect ratio */
#define XMIN -1.4
#define XMAX 1.4 /* x interval */
#define YMIN -1.4
#define YMAX 1.4 /* y interval for 9/16 aspect ratio */
// #define XMIN -2.0
// #define XMAX 2.0 /* x interval */
// #define YMIN -1.125
// #define YMAX 1.125 /* y interval for 9/16 aspect ratio */
#define SCALING_FACTOR 1.0 /* scaling factor of drawing, needed for flower billiards, otherwise set to 1.0 */
@ -60,7 +65,7 @@
// #define LAMBDA 1.4 /* parameter controlling shape of domain */
// #define MU 0.2 /* second parameter controlling shape of billiard */
#define LAMBDA 1.5 /* parameter controlling shape of domain */
#define LAMBDA 1.3 /* parameter controlling shape of domain */
#define MU 0.3 /* second parameter controlling shape of billiard */
#define FOCI 1 /* set to 1 to draw focal points of ellipse */
#define NPOLY 4 /* number of sides of polygon */
@ -74,15 +79,16 @@
/* Simulation parameters */
#define NPART 10000 /* number of particles */
#define NPART 100 /* number of particles */
#define NPARTMAX 100000 /* maximal number of particles after resampling */
#define LMAX 0.01 /* minimal segment length triggering resampling */
#define DMIN 0.02 /* minimal distance to boundary for triggering resampling */
#define CYCLE 1 /* set to 1 for closed curve (start in all directions) */
#define SHOWTRAILS 0 /* set to 1 to keep trails of the particles */
#define SHOWTRAILS 1 /* set to 1 to keep trails of the particles */
#define TEST_ACTIVE 1 /* set to 1 to test whether particle is in billiard */
#define NSTEPS 3500 /* number of frames of movie */
#define TIME 1200 /* time between movie frames, for fluidity of real-time simulation */
#define NSTEPS 1300 /* number of frames of movie */
#define TIME 2500 /* time between movie frames, for fluidity of real-time simulation */
#define DPHI 0.00001 /* integration step */
#define NVID 150 /* number of iterations between images displayed on screen */
@ -94,12 +100,14 @@
/* Colors and other graphical parameters */
#define NCOLORS 16 /* number of colors */
#define COLOR_PALETTE 0 /* Color palette, see list in global_pdes.c */
#define NCOLORS 64 /* number of colors */
#define COLORSHIFT 0 /* hue of initial color */
#define RAINBOW_COLOR 0 /* set to 1 to use different colors for all particles */
#define RAINBOW_COLOR 1 /* set to 1 to use different colors for all particles */
#define FLOWER_COLOR 0 /* set to 1 to adapt initial colors to flower billiard (tracks vs core) */
#define NSEG 100 /* number of segments of boundary */
#define LENGTH 0.01 /* length of velocity vectors */
#define LENGTH 0.03 /* length of velocity vectors */
#define BILLIARD_WIDTH 2 /* width of billiard */
#define PARTICLE_WIDTH 2 /* width of particles */
#define FRONT_WIDTH 3 /* width of wave front */
@ -170,6 +178,31 @@ void init_drop_config(double x0, double y0, double angle1, double angle2, double
}
}
void init_partial_drop_config(double x0, double y0, double angle1, double angle2, int particle1, int particle2,
int col, double *configs[NPARTMAX], int color[NPARTMAX], int newcolor[NPARTMAX])
/* initialize configuration: drop at (x0,y0) for a range of particles */
{
int i;
double dalpha, alpha;
double conf[2], pos[2];
while (angle2 < angle1) angle2 += DPI;
if (particle2 - particle1 > 1) dalpha = (angle2 - angle1)/((double)(particle2 - particle1-1));
else dalpha = 0.0;
for (i=particle1; i<particle2; i++)
{
alpha = angle1 + dalpha*((double)i);
// printf("alpha=%.5lg\n", alpha);
pos[0] = x0;
pos[1] = y0;
vbilliard_xy(configs[i], alpha, pos);
color[i] = col;
newcolor[i] = col;
}
}
void init_sym_drop_config(double x0, double y0, double angle1, double angle2, double *configs[NPARTMAX])
/* initialize configuration with two symmetric partial drops */
{
@ -217,6 +250,71 @@ void init_line_config(double x0, double y0, double x1, double y1, double angle,
}
void draw_config_showtrails(int color[NPARTMAX], double *configs[NPARTMAX], int active[NPARTMAX])
/* draw the particles */
{
int i;
double x0, y0, x1, y1, x2, y2, cosphi, sinphi, rgb[3], len;
glutSwapBuffers();
if (PAINT_INT) paint_billiard_interior();
glLineWidth(PARTICLE_WIDTH);
glEnable(GL_LINE_SMOOTH);
for (i=0; i<nparticles; i++)
{
// if (configs[i][2]<0.0)
// {
// vbilliard(configs[i]);
// if (!RAINBOW_COLOR)
// {
// color[i]++;
// if (color[i] >= NCOLORS) color[i] -= NCOLORS;
// }
// }
configs[i][2] += DPHI;
cosphi = (configs[i][6] - configs[i][4])/configs[i][3];
sinphi = (configs[i][7] - configs[i][5])/configs[i][3];
len = configs[i][2] + LENGTH;
if (len > configs[i][3]) len = configs[i][3];
x0 = configs[i][4];
y0 = configs[i][5];
x1 = configs[i][4] + configs[i][2]*cosphi;
y1 = configs[i][5] + configs[i][2]*sinphi;
x2 = configs[i][4] + len*cosphi;
y2 = configs[i][5] + len*sinphi;
/* test whether particle does not escape billiard */
if ((TEST_ACTIVE)&&(active[i])) active[i] = xy_in_billiard(x1, y1);
if (active[i])
{
rgb_color_scheme(color[i], rgb);
glColor3f(rgb[0], rgb[1], rgb[2]);
glBegin(GL_LINE_STRIP);
glVertex2d(SCALING_FACTOR*x0, SCALING_FACTOR*y0);
glVertex2d(SCALING_FACTOR*x2, SCALING_FACTOR*y2);
glEnd ();
}
// if (configs[i][2] > configs[i][3] - DPHI)
// {
// glBegin(GL_LINE_STRIP);
// glVertex2d(SCALING_FACTOR*x0, SCALING_FACTOR*y0);
// glVertex2d(SCALING_FACTOR*configs[i][6], SCALING_FACTOR*configs[i][7]);
// glEnd ();
// }
}
if (DRAW_BILLIARD) draw_billiard();
}
void draw_config(int color[NPARTMAX], double *configs[NPARTMAX], int active[NPARTMAX])
/* draw the particles */
{
@ -332,7 +430,8 @@ void graph_movie(int time, int color[NPARTMAX], double *configs[NPARTMAX], int a
{
// printf("reflecting particle %i\n", i);
c = vbilliard(configs[i]);
if (c>=0) color[i]++;
// if (c>=0) color[i]++;
if ((!RAINBOW_COLOR)&&(c>=0)) color[i]++;
if (!RAINBOW_COLOR)
{
color[i]++;
@ -354,7 +453,7 @@ void graph_movie(int time, int color[NPARTMAX], double *configs[NPARTMAX], int a
void animation()
{
double time, dt, alpha, r;
double time, dt, alpha, r, rgb[3];
double *configs[NPARTMAX];
int i, j, resamp = 1, s, i1, i2;
int *color, *newcolor, *active;
@ -430,15 +529,27 @@ void animation()
}
sleep(SLEEP1);
/* initialize drops in different colors */
init_partial_drop_config(0.0, 0.0, 0.0, DPI, 0, 2*NPART/5, 0, configs, color, newcolor);
init_partial_drop_config(0.0, 0.8, 0.0, DPI, 2*NPART/5, 4*NPART/5, 10, configs, color, newcolor);
init_partial_drop_config(1.2, 0.1, 0.0, DPI, 4*NPART/5, NPART, 36, configs, color, newcolor);
for (i=0; i<=NSTEPS; i++)
{
graph_movie(TIME, newcolor, configs, active);
draw_config(newcolor, configs, active);
if (SHOWTRAILS) draw_config_showtrails(newcolor, configs, active);
else draw_config(newcolor, configs, active);
// draw_config(newcolor, configs, active);
if (DRAW_BILLIARD) draw_billiard();
for (j=0; j<NPARTMAX; j++) color[j] = newcolor[j];
/* draw initial points */
draw_initial_condition_circle(0.0, 0.0, 0.02, 0);
draw_initial_condition_circle(0.0, 0.8, 0.02, 10);
draw_initial_condition_circle(1.2, 0.1, 0.02, 36);
if (MOVIE)
{

View File

@ -38,6 +38,7 @@
#define XMIN -4.0
#define XMAX 4.0 /* x interval */
#define YMIN -1.25
// #define YMID 1.25
#define YMAX 3.25 /* y interval for 9/16 aspect ratio */
// #define XMIN -2.0
// #define XMAX 2.0 /* x interval */
@ -51,20 +52,30 @@
/* Choice of the billiard table, see global_particles.c */
#define B_DOMAIN 21 /* choice of domain shape */
#define B_DOMAIN 23 /* choice of domain shape */
#define CIRCLE_PATTERN 6 /* pattern of circles */
// #define CIRCLE_PATTERN 21 /* pattern of circles */
#define ABSORBING_CIRCLES 0 /* set to 1 for circular scatterers to be absorbing */
#define NMAXCIRCLES 5000 /* total number of circles (must be at least NCX*NCY for square grid) */
#define NCX 40 /* number of circles in x direction */
#define NMAXCIRCLES 1000 /* total number of circles (must be at least NCX*NCY for square grid) */
#define NCX 44 /* number of circles in x direction */
#define NCY 10 /* number of circles in y direction */
#define NPOISSON 500 /* number of points for Poisson C_RAND_POISSON arrangement */
// #define NCX 50 /* number of circles in x direction */
// #define NCY 20 /* number of circles in y direction */
// #define NCX 52 /* number of circles in x direction */
// #define NCY 30 /* number of circles in y direction */
#define NPOISSON 350 /* number of points for Poisson C_RAND_POISSON arrangement */
#define NGOLDENSPIRAL 2000 /* max number of points for C_GOLDEN_SPIRAL arrandement */
#define LAMBDA 3.8 /* parameter controlling shape of domain */
#define LAMBDA 3.8105 /* parameter controlling shape of domain */
// #define MU 0.1 /* second parameter controlling shape of billiard */
// #define MU 0.085 /* second parameter controlling shape of billiard */
// #define MU 0.09 /* second parameter controlling shape of billiard */
#define MU 0.05 /* second parameter controlling shape of billiard */
// #define MU 0.034 /* second parameter controlling shape of billiard */
#define FOCI 1 /* set to 1 to draw focal points of ellipse */
#define NPOLY 4 /* number of sides of polygon */
#define APOLY 0.5 /* angle by which to turn polygon, in units of Pi/2 */
@ -85,9 +96,14 @@
#define SHOWTRAILS 0 /* set to 1 to keep trails of the particles */
#define TEST_ACTIVE 0 /* set to 1 to test whether particle is in billiard */
#define NSTEPS 7700 /* number of frames of movie */
#define NSTEPS 11700 /* number of frames of movie */
// #define NSTEPS 1000 /* number of frames of movie */
// #define TIME 1500 /* time between movie frames, for fluidity of real-time simulation */
#define TIME 4000 /* time between movie frames, for fluidity of real-time simulation */
// #define DPHI 0.0001 /* integration step */
// #define DPHI 0.00002 /* integration step */
#define DPHI 0.00007 /* integration step */
// #define DPHI 0.000035 /* integration step */
#define NVID 150 /* number of iterations between images displayed on screen */
/* Decreasing TIME accelerates the animation and the movie */
@ -98,8 +114,11 @@
/* Colors and other graphical parameters */
#define NCOLORS 32 /* number of colors */
#define COLORSHIFT 0 /* hue of initial color */
#define COLOR_PALETTE 1 /* Color palette, see list in global_pdes.c */
// #define NCOLORS 256 /* number of colors */
#define NCOLORS 48 /* number of colors */
#define COLORSHIFT 2 /* hue of initial color */
#define RAINBOW_COLOR 1 /* set to 1 to use different colors for all particles */
#define SINGLE_COLOR 1 /* set to 1 to make all particles a single color */
#define FLOWER_COLOR 0 /* set to 1 to adapt initial colors to flower billiard (tracks vs core) */
@ -108,6 +127,7 @@
#define BILLIARD_WIDTH 2 /* width of billiard */
#define PARTICLE_WIDTH 4 /* width of particles */
#define FRONT_WIDTH 3 /* width of wave front */
// #define COLOR_TRAJECTORY 0 /* hue for single color */
#define COLOR_TRAJECTORY 8 /* hue for single color */
#define BLACK 1 /* set to 1 for black background */
@ -118,7 +138,7 @@
#define ERASE_OUTSIDE 1 /* set to 1 to erase outside of rectangular billiard (beta) */
#define PAUSE 1000 /* number of frames after which to pause */
#define PAUSE 500 /* number of frames after which to pause */
#define PSLEEP 5 /* sleep time during pause */
#define SLEEP1 1 /* initial sleeping time */
#define SLEEP2 1000 /* final sleeping time */
@ -133,6 +153,7 @@
int ncol = 0, nobst = 0, nmaxpeg = 0;
int npath[NPATHBINS];
double max_free_path = 0.0;
/*********************/
/* animation part */
@ -404,6 +425,7 @@ void graph_movie(int time, int color[NPARTMAX], double *configs[NPARTMAX], int a
{
int i, j, k, c;
double rgb[3];
static double total_pathlength = 0.0;
for (j=0; j<time; j++)
{
@ -424,22 +446,44 @@ void graph_movie(int time, int color[NPARTMAX], double *configs[NPARTMAX], int a
glEnd ();
}
total_pathlength += configs[i][3];
c = vbilliard(configs[i]);
ncol++;
/* update number of collisions, not counting boundary for periodic b.c. */
if (B_DOMAIN != D_CIRCLES_IN_TORUS) ncol++;
else if (c >= 0) ncol++;
if ((c >= 0)&&(circlecolor[c] == 0)) nobst++;
circlecolor[c]++;
/* take care of circles doubled because of periodic boundary conditions */
if ((circleactive[c])&&(B_DOMAIN == D_CIRCLES_IN_TORUS)&&(partner_circle[c] != c)) circlecolor[partner_circle[c]]++;
newcircle[c] = 10;
/* update free path statistics */
k = (int)((double)NPATHBINS*configs[i][3]/PATHLMAX);
if (k < NPATHBINS) npath[k]++;
// if (circlecolor[c] > nmaxpeg) nmaxpeg = circlecolor[c];
// if (circlecolor[c] > NCOLORS) circlecolor[c] = 1;
// if (c>=0) color[i]++;
if (ncol > 1) /* disregard very first collision */
{
if (B_DOMAIN != D_CIRCLES_IN_TORUS)
{
k = (int)((double)NPATHBINS*configs[i][3]/PATHLMAX);
if (k < NPATHBINS) npath[k]++;
if (total_pathlength > max_free_path) max_free_path = total_pathlength;
total_pathlength = 0.0;
}
else /* case with periodic boundary conditions */
{
if (c >= 0) /* a circle is hit, update histogram */
{
// printf("total path length %.3lg\n", total_pathlength);
k = (int)((double)NPATHBINS*total_pathlength/PATHLMAX);
if (k < NPATHBINS) npath[k]++;
if (total_pathlength > max_free_path) max_free_path = total_pathlength;
total_pathlength = 0.0;
}
}
}
if (!RAINBOW_COLOR)
{
@ -514,8 +558,10 @@ void print_particle_numbers(double *configs[NPARTMAX])
void draw_statistics()
{
int i, n, colmax = 35, pegcollisions[70], nypegs = 70, meanpegs = 0, total_coll = 0, ymax = 0, meanbins = 0, total_bin = 0;
double x, y, yscale = 120.0, y0, dx, rgb[3], xshift;
int i, n, colmax = 55, pegcollisions[90], nypegs = 70, meanpegs = 0, meansquarepegs = 0, total_coll = 0, ymax = 0,
meanbins = 0, meansquarebins, total_bin = 0, stephits = 10, tickstephits = 1;
double x, y, yscale = 110.0, y0, dx, rgb[3], xshift, coll_mean, coll_stdv, path_mean, path_stdv, ebin, len_over_bin,
steppath = 0.5;
char message[50];
glLineWidth(1);
@ -525,10 +571,10 @@ void draw_statistics()
xshift = XMIN + 0.3;
rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 1.0;
/* histogramm of number of collisions per peg */
/* histogram of number of collisions per peg */
for (i=0; i<colmax; i++) pegcollisions[i] = 0;
for (i=0; i<ncircles; i++)
for (i=0; i<ncircles; i++) if ((circleactive[i])&&(!double_circle[i]))
{
n = circlecolor[i];
if (n < colmax) pegcollisions[n]++;
@ -537,6 +583,7 @@ void draw_statistics()
{
total_coll += pegcollisions[i];
meanpegs += i*pegcollisions[i];
meansquarepegs += i*i*pegcollisions[i];
}
for (i=1; i<colmax; i++)
@ -550,8 +597,8 @@ void draw_statistics()
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
/* histogramm */
for (i=1; i<colmax; i++)
/* histogram */
for (i=0; i<colmax; i++)
{
x = xshift + (double)i*dx;
y = y0 + (double)pegcollisions[i]*YMAX/yscale;
@ -574,7 +621,7 @@ void draw_statistics()
glEnd ();
}
for (i=1; i<colmax; i++)
for (i=tickstephits; i<colmax; i+=tickstephits)
{
glBegin(GL_LINE_STRIP);
glVertex2d(xshift + (double)i*dx, y0 - 0.025);
@ -582,10 +629,10 @@ void draw_statistics()
glEnd ();
}
for (i=10; i<colmax; i+=10)
for (i=stephits; i<nypegs - stephits; i+=stephits)
{
sprintf(message, "%4d", i);
write_text_fixedwidth(xshift + (double)i*dx - 0.12, y0 - 0.12, message);
write_text_fixedwidth(xshift + (double)i*dx - 0.15, y0 - 0.12, message);
}
for (i=10; i<nypegs; i+=10)
@ -594,20 +641,34 @@ void draw_statistics()
write_text_fixedwidth(xshift - 0.3, y0 - 0.025 + (double)i*YMAX/yscale, message);
}
coll_mean = (double)meanpegs/(double)total_coll;
coll_stdv = sqrt((double)meansquarepegs/(double)total_coll - coll_mean*coll_mean);
sprintf(message, "hits");
write_text_fixedwidth(xshift + (double)(colmax-3)*dx, y0 - 0.12, message);
sprintf(message, "pegs");
write_text_fixedwidth(xshift - 0.25, y0 - 0.025 + (double)(nypegs - 3)*YMAX/yscale, message);
sprintf(message, "Mean %.4lg", (double)meanpegs/(double)total_coll);
write_text(-1.0, YMAX - 0.3, message);
// sprintf(message, "Mean %.4lg", (double)meanpegs/(double)total_coll);
/* histogramm of path lengths */
sprintf(message, "Max hits/peg %d", nmaxpeg);
write_text(-1.5, YMAX - 0.3, message);
sprintf(message, "Mean hits/peg %.4lg", coll_mean);
write_text(-1.5, YMAX - 0.5, message);
sprintf(message, "Stdv hits/peg %.4lg", coll_stdv);
write_text(-1.5, YMAX - 0.7, message);
/* histogram of path lengths */
for (i=1; i<NPATHBINS; i++)
{
if (npath[i] > ymax) ymax = npath[i];
total_bin += npath[i];
meanbins += i*npath[i];
meansquarebins += i*i*npath[i];
}
yscale = 0.9*(YMAX-y0)*(double)ymax;
@ -620,13 +681,13 @@ void draw_statistics()
x = xshift + (double)i*dx;
y = y0 + (double)npath[i]*YMAX/yscale;
erase_rectangle(x, y0, x+dx, y, rgb);
if (y > y0) erase_rectangle(x, y0, x+dx, y, rgb);
}
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
/* histogramm */
for (i=1; i<NPATHBINS; i++)
/* histogram */
for (i=1; i<NPATHBINS; i++) if (npath[i] > 0)
{
x = xshift + (double)i*dx;
y = y0 + (double)npath[i]*YMAX/yscale;
@ -636,19 +697,23 @@ void draw_statistics()
glVertex2d(x+dx, y0);
glVertex2d(x, y0);
}
glVertex2d(xshift, y0);
glEnd ();
glBegin(GL_LINE_STRIP);
glVertex2d(xshift, YMAX - 0.1);
glVertex2d(xshift, y0);
glVertex2d(xshift + (double)NPATHBINS*dx, y0);
glEnd ();
for (x = 0.5; x < PATHLMAX; x+=0.5)
for (x = steppath; x < PATHLMAX; x+=steppath)
{
i = (int)(x*(double)NPATHBINS/PATHLMAX);
sprintf(message, "%.2f", x);
write_text_fixedwidth(xshift + (double)i*dx - 0.1, y0 - 0.12, message);
}
for (x = 0.1; x < PATHLMAX; x+=0.1)
for (x = steppath; x < PATHLMAX; x+=steppath)
{
i = (int)(x*(double)NPATHBINS/PATHLMAX);
glBegin(GL_LINE_STRIP);
@ -656,12 +721,24 @@ void draw_statistics()
glVertex2d(xshift + (double)i*dx, y0 + 0.025);
glEnd ();
}
ebin = (double)meanbins/(double)total_bin; /* mean bin */
len_over_bin = PATHLMAX/(double)NPATHBINS; /* conversion from bin to path length */
path_mean = ebin*len_over_bin; /* mean free path */
path_stdv = sqrt((double)meansquarebins/(double)total_bin - ebin*ebin)*len_over_bin;
sprintf(message, "free path");
write_text_fixedwidth(XMAX - 0.6, y0 - 0.12, message);
sprintf(message, "Mean free path %.4lg", (double)meanbins*PATHLMAX/(double)(total_bin*NPATHBINS));
sprintf(message, "Max free path %.4lg", max_free_path);
write_text(2.2, YMAX - 0.3, message);
sprintf(message, "Mean free path %.4lg", path_mean);
write_text(2.2, YMAX - 0.5, message);
sprintf(message, "Stdv free path %.4lg", path_stdv);
write_text(2.2, YMAX - 0.7, message);
}
@ -681,24 +758,38 @@ void animation(int circle_config)
configs[i] = (double *)malloc(8*sizeof(double));
/* init circle configuration if the domain is D_CIRCLES */
if ((B_DOMAIN == D_CIRCLES)||(B_DOMAIN == D_CIRCLES_IN_RECT)||(B_DOMAIN == D_CIRCLES_IN_GENUSN))
if ((B_DOMAIN == D_CIRCLES)||(B_DOMAIN == D_CIRCLES_IN_RECT)||(B_DOMAIN == D_CIRCLES_IN_GENUSN)
||(B_DOMAIN == D_CIRCLES_IN_TORUS))
init_circle_config_pinball(circle_config);
/* remove discs that are not in domain */
if ((B_DOMAIN == D_CIRCLES_IN_RECT)||(B_DOMAIN == D_CIRCLES_IN_GENUSN))
if ((B_DOMAIN == D_CIRCLES_IN_RECT)||(B_DOMAIN == D_CIRCLES_IN_GENUSN))
// ||(B_DOMAIN == D_CIRCLES_IN_TORUS))
for (i=0; i<ncircles; i++)
{
if (vabs(circley[i]) + circlerad[i] > 0.99) circleactive[i] = 0;
if (vabs(circlex[i]) + circlerad[i] > 0.99*LAMBDA) circleactive[i] = 0;
}
else if (B_DOMAIN == D_CIRCLES_IN_TORUS)
for (i=0; i<ncircles; i++)
{
if (vabs(circley[i]) - circlerad[i] > 1.0) circleactive[i] = 0;
if (vabs(circlex[i]) - circlerad[i] > LAMBDA) circleactive[i] = 0;
}
// for (i=0; i<ncircles; i++)
// printf("Circle %i at (%.2f, %.2f), double %i, partner %i\n", i, circlex[i], circley[i], double_circle[i], partner_circle[i]);
// if (vabs(circley[i]) > 1.0) circleactive[i] = 0;
/* initialize system by putting particles in a given point with a range of velocities */
r = cos(PI/(double)NPOLY)/cos(DPI/(double)NPOLY);
// init_drop_config(0.4, 0.0, PID, 0.5*PID, configs);
init_drop_config(0.0, 0.0, -0.45*PID, 0.45*PID, configs);
// init_line_config(-1.25, -0.5, -1.25, 0.5, 0.0, configs);
init_drop_config(0.5, 0.1, -0.5*PID, 0.5*PID, configs);
// init_drop_config(0.0, 0.0, -0.5*PID, 0.5*PID, configs);
// init_drop_config(0.5, 0.1, -0.5*PID, 0.5*PID, configs);
// init_drop_config(-1.4, 0.0, -0.5*PID, 0.5*PID, configs);
// init_drop_config(0.5, 0.5, -1.0, 1.0, configs);
// init_sym_drop_config(-1.0, 0.5, -PID, PID, configs);
@ -795,9 +886,9 @@ void animation(int circle_config)
for (j=0; j<ncircles; j++)
if (circlecolor[j] > nmaxpeg) nmaxpeg = circlecolor[j];
sprintf(message, "max hits per peg: %d", nmaxpeg);
glColor3f(1.0, 1.0, 1.0);
write_text(-0.6, YMIN + 0.08, message);
// sprintf(message, "max hits per peg: %d", nmaxpeg);
// glColor3f(1.0, 1.0, 1.0);
// write_text(-0.6, YMIN + 0.08, message);
// write_text(-0.3, YMIN + 0.04, message);
draw_statistics();
@ -849,8 +940,8 @@ void display(void)
}
animation(CIRCLE_PATTERN);
// animation(C_TRI);
// animation(C_GOLDEN_SPIRAL);
// animation(C_SQUARE);
// animation(C_HEX);

View File

@ -39,10 +39,12 @@
/* General geometrical parameters */
#define WINWIDTH 1280 /* window width */
// #define WINWIDTH 1280 /* window width */
#define WINWIDTH 720 /* window width */
#define WINHEIGHT 720 /* window height */
#define NX 1280 /* number of grid points on x axis */
// #define NX 1280 /* number of grid points on x axis */
#define NX 720 /* number of grid points on x axis */
#define NY 720 /* number of grid points on y axis */
// #define NX 640 /* number of grid points on x axis */
// #define NY 360 /* number of grid points on y axis */
@ -52,22 +54,24 @@
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
#define YMIN -1.125
#define YMAX 1.125 /* y interval for 9/16 aspect ratio */
#define YMIN -2.0
#define YMAX 2.0 /* y interval for 9/16 aspect ratio */
// #define YMIN -1.125
// #define YMAX 1.125 /* y interval for 9/16 aspect ratio */
#define JULIA_SCALE 1.0 /* scaling for Julia sets */
/* Choice of the billiard table, see list in global_pdes.c */
#define B_DOMAIN 9 /* choice of domain shape */
#define B_DOMAIN 19 /* choice of domain shape */
#define CIRCLE_PATTERN 0 /* pattern of circles, see list in global_pdes.c */
#define P_PERCOL 0.25 /* probability of having a circle in C_RAND_PERCOL arrangement */
#define NPOISSON 300 /* number of points for Poisson C_RAND_POISSON arrangement */
#define LAMBDA 0.3 /* parameter controlling the dimensions of domain */
#define MU 0.05 /* parameter controlling the dimensions of domain */
#define LAMBDA 0.0 /* parameter controlling the dimensions of domain */
#define MU 1.75 /* parameter controlling the dimensions of domain */
#define NPOLY 6 /* number of sides of polygon */
#define APOLY 1.0 /* angle by which to turn polygon, in units of Pi/2 */
#define MDEPTH 3 /* depth of computation of Menger gasket */
@ -78,13 +82,25 @@
#define NGRIDX 15 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard in sub_wave.c */
/* Physical patameters of wave equation */
// #define DT 0.00000005
#define DT 0.000000005
#define DT 0.00000001
// #define DT 0.000000005
// #define DT 0.000000005
#define HBAR 1.0
@ -94,8 +110,9 @@
/* Parameters for length and speed of simulation */
#define NSTEPS 200 /* number of frames of movie */
#define NVID 1200 /* number of iterations between images displayed on screen */
#define NSTEPS 1400 /* number of frames of movie */
#define NVID 2000 /* number of iterations between images displayed on screen */
// #define NVID 1200 /* number of iterations between images displayed on screen */
#define NSEG 100 /* number of segments of boundary */
#define BOUNDARY_WIDTH 2 /* width of billiard boundary */
@ -111,7 +128,7 @@
/* Plot type, see list in global_pdes.c */
#define PLOT 10
#define PLOT 11
/* Color schemes, see list in global_pdes.c */
@ -133,8 +150,6 @@
#define HUEMEAN 150.0 /* mean value of hue for color scheme C_HUE */
#define HUEAMP -150.0 /* amplitude of variation of hue for color scheme C_HUE */
#include "hsluv.c"
#include "global_pdes.c"
#include "sub_wave.c"
@ -401,7 +416,7 @@ void animation()
printf("Integration step %.3lg\n", intstep);
/* initialize wave wave function */
init_coherent_state(-1.2, 0.0, 20.0, 0.0, 0.25, phi, psi, xy_in);
init_coherent_state(0.5, 0.0, 40.0, 0.0, 0.25, phi, psi, xy_in);
// init_coherent_state(0.0, 0.0, 0.0, 5.0, 0.03, phi, psi, xy_in);
// init_coherent_state(-0.5, 0.0, 1.0, 1.0, 0.05, phi, psi, xy_in);

View File

@ -1,5 +1,8 @@
#include "colormaps.c"
#define DUMMY_ABSORBING -1000.0 /* dummy value of config[0] for absorbing circles */
#define BOUNDARY_SHIFT 100000.0 /* shift of boundary parametrisation for circles in domain */
#define DUMMY_SIDE_ABS -10000 /* dummy value of returned side for absorbing circles */
long int global_time = 0; /* counter to keep track of global time of simulation */
int nparticles=NPART;
@ -133,44 +136,6 @@ void init() /* initialisation of window */
}
void hsl_to_rgb(double h, double s, double l, double rgb[3]) /* color conversion from HSL to RGB */
/* h = hue, s = saturation, l = luminosity */
{
double c = 0.0, m = 0.0, x = 0.0;
c = (1.0 - fabs(2.0 * l - 1.0)) * s;
m = 1.0 * (l - 0.5 * c);
x = c * (1.0 - fabs(fmod(h / 60.0, 2) - 1.0));
if (h >= 0.0 && h < 60.0)
{
rgb[0] = c+m; rgb[1] = x+m; rgb[2] = m;
}
else if (h < 120.0)
{
rgb[0] = x+m; rgb[1] = c+m; rgb[2] = m;
}
else if (h < 180.0)
{
rgb[0] = m; rgb[1] = c+m; rgb[2] = x+m;
}
else if (h < 240.0)
{
rgb[0] = m; rgb[1] = x+m; rgb[2] = c+m;
}
else if (h < 300.0)
{
rgb[0] = x+m; rgb[1] = m; rgb[2] = c+m;
}
else if (h < 360.0)
{
rgb[0] = c+m; rgb[1] = m; rgb[2] = x+m;
}
else
{
rgb[0] = m; rgb[1] = m; rgb[2] = m;
}
}
void rgb_color_scheme(int i, double rgb[3]) /* color scheme */
{
@ -186,6 +151,7 @@ void rgb_color_scheme(int i, double rgb[3]) /* color scheme */
/* saturation = r, luminosity = 0.5 */
}
void rgb_color_scheme_lum(int i, double lum, double rgb[3]) /* color scheme */
{
double hue, y, r;
@ -349,6 +315,18 @@ void draw_colored_circle(double x, double y, double r, int nseg, double rgb[3])
}
void draw_initial_condition_circle(double x, double y, double r, int color)
/* draws a colored circle to mark initial condition */
{
double rgb[3];
rgb_color_scheme(color, rgb);
draw_colored_circle(x, y, r, NSEG, rgb);
rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0;
glColor3f(rgb[0], rgb[1], rgb[2]);
glLineWidth(4);
draw_circle(x, y, r, NSEG);
}
int in_circle(double x, double y, double r)
/* test whether (x,y) is in circle of radius r */
@ -1163,10 +1141,13 @@ void draw_billiard() /* draws the billiard boundary */
{
if (circleactive[k] == 2)
{
hsl_to_rgb(150.0, 0.9, 0.4, rgb);
glColor3f(rgb[0], rgb[1], rgb[2]);
// hsl_to_rgb(150.0, 0.9, 0.4, rgb);
// glColor3f(rgb[0], rgb[1], rgb[2]);
glColor3f(0.0, 1.0, 0.0);
rgb[0] = 0.0; rgb[1] = 0.9; rgb[2] = 0.0;
draw_colored_circle(circlex[k], circley[k], circlerad[k], NSEG, rgb);
}
draw_circle(circlex[k], circley[k], circlerad[k], NSEG);
else draw_circle(circlex[k], circley[k], circlerad[k], NSEG);
init_billiard_color();
}
@ -1227,6 +1208,55 @@ void draw_billiard() /* draws the billiard boundary */
glEnd ();
break;
}
case (D_CIRCLES_IN_TORUS):
{
rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0;
for (k=0; k<ncircles; k++) if (circleactive[k])
{
// printf("k = %i, color = %i\n", k, circlecolor[k]);
if (circlecolor[k] == 0) draw_colored_circle(circlex[k], circley[k], circlerad[k], NSEG, rgb);
else
{
if (newcircle[k] >= 1)
{
rgb_color_scheme_lum(circlecolor[k], 0.85, rgb1);
newcircle[k]--;
}
else rgb_color_scheme(circlecolor[k], rgb1);
draw_colored_circle(circlex[k], circley[k], circlerad[k], NSEG, rgb1);
}
}
init_billiard_color();
for (k=0; k<ncircles; k++) if (circleactive[k] >= 1)
{
if (circleactive[k] == 2)
{
hsl_to_rgb(150.0, 0.9, 0.4, rgb);
glColor3f(rgb[0], rgb[1], rgb[2]);
}
draw_circle(circlex[k], circley[k], circlerad[k], NSEG);
init_billiard_color();
}
/* draw shooter position for laser pattern */
if (CIRCLE_PATTERN == C_LASER)
{
hsl_to_rgb(0.0, 0.9, 0.5, rgb);
glColor3f(rgb[0], rgb[1], rgb[2]);
draw_circle(x_shooter, y_shooter, circlerad[ncircles-1], NSEG);
}
init_billiard_color();
glBegin(GL_LINE_LOOP);
glVertex2d(LAMBDA, -1.0);
glVertex2d(LAMBDA, 1.0);
glVertex2d(-LAMBDA, 1.0);
glVertex2d(-LAMBDA, -1.0);
glEnd();
break;
}
default:
{
printf("Function draw_billiard not defined for this billiard \n");
@ -3924,7 +3954,7 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
int vcircles_xy(double config[8], double alpha, double pos[2])
/* determine initial configuration for start at point pos = (x,y) */
{
double c0, s0, b, c, t, theta, delta, margin = 1.0e-12, tmin, rlarge = 1.0e10;
double c0, s0, b, c, t, theta, delta, margin = 1.0e-12, tmin, rlarge = 1000.0;
double tval[ncircles], xint[ncircles], yint[ncircles], phiint[ncircles];
int i, nt = 0, nscat[ncircles], ntmin;
@ -3991,8 +4021,8 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
}
else /* there is no intersection - set dummy values */
{
config[0] = 0.0;
config[1] = 0.0;
config[0] = DUMMY_ABSORBING;
config[1] = PI;
config[2] = 0.0;
config[3] = rlarge;
config[4] = pos[0]; /* start position */
@ -4012,7 +4042,7 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
c = pos_circles(config, pos, &alpha);
vcircles_xy(config, alpha, pos);
c = vcircles_xy(config, alpha, pos);
return(c);
}
@ -4125,9 +4155,11 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
{
config[0] = DUMMY_ABSORBING;
config[1] = PI;
// return(DUMMY_SIDE_ABS);
}
return(nscat[ntmin]);
if (ABSORBING_CIRCLES) return(DUMMY_SIDE_ABS);
else return(nscat[ntmin]);
}
else /* there is no intersection with the circles - compute intersection with boundary */
{
@ -4150,13 +4182,14 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
c = pos_circles_in_rect(config, pos, &alpha);
vcircles_in_rect_xy(config, alpha, pos);
// vcircles_in_rect_xy(config, alpha, pos);
c = vcircles_in_rect_xy(config, alpha, pos);
return(c);
}
/****************************************************************************************/
/****************************************************************************************/
/* billiard with circular scatterers in a genus n surface (polygon with identifies opposite sides) */
/****************************************************************************************/
@ -4298,6 +4331,151 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
}
/****************************************************************************************/
/* billiard with circular scatterers in a torus (rectangle with periodic boundary conditions) */
/****************************************************************************************/
int pos_circles_in_torus(double conf[2], double pos[2], double *alpha)
/* determine position on boundary of circle */
/* position varies between 0 and ncircles*2Pi for circles and between -BOUNDARY_SHIFT and 0 for boundary*/
/* returns number of hit circle */
{
double angle;
int ncirc, c;
if (conf[0] >= 0)
{
ncirc = (int)(conf[0]/DPI);
if (ncirc >= ncircles) ncirc = ncircles - 1;
angle = conf[0] - (double)ncirc*DPI;
pos[0] = circlex[ncirc] + circlerad[ncirc]*cos(angle);
pos[1] = circley[ncirc] + circlerad[ncirc]*sin(angle);
*alpha = angle + PID + conf[1];
return(ncirc);
}
else /* particle starts on boundary */
{
// conf[0] += 4.0*(LAMBDA + 1.0);
conf[0] += BOUNDARY_SHIFT;
c = pos_rectangle(conf, pos, alpha);
// conf[0] -= 4.0*(LAMBDA + 1.0);
conf[0] -= BOUNDARY_SHIFT;
return(-c-1);
}
}
int vcircles_in_torus_xy(double config[8], double alpha, double pos[2])
/* determine initial configuration for start at point pos = (x,y) */
// double config[8], alpha, pos[2];
{
double c0, s0, b, c, t, theta, delta, margin = 1.0e-12, tmin, rlarge = 1.0e10;
double tval[ncircles], xint[ncircles], yint[ncircles], phiint[ncircles];
int i, nt = 0, nscat[ncircles], ntmin, side;
c0 = cos(alpha);
s0 = sin(alpha);
for (i=0; i<ncircles; i++) if (circleactive[i])
{
b = (pos[0]-circlex[i])*c0 + (pos[1]-circley[i])*s0;
c = (pos[0]-circlex[i])*(pos[0]-circlex[i]) + (pos[1]-circley[i])*(pos[1]-circley[i]) - circlerad[i]*circlerad[i];
delta = b*b - c;
if (delta > margin) /* there is an intersection with circle i */
{
t = -b - sqrt(delta);
if (t > margin)
{
nscat[nt] = i;
tval[nt] = t;
xint[nt] = pos[0] + t*c0;
yint[nt] = pos[1] + t*s0;
phiint[nt] = argument(xint[nt] - circlex[i], yint[nt] - circley[i]);
/* test wether intersection is in rectangle */
if ((vabs(xint[nt]) < LAMBDA)&&(vabs(yint[nt]) < 1.0)) nt++;
}
}
}
if (nt > 0) /* there is at least one intersection */
{
/* find earliest intersection */
tmin = tval[0];
ntmin = 0;
for (i=1; i<nt; i++)
if (tval[i] < tmin)
{
tmin = tval[i];
ntmin = i;
}
while (phiint[ntmin] < 0.0) phiint[ntmin] += DPI;
while (phiint[ntmin] >= DPI) phiint[ntmin] -= DPI;
config[0] = (double)nscat[ntmin]*DPI + phiint[ntmin];
config[1] = PID - alpha + phiint[ntmin]; /* CHECK */
if (config[1] < 0.0) config[1] += DPI;
if (config[1] >= PI) config[1] -= DPI;
config[2] = 0.0; /* running time */
config[3] = module2(xint[ntmin]-pos[0], yint[ntmin]-pos[1]); /* distance to collision */
config[4] = pos[0]; /* start position */
config[5] = pos[1];
config[6] = xint[ntmin]; /* position of collision */
config[7] = yint[ntmin];
/* set dummy coordinates if circles are absorbing */
if (ABSORBING_CIRCLES)
{
config[0] = DUMMY_ABSORBING;
config[1] = PI;
}
return(nscat[ntmin]);
}
else /* there is no intersection with the circles - compute intersection with boundary */
{
side = vrectangle_xy(config, alpha, pos);
if (config[0] < 2.0*LAMBDA) config[0] = 4.0*LAMBDA + 2.0 - config[0];
else if (config[0] < 2.0*LAMBDA + 2.0) config[0] = 6.0*LAMBDA + 4.0 - config[0];
else if (config[0] < 4.0*LAMBDA + 2.0) config[0] = 4.0*LAMBDA + 2.0 - config[0];
else config[0] = 6.0*LAMBDA + 4.0 - config[0];
config[0] -= BOUNDARY_SHIFT;
config[1] = PI - config[1];
// config[0] -= 4.0*(LAMBDA+1.0);
// printf("Hit side %i\n", side);
// print_config(config);
return(side - 5);
}
}
int vcircles_in_torus(double config[8])
/* determine initial configuration when starting from boundary */
{
double pos[2], alpha;
int c;
c = pos_circles_in_torus(config, pos, &alpha);
vcircles_in_torus_xy(config, alpha, pos);
return(c);
}
/****************************************************************************************/
/* general billiard */
@ -4397,6 +4575,11 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
return(pos_circles_in_genusn(conf, pos, alpha));
break;
}
case (D_CIRCLES_IN_TORUS):
{
return(pos_circles_in_torus(conf, pos, alpha));
break;
}
default:
{
printf("Function pos_billiard not defined for this billiard \n");
@ -4500,6 +4683,11 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
return(vcircles_in_genusn_xy(config, alpha, pos));
break;
}
case (D_CIRCLES_IN_TORUS):
{
return(vcircles_in_torus_xy(config, alpha, pos));
break;
}
default:
{
printf("Function vbilliard_xy not defined for this billiard \n");
@ -4642,6 +4830,13 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
return(vcircles_in_genusn(config));
break;
}
case (D_CIRCLES_IN_TORUS):
{
c = pos_circles_in_torus(config, pos, &alpha);
return(vcircles_in_torus(config));
break;
}
default:
{
printf("Function vbilliard not defined for this billiard \n");
@ -4843,6 +5038,18 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
}
break;
}
case D_CIRCLES_IN_TORUS: /* same as D_CIRCLES_IN_RECT */
{
if ((vabs(x) >= LAMBDA)||(vabs(y) >= 1.0)) return(0);
else
{
condition = 1;
for (k=0; k<ncircles; k++)
if (circleactive[k]) condition = condition*out_circle(x-circlex[k], y-circley[k], circlerad[k]);
return(condition);
}
break;
}
default:
{
printf("Function ij_in_billiard not defined for this billiard \n");
@ -4919,6 +5126,8 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
ncircles = NCX*(NCY+1);
dy = (YMAX - YMIN)/((double)NCY);
dx = dy*0.5*sqrt(3.0);
// dx = (XMAX - XMIN)/((double)NCX);
// dy = dx/(0.5*sqrt(3.0));
for (i = 0; i < NCX; i++)
for (j = 0; j < NCY+1; j++)
{
@ -5071,42 +5280,54 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
break;
}
// case (C_LASER):
// {
// ncircles = 17;
//
// xx[0] = 0.5*(X_SHOOTER + X_TARGET);
// xx[1] = LAMBDA - 0.5*(X_TARGET - X_SHOOTER);
case (C_LASER):
{
ncircles = 17;
xx[0] = 0.5*(x_shooter + x_target);
xx[1] = LAMBDA - 0.5*(x_target - x_shooter);
if (xx[1] > LAMBDA) xx[1] = 2.0*LAMBDA - xx[1];
xx[2] = -xx[0];
xx[3] = -xx[1];
yy[0] = 0.5*(y_shooter + y_target);
yy[1] = 1.0 - 0.5*(y_target - y_shooter);
if (yy[1] > 1.0) yy[1] = 2.0 - yy[1];
yy[2] = -yy[0];
yy[3] = -yy[1];
// xx[0] = 0.5*(x_shooter + x_target);
// xx[1] = LAMBDA - 0.5*(x_target - x_shooter);
// xx[2] = -xx[0];
// xx[3] = -xx[1];
//
// yy[0] = 0.5*(Y_SHOOTER + Y_TARGET);
// yy[1] = 1.0 - 0.5*(Y_TARGET - Y_SHOOTER);
// yy[0] = 0.5*(y_shooter + y_target);
// yy[1] = 1.0 - 0.5*(y_target - y_shooter);
// yy[2] = -yy[0];
// yy[3] = -yy[1];
//
// for (i = 0; i < 4; i++)
// for (j = 0; j < 4; j++)
// {
// circlex[4*i + j] = xx[i];
// circley[4*i + j] = yy[j];
//
// }
//
// circlex[ncircles - 1] = X_TARGET;
// circley[ncircles - 1] = Y_TARGET;
//
// for (i=0; i<ncircles - 1; i++)
// {
// circlerad[i] = MU;
// circleactive[i] = 1;
// }
//
// circlerad[ncircles - 1] = 0.5*MU;
// circleactive[ncircles - 1] = 2;
//
// break;
// }
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
circlex[4*i + j] = xx[i];
circley[4*i + j] = yy[j];
}
circlex[ncircles - 1] = x_target;
circley[ncircles - 1] = y_target;
for (i=0; i<ncircles - 1; i++)
{
circlerad[i] = MU;
circleactive[i] = 1;
}
circlerad[ncircles - 1] = 0.5*MU;
circleactive[ncircles - 1] = 2;
break;
}
default:
{
printf("Function init_circle_config not defined for this pattern \n");
@ -5114,3 +5335,6 @@ void print_colors(int color[NPARTMAX]) /* for debugging purposes */
}
}

360
sub_part_pinball.c Normal file
View File

@ -0,0 +1,360 @@
/* global variables needed for circle configuration with periodic boundary conditions */
short int double_circle[NMAXCIRCLES]; /* set to 1 if a circle is a translate of another one on the boundary */
int partner_circle[NMAXCIRCLES]; /* number of circle of which current circle is a copy */
void init_circle_config_pinball(int circle_pattern)
{
int i, j, k, n, ncirc0, n_p_active, ncandidates=5000, naccepted;
double dx, dy, xx[4], yy[4], x, y, gamma, height, phi, r0, r, dpoisson = 3.25*MU;
short int active_poisson[NMAXCIRCLES], far;
switch (circle_pattern) {
case (C_FOUR_CIRCLES):
{
ncircles = 4;
circlex[0] = 1.0;
circley[0] = 0.0;
circlerad[0] = 0.8;
circlex[1] = -1.0;
circley[1] = 0.0;
circlerad[1] = 0.8;
circlex[2] = 0.0;
circley[2] = 0.8;
circlerad[2] = 0.4;
circlex[3] = 0.0;
circley[3] = -0.8;
circlerad[3] = 0.4;
for (i=0; i<4; i++)
{
circleactive[i] = 1;
circlecolor[i] = 0;
newcircle[i] = 0;
}
break;
}
case (C_SQUARE):
{
ncircles = NCX*NCY;
dy = (BOXYMAX - BOXYMIN)/((double)NCY);
// dy = (YMAX - YMIN)/((double)NCY);
for (i = 0; i < NCX; i++)
for (j = 0; j < NCY; j++)
{
n = NCY*i + j;
circlex[n] = ((double)(i-NCX/2) + 0.5)*dy;
circley[n] = BOXYMIN + ((double)j + 0.5)*dy;
circlerad[n] = MU;
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
}
break;
}
case (C_HEX):
{
ncircles = NCX*(NCY+1);
dy = (YMAX - YMIN)/((double)NCY);
dx = dy*0.5*sqrt(3.0);
for (i = 0; i < NCX; i++)
for (j = 0; j < NCY+1; j++)
{
n = (NCY+1)*i + j;
// circlex[n] = ((double)(i-NCX/2) + 0.5)*dy;
circlex[n] = ((double)(i-NCX/2))*dy;
if (NCX % 2 == 0) circlex[n] += 0.5*dy;
circley[n] = YMIN + ((double)j - 0.5)*dy;
if ((i+NCX)%2 == 1) circley[n] += 0.5*dy;
circlerad[n] = MU;
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
}
break;
}
case (C_TRI):
{
ncircles = NCX*(NCY+1);
dy = (BOXYMAX - BOXYMIN)/((double)NCY);
dx = dy*0.5*sqrt(3.0);
for (i = 0; i < NCX; i++)
for (j = 0; j < NCY+1; j++)
{
n = (NCY+1)*i + j;
circlex[n] = ((double)(i-NCX/2) + 0.5)*dx;
circley[n] = BOXYMIN + ((double)j)*dy;
if ((i+NCX)%2 == 1) circley[n] += 0.5*dy;
circlerad[n] = MU;
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
/* take care of periodic boundary conditions */
if (B_DOMAIN == D_CIRCLES_IN_TORUS)
{
if ((j == NCY)&&((i+NCX)%2 == 0))
{
double_circle[n] = 1;
partner_circle[n] = (NCY+1)*i;
}
else
{
double_circle[n] = 0;
if ((j == 0)&&((i+NCX)%2 == 0)) partner_circle[n] = (NCY+1)*i + NCY;
else partner_circle[n] = n;
}
}
else double_circle[n] = 0;
}
break;
}
case (C_GOLDEN_MEAN):
{
ncircles = NCX*NCY;
gamma = (sqrt(5.0) - 1.0)*0.5; /* golden mean */
height = YMAX - YMIN;
dx = 2.0*LAMBDA/((double)ncircles);
for (n = 0; n < ncircles; n++)
{
circlex[n] = -LAMBDA + n*dx;
circley[n] = y;
y += height*gamma;
if (y > YMAX) y -= height;
circlerad[n] = MU;
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
}
break;
}
case (C_GOLDEN_SPIRAL):
{
ncircles = 1;
circlex[0] = 0.0;
circley[0] = 0.0;
gamma = (sqrt(5.0) - 1.0)*PI; /* golden mean times 2Pi */
phi = 0.0;
r0 = 2.0*MU;
r = r0 + MU;
for (i=0; i<NGOLDENSPIRAL; i++)
{
x = r*cos(phi);
y = r*sin(phi);
phi += gamma;
r += MU*r0/r;
if ((vabs(x) < LAMBDA)&&(vabs(y) < YMAX + MU))
{
circlex[ncircles] = x;
circley[ncircles] = y;
ncircles++;
}
}
for (i=0; i<ncircles; i++)
{
circlerad[i] = MU;
circlecolor[i] = 0;
newcircle[i] = 0;
/* inactivate circles outside the domain */
if ((circley[i] < YMAX + MU)&&(circley[i] > YMIN - MU)) circleactive[i] = 1;
}
break;
}
case (C_RAND_DISPLACED):
{
ncircles = NCX*NCY;
dy = (YMAX - YMIN)/((double)NCY);
for (i = 0; i < NCX; i++)
for (j = 0; j < NCY; j++)
{
n = NCY*i + j;
circlex[n] = ((double)(i-NCX/2) + 0.5*((double)rand()/RAND_MAX - 0.5))*dy;
circley[n] = YMIN + ((double)j + 0.5 + 0.5*((double)rand()/RAND_MAX - 0.5))*dy;
circlerad[n] = MU*sqrt(1.0 + 0.8*((double)rand()/RAND_MAX - 0.5));
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
}
break;
}
case (C_RAND_POISSON):
{
ncircles = NPOISSON;
for (n = 0; n < NPOISSON; n++)
{
circlex[n] = LAMBDA*(2.0*(double)rand()/RAND_MAX - 1.0);
circley[n] = (BOXYMAX - BOXYMIN)*(double)rand()/RAND_MAX + BOXYMIN;
circlerad[n] = MU;
circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
double_circle[n] = 0;
partner_circle[n] = n;
/* take care of periodic boundary conditions */
if (B_DOMAIN == D_CIRCLES_IN_TORUS)
{
/* inactivate circles in corners */
if ((vabs(circlex[n]) > LAMBDA - MU)&&((circley[n] < BOXYMIN + MU)||(circley[n] > BOXYMAX - MU)))
circleactive[n] = 0;
if (circlex[n] < - LAMBDA + MU)
{
circlex[ncircles] = circlex[n] + 2.0*LAMBDA;
circley[ncircles] = circley[n];
partner_circle[ncircles] = n;
partner_circle[n] = ncircles;
ncircles++;
}
else if (circlex[n] > LAMBDA - MU)
{
circlex[ncircles] = circlex[n] - 2.0*LAMBDA;
circley[ncircles] = circley[n];
partner_circle[ncircles] = n;
partner_circle[n] = ncircles;
ncircles++;
}
if (circley[n] < BOXYMIN + MU)
{
circlex[ncircles] = circlex[n];
circley[ncircles] = circley[n] + BOXYMAX - BOXYMIN;
partner_circle[ncircles] = n;
partner_circle[n] = ncircles;
ncircles++;
}
else if (circley[n] > BOXYMAX - MU)
{
circlex[ncircles] = circlex[n];
circley[ncircles] = circley[n] - BOXYMAX + BOXYMIN;
partner_circle[ncircles] = n;
partner_circle[n] = ncircles;
ncircles++;
}
}
}
printf("%i circles\n", ncircles);
if (B_DOMAIN == D_CIRCLES_IN_TORUS) for (n = NPOISSON; n < ncircles; n++)
{
// printf("circle %i at (%.3f, %.3f)\n", n, circlex[n], circley[n]);
circlerad[n] = MU;
if (circleactive[partner_circle[n]]) circleactive[n] = 1;
circlecolor[n] = 0;
newcircle[n] = 0;
double_circle[n] = 1;
}
break;
}
case (C_POISSON_DISC):
{
printf("Generating Poisson disc sample\n");
/* generate first circle */
circlex[0] = LAMBDA*(2.0*(double)rand()/RAND_MAX - 1.0);
circley[0] = (YMAX - YMIN)*(double)rand()/RAND_MAX + YMIN;
active_poisson[0] = 1;
n_p_active = 1;
ncircles = 1;
while ((n_p_active > 0)&&(ncircles < NMAXCIRCLES))
{
/* randomly select an active circle */
i = rand()%(ncircles);
while (!active_poisson[i]) i = rand()%(ncircles);
// printf("Starting from circle %i at (%.3f,%.3f)\n", i, circlex[i], circley[i]);
/* generate new candidates */
naccepted = 0;
for (j=0; j<ncandidates; j++)
{
r = dpoisson*(2.0*(double)rand()/RAND_MAX + 1.0);
phi = DPI*(double)rand()/RAND_MAX;
x = circlex[i] + r*cos(phi);
y = circley[i] + r*sin(phi);
// printf("Testing new circle at (%.3f,%.3f)\t", x, y);
far = 1;
for (k=0; k<ncircles; k++) if ((k!=i))
{
/* new circle is far away from circle k */
far = far*((x - circlex[k])*(x - circlex[k]) + (y - circley[k])*(y - circley[k]) >= dpoisson*dpoisson);
/* new circle is in domain */
far = far*(vabs(x) < LAMBDA)*(y < YMAX)*(y > YMIN);
}
if (far) /* accept new circle */
{
printf("New circle at (%.3f,%.3f) accepted\n", x, y);
circlex[ncircles] = x;
circley[ncircles] = y;
circlerad[ncircles] = MU;
circleactive[ncircles] = 1;
circlecolor[ncircles] = 0;
newcircle[ncircles] = 0;
active_poisson[ncircles] = 1;
ncircles++;
n_p_active++;
naccepted++;
}
// else printf("Rejected\n");
}
if (naccepted == 0) /* inactivate circle i */
{
// printf("No candidates work, inactivate circle %i\n", i);
active_poisson[i] = 0;
n_p_active--;
}
printf("%i active circles\n", n_p_active);
}
printf("Generated %i circles\n", ncircles);
break;
}
// case (C_LASER):
// {
// ncircles = 17;
//
// xx[0] = 0.5*(X_SHOOTER + X_TARGET);
// xx[1] = LAMBDA - 0.5*(X_TARGET - X_SHOOTER);
// xx[2] = -xx[0];
// xx[3] = -xx[1];
//
// yy[0] = 0.5*(Y_SHOOTER + Y_TARGET);
// yy[1] = 1.0 - 0.5*(Y_TARGET - Y_SHOOTER);
// yy[2] = -yy[0];
// yy[3] = -yy[1];
//
// for (i = 0; i < 4; i++)
// for (j = 0; j < 4; j++)
// {
// circlex[4*i + j] = xx[i];
// circley[4*i + j] = yy[j];
//
// }
//
// circlex[ncircles - 1] = X_TARGET;
// circley[ncircles - 1] = Y_TARGET;
//
// for (i=0; i<ncircles - 1; i++)
// {
// circlerad[i] = MU;
// circleactive[i] = 1;
// }
//
// circlerad[ncircles - 1] = 0.5*MU;
// circleactive[ncircles - 1] = 2;
//
// break;
// }
default:
{
printf("Function init_circle_config not defined for this pattern \n");
}
}
}

View File

@ -2,6 +2,9 @@
/* Graphics routines */
/*********************/
#include "colors_waves.c"
int writetiff(char *filename, char *description, int x, int y, int width, int height, int compression)
{
TIFF *file;
@ -67,149 +70,8 @@ void init() /* initialisation of window */
void hsl_to_rgb_jet(double h, double s, double l, double rgb[3]) /* color conversion from HSL to RGB */
/* h = hue, s = saturation, l = luminosity */
{
double c = 0.0, m = 0.0, x = 0.0;
c = (1.0 - fabs(2.0 * l - 1.0)) * s;
m = 1.0 * (l - 0.5 * c);
x = c * (1.0 - fabs(fmod(h / 60.0, 2) - 1.0));
if (h >= 0.0 && h < 60.0)
{
rgb[0] = c+m; rgb[1] = x+m; rgb[2] = m;
}
else if (h < 120.0)
{
rgb[0] = x+m; rgb[1] = c+m; rgb[2] = m;
}
else if (h < 180.0)
{
rgb[0] = m; rgb[1] = c+m; rgb[2] = x+m;
}
else if (h < 240.0)
{
rgb[0] = m; rgb[1] = x+m; rgb[2] = c+m;
}
else if (h < 300.0)
{
rgb[0] = x+m; rgb[1] = m; rgb[2] = c+m;
}
else if (h < 360.0)
{
rgb[0] = c+m; rgb[1] = m; rgb[2] = x+m;
}
else
{
rgb[0] = m; rgb[1] = m; rgb[2] = m;
}
}
void hsl_to_rgb(double h, double s, double l, double rgb[3]) /* color conversion from HSL to RGB */
{
double r, g, b;
switch (COLOR_PALETTE) {
case (COL_JET):
{
hsl_to_rgb_jet(h, s, l, rgb);
break;
}
case (COL_HSLUV):
{
hsluv2rgb(h, 100.0*s, l, &r, &g, &b);
rgb[0] = r*100.0;
rgb[1] = g*100.0;
rgb[2] = b*100.0;
break;
}
}
// if (HSLUV_COLORS)
// {
// hsluv2rgb(h, 100.0*s, l, &r, &g, &b);
// rgb[0] = r*100.0;
// rgb[1] = g*100.0;
// rgb[2] = b*100.0;
// }
// else hsl_to_rgb_jet(h, s, l, rgb);
}
double color_amplitude(double value, double scale, int time)
/* transforms the wave amplitude into a double in [-1,1] to feed into color scheme */
{
return(tanh(SLOPE*value/scale)*exp(-((double)time*ATTENUATION)));
}
void color_scheme(int scheme, double value, double scale, int time, double rgb[3]) /* color scheme */
{
double hue, y, r, amplitude;
int intpart;
/* saturation = r, luminosity = y */
switch (scheme) {
case (C_LUM):
{
hue = COLORHUE + (double)time*COLORDRIFT/(double)NSTEPS;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = LUMMEAN + amplitude*LUMAMP;
intpart = (int)y;
y -= (double)intpart;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_HUE):
{
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = 0.5;
hue = HUEMEAN + amplitude*HUEAMP;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
hsl_to_rgb(hue, r, y, rgb);
break;
}
}
}
void color_scheme_lum(int scheme, double value, double scale, int time, double lum, double rgb[3]) /* color scheme */
{
double hue, y, r, amplitude;
int intpart;
/* saturation = r, luminosity = y */
switch (scheme) {
case (C_LUM):
{
hue = COLORHUE + (double)time*COLORDRIFT/(double)NSTEPS;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = LUMMEAN + amplitude*LUMAMP;
intpart = (int)y;
y -= (double)intpart;
hsl_to_rgb(hue, r, y, rgb);
break;
}
case (C_HUE):
{
r = 0.9;
amplitude = color_amplitude(value, scale, time);
y = lum;
hue = HUEMEAN + amplitude*HUEAMP;
if (hue < 0.0) hue += 360.0;
if (hue >= 360.0) hue -= 360.0;
hsl_to_rgb(hue, r, y, rgb);
break;
}
}
}
void blank()
@ -502,7 +364,7 @@ void init_circle_config()
/* for billiard shape D_CIRCLES */
{
int i, j, k, n, ncirc0, n_p_active, ncandidates=5000, naccepted;
double dx, dy, p, phi, r, r0, ra[5], sa[5], height, x, y = 0.0, gamma, dpoisson = 3.25*MU;
double dx, dy, p, phi, r, r0, ra[5], sa[5], height, x, y = 0.0, gamma, dpoisson = 3.25*MU, xx[4], yy[4];
short int active_poisson[NMAXCIRCLES], far;
switch (CIRCLE_PATTERN) {
@ -621,6 +483,42 @@ void init_circle_config()
}
break;
}
case (C_LASER):
{
ncircles = 17;
xx[0] = 0.5*(X_SHOOTER + X_TARGET);
xx[1] = LAMBDA - 0.5*(X_TARGET - X_SHOOTER);
xx[2] = -xx[0];
xx[3] = -xx[1];
yy[0] = 0.5*(Y_SHOOTER + Y_TARGET);
yy[1] = 1.0 - 0.5*(Y_TARGET - Y_SHOOTER);
yy[2] = -yy[0];
yy[3] = -yy[1];
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
circlex[4*i + j] = xx[i];
circley[4*i + j] = yy[j];
}
circlex[ncircles - 1] = X_TARGET;
circley[ncircles - 1] = Y_TARGET;
for (i=0; i<ncircles - 1; i++)
{
circlerad[i] = MU;
circleactive[i] = 1;
}
circlerad[ncircles - 1] = 0.5*MU;
circleactive[ncircles - 1] = 2;
break;
}
case (C_POISSON_DISC):
{
printf("Generating Poisson disc sample\n");
@ -628,6 +526,7 @@ void init_circle_config()
circlex[0] = LAMBDA*(2.0*(double)rand()/RAND_MAX - 1.0);
circley[0] = (YMAX - YMIN)*(double)rand()/RAND_MAX + YMIN;
active_poisson[0] = 1;
// circleactive[0] = 1;
n_p_active = 1;
ncircles = 1;
@ -811,12 +710,104 @@ void init_circle_config()
}
int axial_symmetry(double z1[2], double z2[2], double z[2], double zprime[2])
/* compute reflection of point z wrt axis through z1 and z2 */
{
double u[2], r, zdotu, zparallel[2], zperp[2];
/* compute unit vector parallel to z1-z2 */
u[0] = z2[0] - z1[0];
u[1] = z2[1] - z1[1];
r = module2(u[0], u[1]);
if (r == 0) return(0); /* z1 and z2 are the same */
u[0] = u[0]/r;
u[1] = u[1]/r;
// printf("u = (%.2f, %.2f)\n", u[0], u[1]);
/* projection of z1z on z1z2 */
zdotu = (z[0] - z1[0])*u[0] + (z[1] - z1[1])*u[1];
zparallel[0] = zdotu*u[0];
zparallel[1] = zdotu*u[1];
// printf("zparallel = (%.2f, %.2f)\n", zparallel[0], zparallel[1]);
/* normal vector to z1z2 */
zperp[0] = z[0] - z1[0] - zparallel[0];
zperp[1] = z[1] - z1[1] - zparallel[1];
// printf("zperp = (%.2f, %.2f)\n", zperp[0], zperp[1]);
/* reflected point */
zprime[0] = z[0] - 2.0*zperp[0];
zprime[1] = z[1] - 2.0*zperp[1];
return(1);
}
void compute_isospectral_coordinates(int type, double xshift, double yshift, double scaling, double vertex[9][2])
/* compute positions of vertices of isospectral billiards */
/* central triangle has coordinates (0,0), (1,0) and (LAMBDA,MU) fed into affine transformation */
/* defined by (xshift - 0.5), (yshift - 0.25) and scaling*/
{
vertex[0][0] = (xshift - 0.5)*scaling;
vertex[0][1] = (yshift - 0.25)*scaling;
vertex[1][0] = (0.5 + xshift)*scaling;
vertex[1][1] = (yshift - 0.25)*scaling;
vertex[2][0] = (LAMBDA + xshift - 0.5)*scaling;
vertex[2][1] = (MU + yshift - 0.25)*scaling;
axial_symmetry(vertex[0], vertex[2], vertex[1], vertex[3]);
axial_symmetry(vertex[0], vertex[1], vertex[2], vertex[4]);
axial_symmetry(vertex[1], vertex[2], vertex[0], vertex[5]);
if (type == 0)
{
axial_symmetry(vertex[0], vertex[3], vertex[2], vertex[6]);
axial_symmetry(vertex[1], vertex[4], vertex[0], vertex[7]);
axial_symmetry(vertex[2], vertex[5], vertex[1], vertex[8]);
}
else
{
axial_symmetry(vertex[2], vertex[3], vertex[0], vertex[6]);
axial_symmetry(vertex[0], vertex[4], vertex[1], vertex[7]);
axial_symmetry(vertex[1], vertex[5], vertex[2], vertex[8]);
}
}
void isospectral_initial_point(double x, double y, double left[2], double right[2])
/* compute initial coordinates in isospectral billiards */
{
left[0] = (x + ISO_XSHIFT_LEFT)*ISO_SCALE;
left[1] = (y + ISO_YSHIFT_LEFT)*ISO_SCALE;
right[0] = (x + ISO_XSHIFT_RIGHT)*ISO_SCALE;
right[1] = (y + ISO_YSHIFT_RIGHT)*ISO_SCALE;
}
int xy_in_triangle(double x, double y, double z1[2], double z2[2], double z3[2])
/* returns 1 iff (x,y) is inside the triangle with vertices z1, z2, z3 */
{
double v1, v2, v3;
/* compute wedge products */
v1 = (z2[0] - z1[0])*(y - z1[1]) - (z2[1] - z1[1])*(x - z1[0]);
v2 = (z3[0] - z2[0])*(y - z2[1]) - (z3[1] - z2[1])*(x - z2[0]);
v3 = (z1[0] - z3[0])*(y - z3[1]) - (z1[1] - z3[1])*(x - z3[0]);
if ((v1 >= 0.0)&&(v2 >= 0.0)&&(v3 >= 0.0)) return(1);
else return(0);
}
int xy_in_billiard(double x, double y)
/* returns 1 if (x,y) represents a point in the billiard */
// double x, y;
{
double l2, r2, r2mu, omega, b, c, angle, z, x1, y1, x2, y2, u, v, u1, v1, dx, dy, width;
int i, j, k, k1, k2, condition;
static double vertex[9][2], wertex[9][2];
static int first = 1;
switch (B_DOMAIN) {
case (D_RECTANGLE):
@ -1048,6 +1039,33 @@ int xy_in_billiard(double x, double y)
else return(1);
}
}
case (D_ISOSPECTRAL):
{
if (first)
{
compute_isospectral_coordinates(0, ISO_XSHIFT_LEFT, ISO_YSHIFT_LEFT, ISO_SCALE, vertex);
compute_isospectral_coordinates(1, ISO_XSHIFT_RIGHT, ISO_YSHIFT_RIGHT, ISO_SCALE, wertex);
first = 0;
}
/* 1st triangle */
condition = xy_in_triangle(x, y, vertex[0], vertex[1], vertex[2]);
condition += xy_in_triangle(x, y, vertex[0], vertex[4], vertex[1]);
condition += xy_in_triangle(x, y, vertex[1], vertex[5], vertex[2]);
condition += xy_in_triangle(x, y, vertex[0], vertex[2], vertex[3]);
condition += xy_in_triangle(x, y, vertex[1], vertex[4], vertex[7]);
condition += xy_in_triangle(x, y, vertex[2], vertex[5], vertex[8]);
condition += xy_in_triangle(x, y, vertex[0], vertex[3], vertex[6]);
/* 2nd triangle */
condition += xy_in_triangle(x, y, wertex[0], wertex[1], wertex[2]);
condition += xy_in_triangle(x, y, wertex[0], wertex[4], wertex[1]);
condition += xy_in_triangle(x, y, wertex[1], wertex[5], wertex[2]);
condition += xy_in_triangle(x, y, wertex[0], wertex[2], wertex[3]);
condition += xy_in_triangle(x, y, wertex[0], wertex[7], wertex[4]);
condition += xy_in_triangle(x, y, wertex[1], wertex[8], wertex[5]);
condition += xy_in_triangle(x, y, wertex[2], wertex[6], wertex[3]);
return(condition >= 1);
}
case (D_CIRCLES):
{
for (i = 0; i < ncircles; i++)
@ -1060,6 +1078,19 @@ int xy_in_billiard(double x, double y)
}
return(1);
}
case (D_CIRCLES_IN_RECT): /* returns 2 inside circles, 0 outside rectangle */
{
for (i = 0; i < ncircles; i++)
if (circleactive[i])
{
x1 = circlex[i];
y1 = circley[i];
r2 = circlerad[i]*circlerad[i];
if ((x-x1)*(x-x1) + (y-y1)*(y-y1) < r2) return(2);
}
if ((vabs(x) >= LAMBDA)||(vabs(y) >= 1.0)) return(0);
else return(1);
}
case (D_MENGER):
{
x1 = 0.5*(x+1.0);
@ -1225,10 +1256,22 @@ void toka_lineto(double x1, double y1)
glVertex2d(pos[0], pos[1]);
}
void iso_lineto(double z[2])
/* draws boundary segments of isospectral billiard */
{
double pos[2];
xy_to_pos(z[0], z[1], pos);
glVertex2d(pos[0], pos[1]);
}
void draw_billiard() /* draws the billiard boundary */
{
double x0, x, y, x1, y1, dx, dy, phi, r = 0.01, pos[2], pos1[2], alpha, dphi, omega, z, l, width, a, b, c, ymax;
static double vertex[9][2], wertex[9][2];
int i, j, k, k1, k2, mr2;
static int first = 1;
if (BLACK) glColor3f(1.0, 1.0, 1.0);
else glColor3f(0.0, 0.0, 0.0);
@ -1635,7 +1678,7 @@ void draw_billiard() /* draws the billiard boundary */
glColor3f(0.3, 0.3, 0.3);
for (k=0; k<NPOLY; k++)
{
alpha = APOLY*PID + (k+0.5)*omega;
alpha = APOLY*PID + (2.0*(double)k+1.0)*omega;
draw_circle(LAMBDA*cos(alpha), LAMBDA*sin(alpha), r, NSEG);
}
}
@ -1795,6 +1838,70 @@ void draw_billiard() /* draws the billiard boundary */
}
break;
}
case (D_ISOSPECTRAL):
{
if (first)
{
compute_isospectral_coordinates(0, ISO_XSHIFT_LEFT, ISO_YSHIFT_LEFT, ISO_SCALE, vertex);
compute_isospectral_coordinates(1, ISO_XSHIFT_RIGHT, ISO_YSHIFT_RIGHT, ISO_SCALE, wertex);
// compute_isospectral_coordinates(0, -1.0, 0.05, 0.9, vertex);
// compute_isospectral_coordinates(1, 0.9, 0.05, 0.9, wertex);
// for (i=0; i<9; i++) printf("(x%i, y%i) = (%.2f, %.2f)\n", i, i, vertex[i][0], vertex[i][1]);
first = 0;
}
/* 1st triangle */
glBegin(GL_LINE_LOOP);
iso_lineto(vertex[0]);
iso_lineto(vertex[4]);
iso_lineto(vertex[7]);
iso_lineto(vertex[1]);
iso_lineto(vertex[5]);
iso_lineto(vertex[8]);
iso_lineto(vertex[2]);
iso_lineto(vertex[3]);
iso_lineto(vertex[6]);
glEnd();
/* inner lines */
glBegin(GL_LINE_LOOP);
iso_lineto(vertex[0]);
iso_lineto(vertex[1]);
iso_lineto(vertex[2]);
iso_lineto(vertex[0]);
iso_lineto(vertex[3]);
iso_lineto(vertex[2]);
iso_lineto(vertex[5]);
iso_lineto(vertex[1]);
iso_lineto(vertex[4]);
glEnd();
/* 2nd triangle */
glBegin(GL_LINE_LOOP);
iso_lineto(wertex[0]);
iso_lineto(wertex[7]);
iso_lineto(wertex[4]);
iso_lineto(wertex[1]);
iso_lineto(wertex[8]);
iso_lineto(wertex[5]);
iso_lineto(wertex[2]);
iso_lineto(wertex[6]);
iso_lineto(wertex[3]);
glEnd();
/* inner lines */
glBegin(GL_LINE_LOOP);
iso_lineto(wertex[0]);
iso_lineto(wertex[1]);
iso_lineto(wertex[2]);
iso_lineto(wertex[0]);
iso_lineto(wertex[4]);
iso_lineto(wertex[1]);
iso_lineto(wertex[5]);
iso_lineto(wertex[2]);
iso_lineto(wertex[3]);
glEnd();
break;
}
case (D_CIRCLES):
{
glLineWidth(BOUNDARY_WIDTH);
@ -1802,6 +1909,19 @@ void draw_billiard() /* draws the billiard boundary */
if (circleactive[i]) draw_circle(circlex[i], circley[i], circlerad[i], NSEG);
break;
}
case (D_CIRCLES_IN_RECT):
{
glLineWidth(BOUNDARY_WIDTH);
for (i = 0; i < ncircles; i++)
if (circleactive[i]) draw_circle(circlex[i], circley[i], circlerad[i], NSEG);
draw_rectangle(-LAMBDA, -1.0, LAMBDA, 1.0);
if ((FOCI)&&(CIRCLE_PATTERN == C_LASER))
{
glColor3f(0.3, 0.3, 0.3);
draw_circle(X_SHOOTER, Y_SHOOTER, r, NSEG);
}
break;
}
case (D_MENGER):
{
glLineWidth(3);

10
turbo_colormap.c Normal file

File diff suppressed because one or more lines are too long

View File

@ -48,37 +48,31 @@
/* General geometrical parameters */
#define WINWIDTH 1280 /* window width */
// #define WINWIDTH 720 /* window width */
#define WINHEIGHT 720 /* window height */
#define NX 1280 /* number of grid points on x axis */
// #define NX 720 /* number of grid points on x axis */
#define NY 720 /* number of grid points on y axis */
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
#define YMIN -1.125
#define YMAX 1.125 /* y interval for 9/16 aspect ratio */
// #define XMIN -1.6
// #define XMAX 1.6 /* x interval */
// #define YMIN -1.6
// #define YMAX 1.6 /* y interval for 9/16 aspect ratio */
#define JULIA_SCALE 1.0 /* scaling for Julia sets */
/* Choice of the billiard table */
#define B_DOMAIN 34 /* choice of domain shape, see list in global_pdes.c */
#define B_DOMAIN 32 /* choice of domain shape, see list in global_pdes.c */
#define CIRCLE_PATTERN 8 /* pattern of circles, see list in global_pdes.c */
#define CIRCLE_PATTERN 7 /* pattern of circles, see list in global_pdes.c */
#define P_PERCOL 0.25 /* probability of having a circle in C_RAND_PERCOL arrangement */
#define NPOISSON 300 /* number of points for Poisson C_RAND_POISSON arrangement */
#define LAMBDA 0.6 /* parameter controlling the dimensions of domain */
#define MU 0.3 /* parameter controlling the dimensions of domain */
#define NPOLY 3 /* number of sides of polygon */
#define APOLY 0.0 /* angle by which to turn polygon, in units of Pi/2 */
#define LAMBDA 0.0 /* parameter controlling the dimensions of domain */
#define MU 1.0 /* parameter controlling the dimensions of domain */
#define NPOLY 7 /* number of sides of polygon */
#define APOLY 1.0 /* angle by which to turn polygon, in units of Pi/2 */
#define MDEPTH 4 /* depth of computation of Menger gasket */
#define MRATIO 3 /* ratio defining Menger gasket */
#define MANDELLEVEL 1000 /* iteration level for Mandelbrot set */
@ -87,6 +81,17 @@
#define NGRIDX 16 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard below */
@ -99,9 +104,9 @@
#define OMEGA 0.002 /* frequency of periodic excitation */
#define AMPLITUDE 1.0 /* amplitude of periodic excitation */
#define COURANT 0.02 /* Courant number */
#define COURANTB 0.01 /* Courant number in medium B */
#define COURANTB 0.02 /* Courant number in medium B */
#define GAMMA 0.0 /* damping factor in wave equation */
#define GAMMAB 1.0e-6 /* damping factor in wave equation */
#define GAMMAB 5.0e-3 /* damping factor in wave equation */
#define GAMMA_SIDES 1.0e-4 /* damping factor on boundary */
#define GAMMA_TOPBOT 1.0e-7 /* damping factor on boundary */
#define KAPPA 0.0 /* "elasticity" term enforcing oscillations */
@ -118,8 +123,8 @@
/* Parameters for length and speed of simulation */
#define NSTEPS 4050 /* number of frames of movie */
#define NVID 32 /* number of iterations between images displayed on screen */
#define NSTEPS 5000 /* number of frames of movie */
#define NVID 50 /* number of iterations between images displayed on screen */
#define NSEG 100 /* number of segments of boundary */
#define INITIAL_TIME 0 /* time after which to start saving frames */
#define BOUNDARY_WIDTH 2 /* width of billiard boundary */
@ -133,48 +138,49 @@
/* Parameters of initial condition */
#define INITIAL_AMP 0.2 /* amplitude of initial condition */
#define INITIAL_VARIANCE 0.002 /* variance of initial condition */
#define INITIAL_WAVELENGTH 0.1 /* wavelength of initial condition */
#define INITIAL_AMP 0.75 /* amplitude of initial condition */
#define INITIAL_VARIANCE 0.0005 /* variance of initial condition */
#define INITIAL_WAVELENGTH 0.02 /* wavelength of initial condition */
/* Plot type, see list in global_pdes.c */
#define PLOT 1
#define PLOT_B 0 /* plot type for second movie */
#define PLOT_B 3 /* plot type for second movie */
/* Color schemes */
#define COLOR_PALETTE 0 /* Color palette, see list in global_pdes.c */
#define COLOR_PALETTE 13 /* Color palette, see list in global_pdes.c */
#define BLACK 1 /* background */
#define COLOR_SCHEME 1 /* choice of color scheme, see list in global_pdes.c */
#define COLOR_SCHEME 3 /* choice of color scheme, see list in global_pdes.c */
#define SCALE 0 /* set to 1 to adjust color scheme to variance of field */
#define SLOPE 0.08 /* sensitivity of color on wave amplitude */
// #define SLOPE 0.05 /* sensitivity of color on wave amplitude */
#define SLOPE 0.15 /* sensitivity of color on wave amplitude */
#define ATTENUATION 0.0 /* exponential attenuation coefficient of contrast with time */
#define E_SCALE 200.0 /* scaling factor for energy representation */
// #define E_SCALE 2500.0 /* scaling factor for energy representation */
#define E_SCALE 100.0 /* scaling factor for energy representation */
#define COLORHUE 260 /* initial hue of water color for scheme C_LUM */
#define COLORDRIFT 0.0 /* how much the color hue drifts during the whole simulation */
#define LUMMEAN 0.5 /* amplitude of luminosity variation for scheme C_LUM */
#define LUMAMP 0.3 /* amplitude of luminosity variation for scheme C_LUM */
#define HUEMEAN 220.0 /* mean value of hue for color scheme C_HUE */
#define HUEAMP -230.0 /* amplitude of variation of hue for color scheme C_HUE */
#define HUEMEAN 180.0 /* mean value of hue for color scheme C_HUE */
#define HUEAMP -180.0 /* amplitude of variation of hue for color scheme C_HUE */
#define DRAW_COLOR_SCHEME 1 /* set to 1 to plot the color scheme */
#define SAVE_TIME_SERIES 0 /* set to 1 to save wave time series at a point */
/* For debugging purposes only */
#define FLOOR 0 /* set to 1 to limit wave amplitude to VMAX */
#define VMAX 10.0 /* max value of wave amplitude */
#include "hsluv.c"
#include "global_pdes.c" /* constants and global variables */
#include "sub_wave.c" /* common functions for wave_billiard, heat and schrodinger */
#include "wave_common.c" /* common functions for wave_billiard, wave_comparison, etc */
FILE *time_series_left, *time_series_right;
double courant2, courantb2; /* Courant parameters squared */
@ -200,11 +206,18 @@ void evolve_wave_half(double *phi_in[NX], double *psi_in[NX], double *phi_out[NX
#pragma omp parallel for private(i,j,iplus,iminus,jplus,jminus,delta,x,y,c,cc,gamma)
for (i=0; i<NX; i++){
for (j=0; j<NY; j++){
if (xy_in[i][j])
// if (xy_in[i][j])
// {
// c = COURANT;
// cc = courant2;
// gamma = GAMMA;
// }
if (xy_in[i][j] != 0)
{
c = COURANT;
cc = courant2;
gamma = GAMMA;
if (xy_in[i][j] == 1) gamma = GAMMA;
else gamma = GAMMAB;
}
else if (TWOSPEEDS)
{
@ -213,7 +226,7 @@ void evolve_wave_half(double *phi_in[NX], double *psi_in[NX], double *phi_out[NX
gamma = GAMMAB;
}
if ((TWOSPEEDS)||(xy_in[i][j])){
if ((TWOSPEEDS)||(xy_in[i][j] != 0)){
/* discretized Laplacian for various boundary conditions */
if ((B_COND == BC_DIRICHLET)||(B_COND == BC_ABSORBING))
{
@ -320,11 +333,18 @@ void evolve_wave(double *phi[NX], double *psi[NX], double *phi_tmp[NX], double *
void animation()
{
double time, scale;
double *phi[NX], *psi[NX], *phi_tmp[NX], *psi_tmp[NX];
double time, scale, ratio, startleft[2], startright[2];
double *phi[NX], *psi[NX], *phi_tmp[NX], *psi_tmp[NX], *total_energy[NX];
short int *xy_in[NX];
int i, j, s;
int i, j, s, sample_left[2], sample_right[2];
static int counter = 0;
long int wave_value;
if (SAVE_TIME_SERIES)
{
time_series_left = fopen("wave_left.dat", "w");
time_series_right = fopen("wave_right.dat", "w");
}
/* Since NX and NY are big, it seemed wiser to use some memory allocation here */
for (i=0; i<NX; i++)
@ -333,24 +353,46 @@ void animation()
psi[i] = (double *)malloc(NY*sizeof(double));
phi_tmp[i] = (double *)malloc(NY*sizeof(double));
psi_tmp[i] = (double *)malloc(NY*sizeof(double));
total_energy[i] = (double *)malloc(NY*sizeof(double));
xy_in[i] = (short int *)malloc(NY*sizeof(short int));
}
/* initialise positions and radii of circles */
if (B_DOMAIN == D_CIRCLES) init_circle_config();
if ((B_DOMAIN == D_CIRCLES)||(B_DOMAIN == D_CIRCLES_IN_RECT)) init_circle_config();
courant2 = COURANT*COURANT;
courantb2 = COURANTB*COURANTB;
/* initialize wave with a drop at one point, zero elsewhere */
init_circular_wave(0.0, -LAMBDA, phi, psi, xy_in);
// init_circular_wave(0.0, -LAMBDA, phi, psi, xy_in);
/* initialize total energy table */
if ((PLOT == P_MEAN_ENERGY)||(PLOT_B == P_MEAN_ENERGY))
for (i=0; i<NX; i++)
for (j=0; j<NY; j++)
total_energy[i][j] = 0.0;
ratio = (XMAX - XMIN)/8.4; /* for Tokarsky billiard */
isospectral_initial_point(0.25, 0.0, startleft, startright); /* for isospectral billiards */
xy_to_ij(startleft[0], startleft[1], sample_left);
xy_to_ij(startright[0], startright[1], sample_right);
// printf("xleft = (%.3f, %.3f) xright = (%.3f, %.3f)\n", xin_left, yin_left, xin_right, yin_right);
// init_wave_flat(phi, psi, xy_in);
// init_wave_plus(LAMBDA - 0.3*MU, 0.5*MU, phi, psi, xy_in);
// init_wave(LAMBDA - 0.3*MU, 0.5*MU, phi, psi, xy_in);
// init_wave(0.0, 0.0, phi, psi, xy_in);
// init_circular_wave(X_SHOOTER, Y_SHOOTER, phi, psi, xy_in);
init_circular_wave(-LAMBDA, 0.0, phi, psi, xy_in);
// init_circular_wave(0.5, 0.5, phi, psi, xy_in);
// add_circular_wave(-1.0, 0.0, LAMBDA, phi, psi, xy_in);
// add_circular_wave(1.0, -LAMBDA, 0.0, phi, psi, xy_in);
// add_circular_wave(-1.0, 0.0, -LAMBDA, phi, psi, xy_in);
// init_circular_wave_xplusminus(startleft[0], startleft[1], startright[0], startright[1], phi, psi, xy_in);
// init_circular_wave_xplusminus(-0.9, 0.0, 0.81, 0.0, phi, psi, xy_in);
// init_circular_wave(-2.0*ratio, 0.0, phi, psi, xy_in);
// init_planar_wave(XMIN + 0.015, 0.0, phi, psi, xy_in);
// init_planar_wave(XMIN + 0.02, 0.0, phi, psi, xy_in);
// init_planar_wave(XMIN + 0.8, 0.0, phi, psi, xy_in);
@ -364,8 +406,11 @@ void animation()
blank();
glColor3f(0.0, 0.0, 0.0);
draw_wave(phi, psi, xy_in, 1.0, 0, PLOT);
// draw_wave(phi, psi, xy_in, 1.0, 0, PLOT);
draw_wave_e(phi, psi, total_energy, xy_in, 1.0, 0, PLOT);
draw_billiard();
if (DRAW_COLOR_SCHEME) draw_color_scheme(1.7, YMIN + 0.1, 1.9, YMAX - 0.1, PLOT, -12.0, 12.0);
glutSwapBuffers();
@ -385,21 +430,31 @@ void animation()
}
else scale = 1.0;
draw_wave(phi, psi, xy_in, scale, i, PLOT);
// draw_wave(phi, psi, xy_in, scale, i, PLOT);
draw_wave_e(phi, psi, total_energy, xy_in, scale, i, PLOT);
for (j=0; j<NVID; j++)
{
evolve_wave(phi, psi, phi_tmp, psi_tmp, xy_in);
if (SAVE_TIME_SERIES)
{
wave_value = (long int)(phi[sample_left[0]][sample_left[1]]*1.0e16);
fprintf(time_series_left, "%019ld\n", wave_value);
wave_value = (long int)(phi[sample_right[0]][sample_right[1]]*1.0e16);
fprintf(time_series_right, "%019ld\n", wave_value);
if ((j == 0)&&(i%10 == 0)) printf("Frame %i of %i\n", i, NSTEPS);
// fprintf(time_series_right, "%.15f\n", phi[sample_right[0]][sample_right[1]]);
}
// if (i % 10 == 9) oscillate_linear_wave(0.2*scale, 0.15*(double)(i*NVID + j), -1.5, YMIN, -1.5, YMAX, phi, psi);
}
draw_billiard();
if (DRAW_COLOR_SCHEME) draw_color_scheme(1.7, YMIN + 0.1, 1.9, YMAX - 0.1, PLOT, -12.0, 12.0);
/* add oscillating waves */
// if (i%160 == 159)
if (i%150 == 149)
if (i%345 == 344)
{
add_circular_wave(1.0, 0.0, LAMBDA, phi, psi, xy_in);
add_circular_wave(1.0, 0.0, -LAMBDA, phi, psi, xy_in);
add_circular_wave(1.0, -LAMBDA, 0.0, phi, psi, xy_in);
}
glutSwapBuffers();
@ -411,7 +466,9 @@ void animation()
if ((i >= INITIAL_TIME)&&(DOUBLE_MOVIE))
{
draw_wave(phi, psi, xy_in, scale, i, PLOT_B);
// draw_wave(phi, psi, xy_in, scale, i, PLOT_B);
draw_wave_e(phi, psi, total_energy, xy_in, scale, i, PLOT_B);
if (DRAW_COLOR_SCHEME) draw_color_scheme(1.7, YMIN + 0.1, 1.9, YMAX - 0.1, PLOT_B, -12.0, 12.0);
draw_billiard();
glutSwapBuffers();
save_frame_counter(NSTEPS + 21 + counter);
@ -434,14 +491,16 @@ void animation()
{
if (DOUBLE_MOVIE)
{
draw_wave(phi, psi, xy_in, scale, i, PLOT);
// draw_wave(phi, psi, xy_in, scale, i, PLOT);
draw_wave_e(phi, psi, total_energy, xy_in, scale, NSTEPS, PLOT);
draw_billiard();
glutSwapBuffers();
}
for (i=0; i<MID_FRAMES; i++) save_frame();
if (DOUBLE_MOVIE)
{
draw_wave(phi, psi, xy_in, scale, i, PLOT_B);
// draw_wave(phi, psi, xy_in, scale, i, PLOT_B);
draw_wave_e(phi, psi, total_energy, xy_in, scale, NSTEPS, PLOT_B);
draw_billiard();
glutSwapBuffers();
// for (i=0; i<END_FRAMES; i++) save_frame_counter(NSTEPS + MID_FRAMES + 1 + counter + i);
@ -456,8 +515,16 @@ void animation()
free(psi[i]);
free(phi_tmp[i]);
free(psi_tmp[i]);
free(total_energy[i]);
free(xy_in[i]);
}
if (SAVE_TIME_SERIES)
{
fclose(time_series_left);
fclose(time_series_right);
}
}

View File

@ -94,6 +94,28 @@ void init_wave_plus(double x, double y, double *phi[NX], double *psi[NX], short
}
}
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<NX; i++)
for (j=0; j<NY; j++)
{
ij_to_xy(i, j, xy);
if (xy[0] < 0.0) dist2 = (xy[0]-xleft)*(xy[0]-xleft) + (xy[1]-yleft)*(xy[1]-yleft);
else dist2 = (xy[0]-xright)*(xy[0]-xright) + (xy[1]-yright)*(xy[1]-yright);
xy_in[i][j] = xy_in_billiard(xy[0],xy[1]);
if ((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_planar_wave(double x, double y, double *phi[NX], double *psi[NX], short int * xy_in[NX])
/* initialise field with drop at (x,y) - phi is wave height, psi is phi at time t-1 */
/* beta version, works for vertical planar wave only so far */
@ -339,7 +361,10 @@ void draw_wave_e(double *phi[NX], double *psi[NX], double *total_energy[NX], sho
}
case (P_ENERGY):
{
color_scheme(COLOR_SCHEME, compute_energy(phi, psi, xy_in, i, j), scale, time, rgb);
energy = compute_energy(phi, psi, xy_in, i, j);
/* adjust energy to color palette */
if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, energy, scale, time, rgb);
else color_scheme(COLOR_SCHEME, energy, scale, time, rgb);
break;
}
case (P_MIXED):
@ -352,7 +377,9 @@ void draw_wave_e(double *phi[NX], double *psi[NX], double *total_energy[NX], sho
{
energy = compute_energy(phi, psi, xy_in, i, j);
total_energy[i][j] += energy;
color_scheme(COLOR_SCHEME, total_energy[i][j]/(double)(time+1), scale, time, rgb);
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;
}
}
@ -369,6 +396,59 @@ void draw_wave_e(double *phi[NX], double *psi[NX], double *total_energy[NX], sho
}
void draw_color_scheme(double x1, double y1, double x2, double y2, int plot, double min, double max)
{
int j, ij_botleft[2], ij_topright[2], imin, imax, jmin, jmax;
double y, dy, dy_e, rgb[3], value;
xy_to_ij(x1, y1, ij_botleft);
xy_to_ij(x2, y2, ij_topright);
imin = ij_botleft[0];
imax = ij_topright[0];
jmin = ij_botleft[1];
jmax = ij_topright[1];
glBegin(GL_QUADS);
dy = (max - min)/((double)(jmax - jmin));
dy_e = max/((double)(jmax - jmin));
for (j = jmin; j < jmax; j++)
{
switch (plot) {
case (P_AMPLITUDE):
{
value = min + 1.0*dy*(double)(j - jmin);
color_scheme(COLOR_SCHEME, value, 1.0, 1, rgb);
break;
}
case (P_ENERGY):
{
value = dy_e*(double)(j - jmin);
if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, value, 1.0, 1, rgb);
else color_scheme(COLOR_SCHEME, value, 1.0, 1, rgb);
break;
}
case (P_MEAN_ENERGY):
{
value = dy_e*(double)(j - jmin);
if (COLOR_PALETTE >= COL_TURBO) color_scheme_asym(COLOR_SCHEME, value, 1.0, 1, rgb);
else color_scheme(COLOR_SCHEME, value, 1.0, 1, rgb);
break;
}
}
glColor3f(rgb[0], rgb[1], rgb[2]);
glVertex2i(imin, j);
glVertex2i(imax, j);
glVertex2i(imax, j+1);
glVertex2i(imin, j+1);
}
glEnd ();
glColor3f(1.0, 1.0, 1.0);
draw_rectangle(x1, y1, x2, y2);
}

View File

@ -81,6 +81,17 @@
#define NGRIDX 20 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard below */
@ -133,9 +144,11 @@
/* Parameters of initial condition */
#define INITIAL_AMP 0.2 /* amplitude of initial condition */
#define INITIAL_VARIANCE 0.002 /* variance of initial condition */
#define INITIAL_WAVELENGTH 0.1 /* wavelength of initial condition */
#define INITIAL_AMP 0.75 /* amplitude of initial condition */
// #define INITIAL_VARIANCE 0.0003 /* variance of initial condition */
// #define INITIAL_WAVELENGTH 0.015 /* wavelength of initial condition */
#define INITIAL_VARIANCE 0.0003 /* variance of initial condition */
#define INITIAL_WAVELENGTH 0.02 /* wavelength of initial condition */
/* Plot type, see list in global_pdes.c */
@ -143,7 +156,7 @@
/* Color schemes */
#define COLOR_PALETTE 0 /* Color palette, see list in global_pdes.c */
#define COLOR_PALETTE 0 /* Color palette, see list in global_pdes.c */
#define BLACK 1 /* background */
@ -166,8 +179,6 @@
#define VMAX 5.0 /* max value of wave amplitude */
#include "hsluv.c"
#include "global_pdes.c" /* constants and global variables */
#include "sub_wave.c" /* common functions for wave_billiard, heat and schrodinger */
#include "wave_common.c" /* common functions for wave_billiard, wave_comparison, etc */

View File

@ -50,23 +50,23 @@
#define NX 1280 /* number of grid points on x axis */
#define NY 720 /* number of grid points on y axis */
#define XMIN -1.777777778
#define XMAX 1.777777778 /* x interval */
#define YMIN -1.0
#define YMAX 1.0 /* y interval for 9/16 aspect ratio */
// #define XMIN -2.0
// #define XMAX 2.0 /* x interval */
// #define YMIN -1.125
// #define YMAX 1.125 /* y interval for 9/16 aspect ratio */
// #define XMIN -1.777777778
// #define XMAX 1.777777778 /* x interval */
// #define YMIN -1.0
// #define YMAX 1.0 /* y interval for 9/16 aspect ratio */
#define XMIN -2.0
#define XMAX 2.0 /* x interval */
#define YMIN -1.125
#define YMAX 1.125 /* y interval for 9/16 aspect ratio */
#define JULIA_SCALE 1.0 /* scaling for Julia sets */
/* Choice of the billiard table */
#define B_DOMAIN 15 /* choice of domain shape, see list in global_pdes.c */
#define B_DOMAIN_B 15 /* choice of domain shape, see list in global_pdes.c */
#define B_DOMAIN 20 /* choice of domain shape, see list in global_pdes.c */
#define B_DOMAIN_B 20 /* choice of domain shape, see list in global_pdes.c */
#define CIRCLE_PATTERN 2 /* pattern of circles, see list in global_pdes.c */
#define CIRCLE_PATTERN 1 /* pattern of circles, see list in global_pdes.c */
#define CIRCLE_PATTERN_B 11 /* pattern of circles, see list in global_pdes.c */
#define P_PERCOL 0.25 /* probability of having a circle in C_RAND_PERCOL arrangement */
@ -85,6 +85,17 @@
#define NGRIDX 15 /* number of grid point for grid of disks */
#define NGRIDY 20 /* number of grid point for grid of disks */
#define X_SHOOTER -0.2
#define Y_SHOOTER -0.6
#define X_TARGET 0.4
#define Y_TARGET 0.7 /* shooter and target positions in laser fight */
#define ISO_XSHIFT_LEFT -1.65
#define ISO_XSHIFT_RIGHT 0.4
#define ISO_YSHIFT_LEFT -0.05
#define ISO_YSHIFT_RIGHT -0.05
#define ISO_SCALE 0.85 /* coordinates for isospectral billiards */
/* You can add more billiard tables by adapting the functions */
/* xy_in_billiard and draw_billiard below */
@ -98,14 +109,8 @@
#define AMPLITUDE 0.025 /* amplitude of periodic excitation */
#define COURANT 0.02 /* Courant number */
#define COURANTB 0.004 /* Courant number in medium B */
// #define COURANTB 0.005 /* Courant number in medium B */
// #define COURANTB 0.008 /* Courant number in medium B */
#define GAMMA 0.0 /* damping factor in wave equation */
// #define GAMMA 1.0e-8 /* damping factor in wave equation */
#define GAMMAB 1.0e-8 /* damping factor in wave equation */
// #define GAMMAB 1.0e-6 /* damping factor in wave equation */
// #define GAMMAB 2.0e-4 /* damping factor in wave equation */
// #define GAMMAB 2.5e-4 /* damping factor in wave equation */
#define GAMMA_SIDES 1.0e-4 /* damping factor on boundary */
#define GAMMA_TOPBOT 1.0e-6 /* damping factor on boundary */
#define KAPPA 0.0 /* "elasticity" term enforcing oscillations */
@ -122,7 +127,7 @@
/* Parameters for length and speed of simulation */
#define NSTEPS 4500 /* number of frames of movie */
#define NSTEPS 3750 /* number of frames of movie */
#define NVID 25 /* number of iterations between images displayed on screen */
#define NSEG 100 /* number of segments of boundary */
#define INITIAL_TIME 200 /* time after which to start saving frames */
@ -170,8 +175,6 @@
#define VMAX 5.0 /* max value of wave amplitude */
#include "hsluv.c"
#include "global_pdes.c" /* constants and global variables */
#include "sub_wave.c" /* common functions for wave_billiard, heat and schrodinger */
#include "wave_common.c" /* common functions for wave_billiard, wave_comparison, etc */