/*************************************************************************
 * FILE: print.c                                                         *
 * --------------------------------------------------------------------- *
 * DESCRIPTION:                                                          *
 *   Dummy functions that print out domain information.                  *
 * --------------------------------------------------------------------- *
 * EXTERNAL FUNCTIONS:                                                   *
 *   print_dom: Print detailed domain information.                       *
 *   print_itf: Print detailed interface information.                    *
 *   print_op: Print detailed operator information.                      *
 *************************************************************************/

#include <math.h>
#include <stdio.h>
#include "prophetc.h"
#include "grid.h"
#include "assemblist.h"
#include "pdeterms.h"
#include "mathpack.h"

/*************************************************************************
 * EXTERNAL FUNCTION: print_dom                                          *
 * --------------------------------------------------------------------- *
 * Print detailed domain information. Implements out_var = in_var.       *
 *                                                                       *
 * Read variables: [in_var]                                              *
 * Write variables: [out_var]                                            *
 *************************************************************************/

int print_dom (arglist)
    argdescrip
{
    static int num;
    int i, in, maxnum;
    int rhs = ((*imtx)%10 == 1), mtx = ((*imtx)/10 == 1);
    domain *dom = PDEdom;

    /* if-block to check that we have the necessary # of i/o variables */

    if (*nsol != 1 || *ndep != 1) {
        dberr ("bad input to print_dom");
        fluxwhine (nsol,msol,ndep,mdep);
        return (-1);
    }

    /* switch performs different actions depending on value of "path" */

    switch( *path) {

        case FT_CONFIG:
            df[0] = 1;
            return (0);
    
        case FT_DT:
            num = 0;
            return (0);

        case FT_RUN:

            maxnum = 1;
            if (num < maxnum) {

                /* General domain info */
                printf ("Domain Info:\n");
                printf ("  Space dimensions: %d\n", dom->dim);
                printf ("  Number of points: %d\n", dom->nfld[fPoint]);
                printf ("  Number of nodes: %d\n", dom->nfld[fNode]);
                printf ("  Number of interface points: %d\n", dom->nfld[fIpt]);
                printf ("  Number of edges: %d\n", dom->nfld[fEdge]);
                printf ("  Number of element edges: %d\n", dom->nfld[fEledge]);
                printf ("  Number of elements: %d\n", dom->nfld[fElt]);

                /* Region info */
                printf ("  Number of regions: %d\n", dom->nr);
                for (i = 0; i < dom->nr; i++) {
                    printf ("    Region %d: %s/%s\n", i,
                        idreg(i), dom->rname[i]);
                }

                /* Surface info */
                printf ("  Number of surfaces: %d\n", dom->ns);
                for (i = 0; i < dom->ns; i++) {
                    printf ("    Surface %d: %s/%s\n", i+1,
                        idreg(-(i+1)), dom->rname[-(i+1)]);
                }

                /* Interface info */
                printf ("  Number of interfaces: %d\n", dom->ni);
                for (i = 0; i < dom->ni; i++) {
                    interface ifc = dom->itf[i];
                    printf ("    Interface %d: %s/%s\n", i,
                        dom->rname[ifc.reg[0]], dom->rname[ifc.reg[1]]);
                }

                /* Field info */
                printf ("  Number of fields: %d\n", dom->nf);
                for (i = FORTRAN1; i < FORTRAN1 + dom->nf; i++) {
                    field f = dom->fld[i-FORTRAN1];
                    printf ("    Field %d: Type: %d; Name: %s/%s, Dim: %d; Size: %d\n",
                        i, f.type, idvar(i), f.name, f.dim, f.size);
                }

                printf ("\n");
                ++num;
            }

            /* evaluate "f" and "df" */

            if (rhs || mtx) {
                for (in = 0; in < *nn; in++) {
                    if (rhs) { f[in] = sol[in]; }
                    if (mtx) { df[in] = 1.0; }
                }
            }
            break;

        /* ... Ignore all other calls.  */
        default:
            break;
    }

    return (0);
}

/*************************************************************************
 * EXTERNAL FUNCTION: print_itf                                          *
 * --------------------------------------------------------------------- *
 * Print detailed interface information. Implements out_var = in_var.    *
 *                                                                       *
 * Read variables: [in_var]                                              *
 * Write variables: [out_var]                                            *
 *************************************************************************/

int print_itf (arglist)
    argdescrip
{
    char *rn, *rn0, *rn1;
    static int num;
    int i, in, maxnum, rox;
    int rhs = ((*imtx)%10 == 1), mtx = ((*imtx)/10 == 1);
    domain *dom = PDEdom;
    interface ifc;
    node n;

    /* if-block to check that we have the necessary # of i/o variables */

    if (*nsol != 1 || *ndep != 1) {
        dberr ("bad input to print_itf");
        fluxwhine (nsol,msol,ndep,mdep);
        return (-1);
    }

    /* switch performs different actions depending on value of "path" */

    switch( *path) {

        case FT_CONFIG:
            df[0] = 1;
            return (0);
    
        case FT_DT:
            num = 0;
            return (0);

        case FT_RUN:

            maxnum = dom->nr;

            /* Find index of oxide region */
            for (i = 0; i < dom->nr; i++) {
                if (!strcmp(dom->rname[i],"oxide")) { break; }
            }
            if (i == dom->nr) {
                printf ("Error: oxide region not found!\n");
                return (-1);
            }
            rox = i; /* oxide region number */
            if (num < maxnum && *ireg == rox) {
                printf ("In oxide: no action to take.\n");
                printf ("\n");
                ++num;
                return (0);
            }

            rn = dom->rname[*ireg];
            if (num < maxnum) {
                printf ("Interface of interest: ");
                for (i = 0; i < dom->ni; i++) {
                    ifc = dom->itf[i];
                    rn0 = dom->rname[ifc.reg[0]];
                    rn1 = dom->rname[ifc.reg[1]];
                    if ((ifc.reg[0] == *ireg && ifc.reg[1] == rox) ||
                        (ifc.reg[1] == *ireg && ifc.reg[0] == rox)) {
                        printf ("%d (%s/%s)\n", i, rn0, rn1);
                        break;
                    }
                }
                if (i == dom->ni) {
                    printf ("Error: %s/oxide interface not found!\n", rn);
                    return (-1);
                }
                printf ("  Nodes on %s/oxide interface: %d\n", rn, 2*ifc.nno);
                for (i = 0; i < 2*ifc.nno; i++) {
                    in = ifc.nd[i]; n = dom->nd[in];
                    printf ("  %d: Node %d, Region %d (%s); Point %d at ",
                        i, in, n.reg, dom->rname[n.reg], n.pt);
                    if (dom->dim == 1) {
                        printf ("x=%g/%g/%g\n",
                            dom->pt[n.pt].coord[0], node_coord(dom,in,0),
                            node_x(dom,in));
                    } else if (dom->dim == 2) {
                        printf ("x=%g/%g/%g, y=%g/%g/%g\n",
                            dom->pt[n.pt].coord[0], node_coord(dom,in,0),
                            node_x(dom,in),
                            dom->pt[n.pt].coord[1], node_coord(dom,in,1),
                            node_y(dom,in));
                    } else {
                        printf ("x=%g/%g/%g, y=%g/%g/%g, z=%g/%g/%g\n",
                            dom->pt[n.pt].coord[0], node_coord(dom,in,0),
                            node_x(dom,in),
                            dom->pt[n.pt].coord[1], node_coord(dom,in,1),
                            node_y(dom,in),
                            dom->pt[n.pt].coord[2], node_coord(dom,in,2),
                            node_z(dom,in));
                    }
                }

                printf ("\n");
                ++num;
            }

            /* evaluate "f" and "df" */

            if (rhs || mtx) {
                for (in = 0; in < *nn; in++) {
                    if (rhs) { f[in] = sol[in]; }
                    if (mtx) { df[in] = 1.0; }
                }
            }
            break;

        /* ... Ignore all other calls.  */
        default:
            break;
    }

    return (0);
}

/*************************************************************************
 * EXTERNAL FUNCTION: print_op                                           *
 * --------------------------------------------------------------------- *
 * Print detailed operator information. Implements out_var = in_var.     *
 *                                                                       *
 * Read variables: [in_var]                                              *
 * Write variables: [out_var]                                            *
 *************************************************************************/

int print_op (arglist)
    argdescrip
{
    static int num;
    int i, in, maxnum;
    int rhs = ((*imtx)%10 == 1), mtx = ((*imtx)/10 == 1);
    domain *dom = PDEdom;

    /* if-block to check that we have the necessary # of i/o variables */

    if (*nsol != 1 || *ndep != 1) {
        dberr ("bad input to print_reg");
        fluxwhine (nsol,msol,ndep,mdep);
        return (-1);
    }

    /* switch performs different actions depending on value of "path" */

    switch( *path) {

        case FT_CONFIG:
            df[0] = 1;
            return (0);
    
        case FT_DT:
            num = 0;
            return (0);

        case FT_RUN:

            maxnum = dom->nr;
            if (num < maxnum) {
                printf ("Operator info:\n");
                printf ("  Region number: %d\n", *ireg);
                printf ("  Region name: %s/%s\n", idreg(*ireg),
                    dom->rname[*ireg]);
                printf ("  Number of nodes: %d\n", *nn);
                printf ("  Input field(s):\n");
                for (i = 0; i < *ndep; i++) {
                    printf ("    Field %d: global index: %d; name: %s/%s\n",
                        i, mdep[i], idvar(mdep[i]),
                        dom->fld[mdep[i]-FORTRAN1].name);
                }
                printf ("  Output field(s):\n");
                for (i = 0; i < *nsol; i++) {
                    printf ("    Field %d: global index: %d; name: %s/%s\n",
                        i, msol[i], idvar(msol[i]),
                        dom->fld[msol[i]-FORTRAN1].name);
                }
                printf ("  Operator dimension: %d\n", *dim);

                printf ("\n");
                ++num;
            }

            /* evaluate "f" and "df" */

            if (rhs || mtx) {
                for (in = 0; in < *nn; in++) {
                    if (rhs) { f[in] = sol[in]; }
                    if (mtx) { df[in] = 1.0; }
                }
            }
            break;

        /* ... Ignore all other calls.  */
        default:
            break;
    }

    return (0);
}
