/* nag_mesh2d_join (d06dbc) Example Program.
 *
 * Copyright 2017 Numerical Algorithms Group.
 *
 * Mark 26.1, 2017.
 */

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

#ifdef __cplusplus
extern "C"
{
#endif
  static double NAG_CALL fbnd(Integer, double, double, Nag_Comm *);
#ifdef __cplusplus
}
#endif

static int ex1(void);
static int ex2(void);

#define EDGE1(I, J)  edge1[3*((J) -1)+(I) -1]
#define EDGE2(I, J)  edge2[3*((J) -1)+(I) -1]
#define EDGE3(I, J)  edge3[3*((J) -1)+(I) -1]
#define EDGE5(I, J)  edge5[3*((J) -1)+(I) -1]
#define CONN1(I, J)  conn1[3*((J) -1)+(I) -1]
#define CONN3(I, J)  conn3[3*((J) -1)+(I) -1]
#define CONN5(I, J)  conn5[3*((J) -1)+(I) -1]
#define COOR1(I, J)  coor1[2*((J) -1)+(I) -1]
#define COOR3(I, J)  coor3[2*((J) -1)+(I) -1]
#define COOR5(I, J)  coor5[2*((J) -1)+(I) -1]
#define TRANS(I, J)  trans[6*((J) -1)+(I) -1]
#define LINED(I, J)  lined[4*((J) -1)+(I) -1]
#define COORCH(I, J) coorch[2*(J-1)+I-1]

int main(void)
{
  Integer exit_status_ex1 = 0;
  Integer exit_status_ex2 = 0;

  printf("nag_mesh2d_join (d06dbc) Example Program Results\n");
  exit_status_ex1 = ex1();
  exit_status_ex2 = ex2();

  return (exit_status_ex1 == 0 && exit_status_ex2 == 0) ? 0 : 1;
}

int ex1(void)
{
  const Integer nvmax = 900, nedmx = 200, neltmx = 2 * nvmax + 5, ntrans = 1,
         mode = 0;
  double eps;
  Integer exit_status, i, imax, itrace, itrans, jmax, jtrans, k, ktrans;
  Integer nedge1, nedge2, nedge3, nelt1, nelt2, nelt3, nv1, nv2, nv3, reftk;
  Integer imaxm1, jmaxm1, ind;
  char pmesh[2];
  double *coor1 = 0, *coor2 = 0, *coor3 = 0, *trans = 0;
  Integer *conn1 = 0, *conn2 = 0, *conn3 = 0, *edge1 = 0, *edge2 = 0;
  Integer *edge3 = 0, *itype = 0, *reft1 = 0, *reft2 = 0, *reft3 = 0;
  NagError fail;

  INIT_FAIL(fail);
  exit_status = 0;

  printf("\nExample 1\n\n");

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

  /* Read the mesh: coordinates and connectivity of the 1st domain */
  scanf("%" NAG_IFMT "", &nv1);
  scanf("%" NAG_IFMT "", &nelt1);
  scanf("%*[^\n] ");

  nv2 = nv1;
  nelt2 = nelt1;

  imax = 20;
  jmax = imax;
  imaxm1 = imax - 1;
  jmaxm1 = jmax - 1;
  nedge1 = 2 * (imaxm1 + jmaxm1);
  nedge2 = nedge1;

  /* Allocate memory */

  if (!(coor1 = NAG_ALLOC(2 * nv1, double)) ||
      !(coor2 = NAG_ALLOC(2 * nv2, double)) ||
      !(coor3 = NAG_ALLOC(2 * nvmax, double)) ||
      !(trans = NAG_ALLOC(6 * ntrans, double)) ||
      !(conn1 = NAG_ALLOC(3 * nelt1, Integer)) ||
      !(conn2 = NAG_ALLOC(3 * nelt2, Integer)) ||
      !(conn3 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(edge1 = NAG_ALLOC(3 * nedge1, Integer)) ||
      !(edge2 = NAG_ALLOC(3 * nedge2, Integer)) ||
      !(edge3 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(itype = NAG_ALLOC(ntrans, Integer)) ||
      !(reft1 = NAG_ALLOC(nelt1, Integer)) ||
      !(reft2 = NAG_ALLOC(nelt2, Integer)) ||
      !(reft3 = NAG_ALLOC(neltmx, Integer)))
  {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

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

  for (k = 1; k <= nelt1; ++k) {
    scanf("%" NAG_IFMT "", &CONN1(1, k));
    scanf("%" NAG_IFMT "", &CONN1(2, k));
    scanf("%" NAG_IFMT "", &CONN1(3, k));
    scanf("%" NAG_IFMT "", &reftk);
    scanf("%*[^\n] ");

    reft1[k - 1] = 1;
    reft2[k - 1] = 2;
  }
  scanf(" ' %1s '", pmesh);
  scanf("%*[^\n] ");

  /* the edges of the boundary */

  ind = 0;

  for (i = 1; i <= imaxm1; ++i) {
    ++ind;
    EDGE1(1, ind) = i;
    EDGE1(2, ind) = i + 1;
    EDGE1(3, ind) = 1;
  }

  for (i = 1; i <= jmaxm1; ++i) {
    ++ind;
    EDGE1(1, ind) = i * imax;
    EDGE1(2, ind) = (i + 1) * imax;
    EDGE1(3, ind) = 1;
  }

  for (i = 1; i <= imaxm1; ++i) {
    ++ind;
    EDGE1(1, ind) = imax * jmax - i + 1;
    EDGE1(2, ind) = imax * jmax - i;
    EDGE1(3, ind) = 1;
  }

  for (i = 1; i <= jmaxm1; ++i) {
    ++ind;
    EDGE1(1, ind) = (jmax - i) * imax + 1;
    EDGE1(2, ind) = (jmax - i - 1) * imax + 1;
    EDGE1(3, ind) = 1;
  }

  for (ktrans = 0; ktrans < 2; ++ktrans) {
    /* Translation of the 1st domain to obtain the 2nd domain */
    /* KTRANS = 0 leading to a domain overlapping */
    /* KTRANS = 1 leading to a domain partition */

    if (ktrans == 0) {
      itrans = imax - 5;
      jtrans = jmax - 3;
    }
    else {
      itrans = imax - 1;
      jtrans = 0;
    }

    itype[0] = 1;
    TRANS(1, 1) = (double) itrans / (imax - 1.0);
    TRANS(2, 1) = (double) jtrans / (jmax - 1.0);
    itrace = 0;

    /* nag_mesh2d_trans (d06dac).
     * Generates a mesh resulting from an affine transformation
     * of a given mesh
     */
    nag_mesh2d_trans(mode, nv2, nedge2, nelt2, ntrans, itype, trans, coor1,
                     edge1, conn1, coor2, edge2, conn2, itrace, 0, &fail);
    if (fail.code == NE_NOERROR) {
      for (i = 1; i <= nedge2; ++i)
        EDGE2(3, i) = 2;

      /* Call to the restitching driver */

      itrace = 0;
      eps = 0.01;

      /* nag_mesh2d_join (d06dbc).
       * Joins together two given adjacent (possibly overlapping)
       * meshes
       */
      nag_mesh2d_join(eps, nv1, nelt1, nedge1, coor1, edge1, conn1, reft1,
                      nv2, nelt2, nedge2, coor2, edge2, conn2, reft2, &nv3,
                      &nelt3, &nedge3, coor3, edge3, conn3, reft3, itrace,
                      0, &fail);
      if (fail.code == NE_NOERROR) {
        if (pmesh[0] == 'N') {
          if (ktrans == 0) {
            printf("The restitched mesh characteristics\n");
            printf("in the overlapping case\n");
          }
          else {
            printf("in the partition case\n");
          }
          printf(" nv    =%6" NAG_IFMT "\n", nv3);
          printf(" nelt  =%6" NAG_IFMT "\n", nelt3);
          printf(" nedge =%6" NAG_IFMT "\n", nedge3);
        }
        else if (pmesh[0] == 'Y') {
          /* Output the mesh to view it using the
             NAG Graphics Library */

          printf(" %10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "\n", nv3,
                 nelt3, nedge3);

          for (i = 1; i <= nv3; ++i)
            printf("  %15.6e  %15.6e\n", COOR3(1, i), COOR3(2, i));

          for (k = 1; k <= nelt3; ++k)
            printf(" %10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT ""
                   "%10" NAG_IFMT "\n", CONN3(1, k), CONN3(2, k),
                   CONN3(3, k), reft3[k - 1]);

          for (k = 1; k <= nedge3; ++k)
            printf(" %10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "\n",
                   EDGE3(1, k), EDGE3(2, k), EDGE3(3, k));
        }
        else {
          printf("Problem with the printing option Y or N\n");
          exit_status = -1;
          goto END;
        }
      }
      else {
        printf("Error from nag_mesh2d_join (d06dbc).\n%s\n", fail.message);
        exit_status = 1;
        goto END;
      }
    }
    else {
      printf("Error from nag_mesh2d_trans (d06dac).\n%s\n", fail.message);
      exit_status = 1;
      goto END;
    }
  }

END:
  NAG_FREE(coor1);
  NAG_FREE(coor2);
  NAG_FREE(coor3);
  NAG_FREE(trans);
  NAG_FREE(conn1);
  NAG_FREE(conn2);
  NAG_FREE(conn3);
  NAG_FREE(edge1);
  NAG_FREE(edge2);
  NAG_FREE(edge3);
  NAG_FREE(itype);
  NAG_FREE(reft1);
  NAG_FREE(reft2);
  NAG_FREE(reft3);

  return exit_status;
}

int ex2(void)
{
  const Integer nvmax = 900, nedmx = 200, neltmx = 2 * nvmax + 5,
         ntrans = 1, nus = 0, nvint = 0, nvfix = 0;
  static double ruser[1] = { -1.0 };
  double eps;
  Integer exit_status, i, itrace, j, k, l, ncomp, nedge1, nedge2, nedge3;
  Integer nedge4, nedge5, nelt1, nelt2, nelt3, nelt4, nelt5, nlines;
  Integer npropa, nqint, nv1, nv2, nv3, nv4, nv5, nvb1, nvb2, mode;
  char pmesh[2];
  double *coor1 = 0, *coor2 = 0, *coor3 = 0, *coor4 = 0, *coor5 = 0;
  double *coorch = 0, *coorus = 0, *rate = 0, *trans = 0, *weight = 0;
  Integer *conn1 = 0, *conn2 = 0, *conn3 = 0, *conn4 = 0, *conn5 = 0;
  Integer *edge1 = 0, *edge2 = 0, *edge3 = 0, *edge4 = 0, *edge5 = 0;
  Integer *itype = 0, *lcomp = 0, *lined = 0, *nlcomp = 0, *numfix = 0;
  Integer *reft1 = 0, *reft2 = 0, *reft3 = 0, *reft4 = 0, *reft5 = 0;
  NagError fail;
  Nag_Comm comm;

  INIT_FAIL(fail);

  /* For communication with user-supplied functions: */
  comm.user = ruser;

  exit_status = 0;

  printf("\nExample 2\n\n");

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

  /* Build the mesh of the 1st domain */
  /* Initialize boundary mesh inputs: */
  /* the number of line and of the characteristic points of */
  /* the boundary mesh */
  scanf("%" NAG_IFMT "", &nlines);
  scanf("%*[^\n] ");

  /* Allocate memory */

  if (!(coor1 = NAG_ALLOC(2 * nvmax, double)) ||
      !(coor2 = NAG_ALLOC(2 * nvmax, double)) ||
      !(coor3 = NAG_ALLOC(2 * nvmax, double)) ||
      !(coor4 = NAG_ALLOC(2 * nvmax, double)) ||
      !(coor5 = NAG_ALLOC(2 * nvmax, double)) ||
      !(coorch = NAG_ALLOC(2 * nlines, double)) ||
      !(coorus = NAG_ALLOC(1, double)) ||
      !(rate = NAG_ALLOC(nlines, double)) ||
      !(trans = NAG_ALLOC(6 * ntrans, double)) ||
      !(weight = NAG_ALLOC(1, double)) ||
      !(conn1 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(conn2 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(conn3 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(conn4 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(conn5 = NAG_ALLOC(3 * neltmx, Integer)) ||
      !(edge1 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(edge2 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(edge3 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(edge4 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(edge5 = NAG_ALLOC(3 * nedmx, Integer)) ||
      !(itype = NAG_ALLOC(ntrans, Integer)) ||
      !(lcomp = NAG_ALLOC(nlines, Integer)) ||
      !(lined = NAG_ALLOC(4 * nlines, Integer)) ||
      !(numfix = NAG_ALLOC(1, Integer)) ||
      !(reft1 = NAG_ALLOC(2 * nvmax + 5, Integer)) ||
      !(reft2 = NAG_ALLOC(2 * nvmax + 5, Integer)) ||
      !(reft3 = NAG_ALLOC(2 * nvmax + 5, Integer)) ||
      !(reft4 = NAG_ALLOC(2 * nvmax + 5, Integer)) ||
      !(reft5 = NAG_ALLOC(2 * nvmax + 5, Integer)))
  {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

  /* Characteristic points of the boundary geometry */

  for (j = 1; j <= nlines; ++j) {
    scanf("%lf", &COORCH(1, j));
  }
  scanf("%*[^\n] ");

  for (j = 1; j <= nlines; ++j) {
    scanf("%lf", &COORCH(2, j));
  }
  scanf("%*[^\n] ");

  /* The lines of the boundary mesh */

  for (j = 1; j <= nlines; ++j) {
    for (i = 1; i <= 4; ++i)
      scanf("%" NAG_IFMT "", &LINED(i, j));
    scanf("%lf", &rate[j - 1]);
  }
  scanf("%*[^\n] ");

  /* The number of connected components */
  /* on the boundary and their data */
  scanf("%" NAG_IFMT "", &ncomp);
  scanf("%*[^\n] ");

  /* Allocate memory */

  if (!(nlcomp = NAG_ALLOC(ncomp, Integer)))
  {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

  j = 1;

  for (i = 1; i <= ncomp; ++i) {
    scanf("%" NAG_IFMT "", &nlcomp[i - 1]);
    scanf("%*[^\n] ");
    l = j + abs(nlcomp[i - 1]) - 1;
    for (k = j; k <= l; ++k)
      scanf("%" NAG_IFMT "", &lcomp[k - 1]);
    scanf("%*[^\n] ");
    j += abs(nlcomp[i - 1]);
  }

  itrace = 0;

  /* Call to the 2D boundary mesh generator */

  /* nag_mesh2d_bound (d06bac).
   * Generates a boundary mesh
   */
  nag_mesh2d_bound(nlines, coorch, lined, fbnd, coorus, nus, rate, ncomp,
                   nlcomp, lcomp, nvmax, nedmx, &nvb1, coor1, &nedge1,
                   edge1, itrace, 0, &comm, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_bound (d06bac).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  /* Generate mesh using Delaunay-Voronoi method */

  /* Initialize mesh control parameters */

  itrace = 0;
  npropa = 1;

  /* nag_mesh2d_delaunay (d06abc).
   * Generates a two-dimensional mesh using a Delaunay-Voronoi
   * process
   */
  nag_mesh2d_delaunay(nvb1, nvint, nvmax, nedge1, edge1, &nv1, &nelt1, coor1,
                      conn1, weight, npropa, itrace, 0, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_delaunay (d06abc).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  for (k = 1; k <= nelt1; ++k)
    reft1[k - 1] = 1;

  /* Call the smoothing routine */

  nqint = 10;
  /* nag_mesh2d_smooth (d06cac).
   * Uses a barycentering technique to smooth a given mesh
   */
  nag_mesh2d_smooth(nv1, nelt1, nedge1, coor1, edge1, conn1, nvfix, numfix,
                    itrace, 0, nqint, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_smooth (d06cac).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  /* Build the mesh of the 2nd domain */
  scanf("%" NAG_IFMT "", &nlines);
  scanf("%*[^\n] ");

  /* Characteristic points of the boundary geometry */
  for (j = 1; j <= nlines; ++j)
    scanf("%lf", &COORCH(1, j));
  scanf("%*[^\n] ");
  for (j = 1; j <= nlines; ++j)
    scanf("%lf", &COORCH(2, j));
  scanf("%*[^\n] ");

  /* The lines of the boundary mesh */

  for (j = 1; j <= nlines; ++j) {
    for (i = 1; i <= 4; ++i)
      scanf("%" NAG_IFMT "", &LINED(i, j));
    scanf("%lf", &rate[j - 1]);
  }
  scanf("%*[^\n] ");

  /* The number of connected components */
  /* to the boundary and their data */
  scanf("%" NAG_IFMT "", &ncomp);
  scanf("%*[^\n] ");

  j = 1;
  for (i = 1; i <= ncomp; ++i) {
    scanf("%" NAG_IFMT "", &nlcomp[i - 1]);
    scanf("%*[^\n] ");

    for (k = j; k <= j + abs(nlcomp[i - 1]) - 1; ++k)
      scanf("%" NAG_IFMT "", &lcomp[k - 1]);
    scanf("%*[^\n] ");
    j += abs(nlcomp[i - 1]);
  }
  scanf(" ' %1s '", pmesh);
  scanf("%*[^\n] ");

  itrace = 0;

  /* Call to the 2D boundary mesh generator */

  /* nag_mesh2d_bound (d06bac), see above. */
  nag_mesh2d_bound(nlines, coorch, lined, fbnd, coorus, nus, rate, ncomp,
                   nlcomp, lcomp, nvmax, nedmx, &nvb2, coor2, &nedge2, edge2,
                   itrace, 0, &comm, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_bound (d06bac).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  /* Generate mesh using the advancing front method */

  itrace = 0;

  /* nag_mesh2d_front (d06acc).
   * Generates a two-dimensional mesh using an Advancing-front
   * method
   */
  nag_mesh2d_front(nvb2, nvint, nvmax, nedge2, edge2, &nv2, &nelt2, coor2,
                   conn2, weight, itrace, 0, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_front (d06acc).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  for (k = 1; k <= nelt2; ++k)
    reft2[k - 1] = 2;

  /* Rotation of the 2nd domain mesh */
  /* to produce the 3rd mesh domain */

  itype[0] = 3;
  TRANS(1, 1) = 6.0;
  TRANS(2, 1) = -1.0;
  TRANS(3, 1) = -90.0;
  itrace = 0;
  mode = 0;

  /* nag_mesh2d_trans (d06dac), see above. */
  nag_mesh2d_trans(mode, nv2, nedge2, nelt2, ntrans, itype, trans, coor2,
                   edge2, conn2, coor3, edge3, conn3, itrace, 0, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_trans (d06dac).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  nv3 = nv2;
  nelt3 = nelt2;
  nedge3 = nedge2;

  for (k = 1; k <= nelt3; ++k)
    reft3[k - 1] = 3;

  /* Restitching meshes 1 and 2 to form mesh 4 */

  eps = 0.001;
  itrace = 0;

  /* nag_mesh2d_join (d06dbc), see above. */
  nag_mesh2d_join(eps, nv1, nelt1, nedge1, coor1, edge1, conn1, reft1, nv2,
                  nelt2, nedge2, coor2, edge2, conn2, reft2, &nv4, &nelt4,
                  &nedge4, coor4, edge4, conn4, reft4, itrace, 0, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_join (d06dbc).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  /* Restitching meshes 3 and 4 to form mesh 5 */

  itrace = 0;

  /* nag_mesh2d_join (d06dbc), see above. */
  nag_mesh2d_join(eps, nv4, nelt4, nedge4, coor4, edge4, conn4, reft4, nv3,
                  nelt3, nedge3, coor3, edge3, conn3, reft3, &nv5, &nelt5,
                  &nedge5, coor5, edge5, conn5, reft5, itrace, 0, &fail);
  if (fail.code != NE_NOERROR) {
    printf("Error from nag_mesh2d_join (d06dbc).\n%s\n", fail.message);
    exit_status = 1;
    goto END;
  }

  if (pmesh[0] == 'N') {
    printf("The restitched mesh characteristics\n");
    printf(" nv    =%6" NAG_IFMT "\n", nv5);
    printf(" nelt  =%6" NAG_IFMT "\n", nelt5);
    printf(" nedge =%6" NAG_IFMT "\n", nedge5);
  }
  else if (pmesh[0] == 'Y') {
    /* Output the mesh to view it using the NAG Graphics Library */

    printf(" %10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "\n", nv5, nelt5,
           nedge5);

    for (i = 1; i <= nv5; ++i)
      printf("  %15.6e  %15.6e\n", COOR5(1, i), COOR5(2, i));

    for (k = 1; k <= nelt5; ++k)
      printf("%10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "\n",
             CONN5(1, k), CONN5(2, k), CONN5(3, k), reft5[k - 1]);

    for (k = 1; k <= nedge5; ++k)
      printf(" %10" NAG_IFMT "%10" NAG_IFMT "%10" NAG_IFMT "\n",
             EDGE5(1, k), EDGE5(2, k), EDGE5(3, k));
  }
  else {
    printf("Problem with the printing option Y or N\n");
  }

END:
  NAG_FREE(coor1);
  NAG_FREE(coor2);
  NAG_FREE(coor3);
  NAG_FREE(coor4);
  NAG_FREE(coor5);
  NAG_FREE(coorch);
  NAG_FREE(coorus);
  NAG_FREE(rate);
  NAG_FREE(trans);
  NAG_FREE(weight);
  NAG_FREE(conn1);
  NAG_FREE(conn2);
  NAG_FREE(conn3);
  NAG_FREE(conn4);
  NAG_FREE(conn5);
  NAG_FREE(edge1);
  NAG_FREE(edge2);
  NAG_FREE(edge3);
  NAG_FREE(edge4);
  NAG_FREE(edge5);
  NAG_FREE(itype);
  NAG_FREE(lcomp);
  NAG_FREE(lined);
  NAG_FREE(nlcomp);
  NAG_FREE(numfix);
  NAG_FREE(reft1);
  NAG_FREE(reft2);
  NAG_FREE(reft3);
  NAG_FREE(reft4);
  NAG_FREE(reft5);

  return exit_status;
}

double NAG_CALL fbnd(Integer i, double x, double y, Nag_Comm *pcomm)
{
  double radius2, x0, y0, ret_val;

  if (pcomm->user[0] == -1.0) {
    printf("(User-supplied callback fbnd, first invocation.)\n");
    pcomm->user[0] = 0.0;
  }

  ret_val = 0.0;
  switch (i) {
  case 1:

    /* inner circle */

    x0 = 0.0;
    y0 = 0.0;
    radius2 = 1.0;
    ret_val = (x - x0) * (x - x0) + (y - y0) * (y - y0) - radius2;
    break;

  case 2:

    /* outer circle */

    x0 = 0.0;
    y0 = 0.0;
    radius2 = 5.0;
    ret_val = (x - x0) * (x - x0) + (y - y0) * (y - y0) - radius2;
    break;
  }

  return ret_val;
}