/* nag_mesh2d_delaunay (d06abc) Example Program.
 *
 * Copyright 2017 Numerical Algorithms Group.
 *
 * Mark 26.1, 2017.
 */

#include <stdio.h>
#include <nag.h>
#include <nag_stdlib.h>
#include <nagd06.h>

#define EDGE(I, J) edge[3*((J) -1)+(I) -1]
#define CONN(I, J) conn[3*((J) -1)+(I) -1]
#define COOR(I, J) coor[2*((J) -1)+(I) -1]

int main(void)
{
  const Integer nvmax = 6000, nvint = 40;
  double dnvint;
  Integer exit_status, i, itrace, j, k, nedge, nelt,
    npropa, nv, nvb, reftk, i1, nearest, nv_near, nelt_near;
  NagError fail;
  char pmesh[2];
  double *coor = 0, *weight = 0;
  Integer *conn = 0, *edge = 0;

  INIT_FAIL(fail);

  exit_status = 0;

  printf("nag_mesh2d_delaunay (d06abc) Example Program Results\n\n");

  /* Skip heading in data file */
  scanf("%*[^\n] ");

  /* Reading of the geometry */
  scanf("%" NAG_IFMT "%" NAG_IFMT "%*[^\n] ", &nvb, &nedge);

  if (nvb > nvmax) {
    printf("Problem with the array dimensions\n");
    printf(" nvb nvmax %6" NAG_IFMT "%6" NAG_IFMT "\n", nvb, nvmax);
    printf(" Please increase the value of nvmax\n");
    exit_status = -1;
    goto END;
  }

  /* Allocate memory */

  if (!(coor = NAG_ALLOC(2 * nvmax, double)) ||
      !(weight = NAG_ALLOC(nvint, double)) ||
      !(conn = NAG_ALLOC(3 * (2 * nvmax + 5), Integer)) ||
      !(edge = NAG_ALLOC(3 * nedge, Integer)))
  {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

  /* Coordinates of the boundary mesh vertices and boundary edges */

  for (i = 1; i <= nvb; ++i) {
    scanf("%" NAG_IFMT "", &i1);
    scanf("%lf", &COOR(1, i1));
    scanf("%lf", &COOR(2, i1));
    scanf("%*[^\n] ");
  }

  for (i = 1; i <= nedge; ++i) {
    scanf("%" NAG_IFMT "", &i1);
    scanf("%" NAG_IFMT "", &EDGE(1, i1));
    scanf("%" NAG_IFMT "", &EDGE(2, i1));
    scanf("%" NAG_IFMT "", &EDGE(3, i1));
    scanf("%*[^\n] ");
  }
  scanf(" ' %1s '%*[^\n]", pmesh);

  /* Initialize mesh control parameters */

  itrace = 0;

  /* Generation of interior vertices on the RAE airfoils wake */

  dnvint = 2.5 / (double) (nvint + 1);

  for (i = 1; i <= nvint; ++i) {
    i1 = nvb + i;
    COOR(1, i1) = (double) i *dnvint + 1.38;
    COOR(2, i1) = -0.27 * COOR(1, i1) + 0.2;
    weight[i - 1] = 0.01;
  }

  /* Loop on the propagation coef */

  nearest = 250;
  for (j = 0; j < 4; ++j) {
    switch (j) {
    case 0:
      npropa = -5;
      break;
    case 1:
      npropa = -1;
      break;
    case 2:
      npropa = 1;
      break;
    default:
      npropa = 5;
    }

    /* Call to the 2D Delaunay-Voronoi mesh generator */

    /* nag_mesh2d_delaunay (d06abc).
     * Generates a two-dimensional mesh using a Delaunay-Voronoi
     * process
     */
    nag_mesh2d_delaunay(nvb, nvint, nvmax, nedge, edge, &nv, &nelt, coor,
                        conn, weight, npropa, itrace, 0, &fail);

    if (fail.code == NE_NOERROR) {
      if (pmesh[0] == 'N') {
        printf(" Mesh characteristics with npropa =%6" NAG_IFMT "\n", npropa);
        nv_near = ((nv+nearest/2)/nearest)*nearest;
        nelt_near = ((nelt+nearest/2)/nearest)*nearest;
        printf(" nv   =%10" NAG_IFMT " to the nearest %3" NAG_IFMT "\n",
               nv_near, nearest);
        printf(" nelt =%10" NAG_IFMT " to the nearest %3" NAG_IFMT "\n",
               nelt_near, nearest);
      }
      else if (pmesh[0] == 'Y') {
        /* Output the mesh in a form suitable for printing */

        printf(" %10" NAG_IFMT " %10" NAG_IFMT "\n", nv, nelt);

        for (i = 1; i <= nv; ++i) {
          printf("  %15.6e  %15.6e  \n", COOR(1, i), COOR(2, i));
        }

        reftk = 0;
        for (k = 1; k <= nelt; ++k) {
          printf(" %10" NAG_IFMT " %10" NAG_IFMT " %10" NAG_IFMT ""
                 " %10" NAG_IFMT "\n", CONN(1, k), CONN(2, k),
                 CONN(3, k), reftk);
        }
      }
      else {
        printf("Problem with the printing option Y or N\n");
        exit_status = -1;
        goto END;
      }
    }
    else {
      printf("Error from nag_mesh2d_delaunay (d06abc).\n%s\n", fail.message);
      exit_status = 1;
      goto END;
    }
  }

END:
  NAG_FREE(coor);
  NAG_FREE(weight);
  NAG_FREE(conn);
  NAG_FREE(edge);

  return exit_status;
}