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;
}