int main ( ) /******************************************************************************/ /* Purpose: FD1D_ADVECTION_FTCS solves the advection equation using the FTCS method. Discussion: The FTCS method is unstable for the advection problem. Given a smooth initial condition, successive FTCS approximations will exhibit erroneous oscillations of increasing magnitude. Licensing: This code is distributed under the GNU LGPL license. Modified: 25 December 2012 Author: John Burkardt */ { double a; double b; double c; char command_filename[] = "advection_commands.txt"; FILE *command_unit; char data_filename[] = "advection_data.txt"; FILE *data_unit; double dt; double dx; int i; int j; int jm1; int jp1; int nx; int nt; int nt_step; int plotstep; double t; double *u; double *unew; double *x; timestamp ( ); printf ( "\n" ); printf ( "FD1D_ADVECTION_FTCS:\n" ); printf ( " C version\n" ); printf ( "\n" ); printf ( " Solve the constant-velocity advection equation in 1D,\n" ); printf ( " du/dt = - c du/dx\n" ); printf ( " over the interval:\n" ); printf ( " 0.0 <= x <= 1.0\n" ); printf ( " with periodic boundary conditions, and\n" ); printf ( " with a given initial condition\n" ); printf ( " u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" ); printf ( " = 0 elsewhere.\n" ); printf ( "\n" ); printf ( " We use a method known as FTCS:\n" ); printf ( " FT: Forward Time : du/dt = (u(t+dt,x)-u(t,x))/dt\n" ); printf ( " CS: Centered Space: du/dx = (u(t,x+dx)-u(t,x-dx))/2/dx\n" ); nx = 101; dx = 1.0 / ( double ) ( nx - 1 ); a = 0.0; b = 1.0; x = r8vec_linspace_new ( nx, a, b ); nt = 1000; dt = 1.0 / ( double ) ( nt ); c = 1.0; u = initial_condition ( nx, x ); /* Open data file, and write solutions as they are computed. */ data_unit = fopen ( data_filename, "wt" ); t = 0.0; fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[0], t, u[0] ); for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = 100; printf ( "\n" ); printf ( " Number of nodes NX = %d\n", nx ); printf ( " Number of time steps NT = %d\n", nt ); printf ( " Constant velocity C = %g\n", c ); unew = ( double * ) malloc ( nx * sizeof ( double ) ); for ( i = 0; i < nt; i++ ) { for ( j = 0; j < nx; j++ ) { jm1 = i4_wrap ( j - 1, 0, nx - 1 ); jp1 = i4_wrap ( j + 1, 0, nx - 1 ); unew[j] = u[j] - c * dt / dx / 2.0 * ( u[jp1] - u[jm1] ); } for ( j = 0; j < nx; j++ ) { u[j] = unew[j]; } if ( i == nt_step - 1 ) { t = ( double ) ( i ) * dt; for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = nt_step + 100; } } /* Close the data file once the computation is done. */ fclose ( data_unit ); printf ( "\n" ); printf ( " Plot data written to the file \"%s\"\n", data_filename ); /* Write gnuplot command file. */ command_unit = fopen ( command_filename, "wt" ); fprintf ( command_unit, "set term png\n" ); fprintf ( command_unit, "set output 'advection.png'\n" ); fprintf ( command_unit, "set grid\n" ); fprintf ( command_unit, "set style data lines\n" ); fprintf ( command_unit, "unset key\n" ); fprintf ( command_unit, "set xlabel '<---X--->'\n"); fprintf ( command_unit, "set ylabel '<---Time--->'\n" ); fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename ); fprintf ( command_unit, "quit\n" ); fclose ( command_unit ); printf ( " Gnuplot command data written to the file \"%s\"\n", command_filename ); /* Free memory. */ free ( u ); free ( unew ); free ( x ); /* Terminate. */ printf ( "\n" ); printf ( "FD1D_ADVECTION_FTCS\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
int main ( ) /******************************************************************************/ /* Purpose: FD1D_ADVECTION_LAX_WENDROFF: advection equation using Lax-Wendroff method. Licensing: This code is distributed under the GNU LGPL license. Modified: 11 March 2013 Author: John Burkardt */ { double a; double b; double c; double c1; double c2; char command_filename[] = "advection_commands.txt"; FILE *command_unit; char data_filename[] = "advection_data.txt"; FILE *data_unit; double dt; double dx; int i; int j; int jm1; int jp1; int nx; int nt; int nt_step; int plotstep; double t; double *u; double *unew; double *x; timestamp ( ); printf ( "\n" ); printf ( "FD1D_ADVECTION_LAX_WENDROFF:\n" ); printf ( " C version\n" ); printf ( "\n" ); printf ( " Solve the constant-velocity advection equation in 1D,\n" ); printf ( " du/dt = - c du/dx\n" ); printf ( " over the interval:\n" ); printf ( " 0.0 <= x <= 1.0\n" ); printf ( " with periodic boundary conditions, and\n" ); printf ( " with a given initial condition\n" ); printf ( " u(0,x) = (10x-4)^2 (6-10x)^2 for 0.4 <= x <= 0.6\n" ); printf ( " = 0 elsewhere.\n" ); printf ( "\n" ); printf ( " We modify the FTCS method using the Lax-Wendroff method:\n" ); nx = 101; dx = 1.0 / ( double ) ( nx - 1 ); a = 0.0; b = 1.0; x = r8vec_linspace_new ( nx, a, b ); nt = 1000; dt = 1.0 / ( double ) ( nt ); c = 1.0; c1 = 0.5 * c * dt / dx; c2 = 0.5 * pow ( c * dt / dx, 2 ); u = initial_condition ( nx, x ); /* Open data file, and write solutions as they are computed. */ data_unit = fopen ( data_filename, "wt" ); t = 0.0; fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[0], t, u[0] ); for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = 100; printf ( "\n" ); printf ( " Number of nodes NX = %d\n", nx ); printf ( " Number of time steps NT = %d\n", nt ); printf ( " Constant velocity C = %g\n", c ); printf ( " CFL condition: dt (%g) <= dx / c (%g)\n", dt, dx / c ); unew = ( double * ) malloc ( nx * sizeof ( double ) ); for ( i = 0; i < nt; i++ ) { for ( j = 0; j < nx; j++ ) { jm1 = i4_wrap ( j - 1, 0, nx - 1 ); jp1 = i4_wrap ( j + 1, 0, nx - 1 ); unew[j] = u[j] - c1 * ( u[jp1] - u[jm1] ) + c2 * ( u[jp1] - 2.0 * u[j] + u[jm1] ); } for ( j = 0; j < nx; j++ ) { u[j] = unew[j]; } if ( i == nt_step - 1 ) { t = ( double ) ( i ) * dt; for ( j = 0; j < nx; j++ ) { fprintf ( data_unit, "%10.4f %10.4f %10.4f\n", x[j], t, u[j] ); } fprintf ( data_unit, "\n" ); nt_step = nt_step + 100; } } /* Close the data file once the computation is done. */ fclose ( data_unit ); printf ( "\n" ); printf ( " Plot data written to the file \"%s\"\n", data_filename ); /* Write gnuplot command file. */ command_unit = fopen ( command_filename, "wt" ); fprintf ( command_unit, "set term png\n" ); fprintf ( command_unit, "set output 'advection_lax_wendroff.png'\n" ); fprintf ( command_unit, "set grid\n" ); fprintf ( command_unit, "set style data lines\n" ); fprintf ( command_unit, "unset key\n" ); fprintf ( command_unit, "set xlabel '<---X--->'\n"); fprintf ( command_unit, "set ylabel '<---Time--->'\n" ); fprintf ( command_unit, "splot '%s' using 1:2:3 with lines\n", data_filename ); fprintf ( command_unit, "quit\n" ); fclose ( command_unit ); printf ( " Gnuplot command data written to the file \"%s\"\n", command_filename ); /* Free memory. */ free ( u ); free ( unew ); free ( x ); /* Terminate. */ printf ( "\n" ); printf ( "FD1D_ADVECTION_LAX_WENDROFF\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
void vbedg ( double x, double y, int point_num, double point_xy[], int tri_num, int tri_vert[], int tri_nabe[], int *ltri, int *ledg, int *rtri, int *redg ) { int a; double ax; double ay; int b; double bx; double by; bool done; int e; int l; int lr; int t; // // Find the rightmost visible boundary edge using links, then possibly // leftmost visible boundary edge using triangle neighbor information. // if ( *ltri == 0 ) { done = false; *ltri = *rtri; *ledg = *redg; } else { done = true; } for ( ; ; ) { l = -tri_nabe[3*((*rtri)-1)+(*redg)-1]; t = l / 3; e = 1 + l % 3; a = tri_vert[3*(t-1)+e-1]; if ( e <= 2 ) { b = tri_vert[3*(t-1)+e]; } else { b = tri_vert[3*(t-1)+0]; } ax = point_xy[2*(a-1)+0]; ay = point_xy[2*(a-1)+1]; bx = point_xy[2*(b-1)+0]; by = point_xy[2*(b-1)+1]; lr = lrline ( x, y, ax, ay, bx, by, 0.0 ); if ( lr <= 0 ) { break; } *rtri = t; *redg = e; } if ( done ) { return; } t = *ltri; e = *ledg; for ( ; ; ) { b = tri_vert[3*(t-1)+e-1]; e = i4_wrap ( e-1, 1, 3 ); while ( 0 < tri_nabe[3*(t-1)+e-1] ) { t = tri_nabe[3*(t-1)+e-1]; if ( tri_vert[3*(t-1)+0] == b ) { e = 3; } else if ( tri_vert[3*(t-1)+1] == b ) { e = 1; } else { e = 2; } } a = tri_vert[3*(t-1)+e-1]; ax = point_xy[2*(a-1)+0]; ay = point_xy[2*(a-1)+1]; bx = point_xy[2*(b-1)+0]; by = point_xy[2*(b-1)+1]; lr = lrline ( x, y, ax, ay, bx, by, 0.0 ); if ( lr <= 0 ) { break; } } *ltri = t; *ledg = e; return; }
void triangle_nco_rule ( int rule, int order_num, double xy[], double w[] ) /******************************************************************************/ /* Purpose: TRIANGLE_NCO_RULE returns the points and weights of an NCO rule. Licensing: This code is distributed under the GNU LGPL license. Modified: 30 January 2007 Author: John Burkardt Reference: Peter Silvester, Symmetric Quadrature Formulae for Simplexes, Mathematics of Computation, Volume 24, Number 109, January 1970, pages 95-100. Parameters: Input, int RULE, the index of the rule. Input, int ORDER_NUM, the order (number of points) of the rule. Output, double XY[2*ORDER_NUM], the points of the rule. Output, double W[ORDER_NUM], the weights of the rule. */ { int k; int o; int s; int *suborder; int suborder_num; double *suborder_w; double *suborder_xyz; /* Get the suborder information. */ suborder_num = triangle_nco_suborder_num ( rule ); suborder_xyz = ( double * ) malloc ( 3 * suborder_num * sizeof ( double ) ); suborder_w = ( double * ) malloc ( suborder_num * sizeof ( double ) ); suborder = triangle_nco_suborder ( rule, suborder_num ); triangle_nco_subrule ( rule, suborder_num, suborder_xyz, suborder_w ); /* Expand the suborder information to a full order rule. */ o = 0; for ( s = 0; s < suborder_num; s++ ) { if ( suborder[s] == 1 ) { xy[0+o*2] = suborder_xyz[0+s*3]; xy[1+o*2] = suborder_xyz[1+s*3]; w[o] = suborder_w[s]; o = o + 1; } else if ( suborder[s] == 3 ) { for ( k = 0; k < 3; k++ ) { xy[0+o*2] = suborder_xyz [ i4_wrap(k, 0,2) + s*3 ]; xy[1+o*2] = suborder_xyz [ i4_wrap(k+1,0,2) + s*3 ]; w[o] = suborder_w[s]; o = o + 1; } } else if ( suborder[s] == 6 ) { for ( k = 0; k < 3; k++ ) { xy[0+o*2] = suborder_xyz [ i4_wrap(k, 0,2) + s*3 ]; xy[1+o*2] = suborder_xyz [ i4_wrap(k+1,0,2) + s*3 ]; w[o] = suborder_w[s]; o = o + 1; } for ( k = 0; k < 3; k++ ) { xy[0+o*2] = suborder_xyz [ i4_wrap(k+1,0,2) + s*3 ]; xy[1+o*2] = suborder_xyz [ i4_wrap(k, 0,2) + s*3 ]; w[o] = suborder_w[s]; o = o + 1; } } else { fprintf ( stderr, "\n" ); fprintf ( stderr, "TRIANGLE_NCO_RULE - Fatal error!\n" ); fprintf ( stderr, " Illegal SUBORDER(%d) = %d\n", s, suborder[s] ); exit ( 1 ); } } free ( suborder ); free ( suborder_xyz ); free ( suborder_w ); return; }
int swapec ( int i, int *top, int *btri, int *bedg, int point_num, double point_xy[], int tri_num, int tri_vert[], int tri_nabe[], int stack[] ) { int a; int b; int c; int e; int ee; int em1; int ep1; int f; int fm1; int fp1; int l; int r; int s; int swap; int t; int tt; int u; double x; double y; // // Determine whether triangles in stack are Delaunay, and swap // diagonal edge of convex quadrilateral if not. // x = point_xy[2*(i-1)+0]; y = point_xy[2*(i-1)+1]; for ( ; ; ) { if ( *top <= 0 ) { break; } t = stack[(*top)-1]; *top = *top - 1; if ( tri_vert[3*(t-1)+0] == i ) { e = 2; b = tri_vert[3*(t-1)+2]; } else if ( tri_vert[3*(t-1)+1] == i ) { e = 3; b = tri_vert[3*(t-1)+0]; } else { e = 1; b = tri_vert[3*(t-1)+1]; } a = tri_vert[3*(t-1)+e-1]; u = tri_nabe[3*(t-1)+e-1]; if ( tri_nabe[3*(u-1)+0] == t ) { f = 1; c = tri_vert[3*(u-1)+2]; } else if ( tri_nabe[3*(u-1)+1] == t ) { f = 2; c = tri_vert[3*(u-1)+0]; } else { f = 3; c = tri_vert[3*(u-1)+1]; } swap = diaedg ( x, y, point_xy[2*(a-1)+0], point_xy[2*(a-1)+1], point_xy[2*(c-1)+0], point_xy[2*(c-1)+1], point_xy[2*(b-1)+0], point_xy[2*(b-1)+1] ); if ( swap == 1 ) { em1 = i4_wrap ( e - 1, 1, 3 ); ep1 = i4_wrap ( e + 1, 1, 3 ); fm1 = i4_wrap ( f - 1, 1, 3 ); fp1 = i4_wrap ( f + 1, 1, 3 ); tri_vert[3*(t-1)+ep1-1] = c; tri_vert[3*(u-1)+fp1-1] = i; r = tri_nabe[3*(t-1)+ep1-1]; s = tri_nabe[3*(u-1)+fp1-1]; tri_nabe[3*(t-1)+ep1-1] = u; tri_nabe[3*(u-1)+fp1-1] = t; tri_nabe[3*(t-1)+e-1] = s; tri_nabe[3*(u-1)+f-1] = r; if ( 0 < tri_nabe[3*(u-1)+fm1-1] ) { *top = *top + 1; stack[(*top)-1] = u; } if ( 0 < s ) { if ( tri_nabe[3*(s-1)+0] == u ) { tri_nabe[3*(s-1)+0] = t; } else if ( tri_nabe[3*(s-1)+1] == u ) { tri_nabe[3*(s-1)+1] = t; } else { tri_nabe[3*(s-1)+2] = t; } *top = *top + 1; if ( point_num < *top ) { return 8; } stack[(*top)-1] = t; } else { if ( u == *btri && fp1 == *bedg ) { *btri = t; *bedg = e; } l = - ( 3 * t + e - 1 ); tt = t; ee = em1; while ( 0 < tri_nabe[3*(tt-1)+ee-1] ) { tt = tri_nabe[3*(tt-1)+ee-1]; if ( tri_vert[3*(tt-1)+0] == a ) { ee = 3; } else if ( tri_vert[3*(tt-1)+1] == a ) { ee = 1; } else { ee = 2; } } tri_nabe[3*(tt-1)+ee-1] = l; } if ( 0 < r ) { if ( tri_nabe[3*(r-1)+0] == t ) { tri_nabe[3*(r-1)+0] = u; } else if ( tri_nabe[3*(r-1)+1] == t ) { tri_nabe[3*(r-1)+1] = u; } else { tri_nabe[3*(r-1)+2] = u; } } else { if ( t == *btri && ep1 == *bedg ) { *btri = u; *bedg = f; } l = - ( 3 * u + f - 1 ); tt = u; ee = fm1; while ( 0 < tri_nabe[3*(tt-1)+ee-1] ) { tt = tri_nabe[3*(tt-1)+ee-1]; if ( tri_vert[3*(tt-1)+0] == b ) { ee = 3; } else if ( tri_vert[3*(tt-1)+1] == b ) { ee = 1; } else { ee = 2; } } tri_nabe[3*(tt-1)+ee-1] = l; } } } return 0; }