/* $Id: gridimpl.h,v 1.17 2000/07/16 23:20:00 knepley Exp $ */
/*
  This file includes the definition of structures used in PETSc for 
  grids. This should not be included in users' code.
*/

#ifndef __GRIDIMPL_H
#define __GRIDIMPL_H

#include "mesh.h"
#include "grid.h"
#include "gvec.h"

#include "discretization/discimpl.h"

/*-------------------------------------------------------------------------------------------------------------------*/

/*
  ElementVec and ElementMat are auxiliary classes used to simplify the
  finite element interface for the programmer. It will probably not be
  necessary for the user to create these.
*/
struct _ElementVec {
  PETSCHEADER(int)
  int          size;          /* Number of test functions per element */
  int          reduceSize;    /* Number of unknowns after reduction */
  int         *indices;       /* Global row indices for data */
  PetscScalar *array;         /* Contains entries for global vector */
};

struct _ElementMat {
  PETSCHEADER(int)
  int          rowSize;       /* Number of test  functions per element */
  int          colSize;       /* Number of basis functions per element */
  int          reduceRowSize; /* Number of test  unknowns after reduction */
  int          reduceColSize; /* Number of basis unknowns after reduction */
  int         *rowIndices;    /* Global row indices for data */
  int         *colIndices;    /* Global column indices for data */
  int         *reduceCols;    /* Element matrix columns of independent variables */
  PetscScalar *array;         /* Contains entries for global matrix */
  int         *tempIndices;   /* Storage for permuting indices */
  PetscScalar *tempArray;     /* Storage for permuting element matrix */
};

/*-------------------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------- Class Structure ------------------------------------------------------*/
typedef struct _FieldClassMapOps {
  int (*setup)(FieldClassMap);
  int (*constrain)(FieldClassMap, Grid, PetscTruth, PetscTruth, FieldClassMap *);
  int (*reduce)(FieldClassMap, Grid, FieldClassMap *);
  int (*destroy)(FieldClassMap);
  int (*view)(FieldClassMap, PetscViewer);
} FieldClassMapOps;

struct _FieldClassMap {
  PETSCHEADER(FieldClassMapOps)
  void      *data;               /*           Type-specific structure */
  /* Field variables */
  int        numFields;          /*  F:       The number of fields */
  int       *fields;             /* [F]:      The fields */
  /* Mesh variables */
  int        numNodes;           /*  N:       The number of nodes in this domain */
  int        numGhostNodes;      /*  NG:      The number of ghost nodes in this domain */
  int        numOverlapNodes;    /*  N+NG:    The number of nodes+ghost nodes in this domain */
  /* Class variables */
  int        numClasses;         /*  C:       The number of node classes */
  int      **fieldClasses;       /* [F][C]:   Classes containing a given field */
  int       *classes;            /* [N+NG]:   List of node classes, i.e. the fields defined on each node */
  int       *classSizes;         /* [C]:      The number of variables on a node of a given class */
  /* Reduction variables */
  PetscTruth isReduced;          /*           The flag for using BC reduction */
  int      **reduceFieldClasses; /* [F][C]:   Classes containing a reduced field */
  /* Constraint variables */
  PetscTruth isConstrained;      /*           The flag for using constraints */
  int       *isClassConstrained; /* [C]:      The flag indicating a class containing constrained fields */
  int       *classSizeDiffs;     /* [C]:      The increment in size (pos or neg) of the class size with the new fields */
  /* Reduction/Constraint map */
  int        mapSize;            /*  MS:      The number of constraints in the classMap */
  int        numOldClasses;      /*  OC:      The number of classes before reduction */
  int      **classMap;           /* [MS][OC]: The class map from unconstrained to constrained classes */
};

/*------------------------------------------- Variable Ordering -----------------------------------------------------*/
/*
  VarOrdering is an auxiliary object which encapsulates a global variable ordering for a local node-based discretization.
*/
struct _VarOrdering {
  PETSCHEADER(int)
  /* Sizes */
  int   numVars;           /*          The number of global variables in the ordering */
  int   numLocVars;        /*          The number of local variables in the ordering */
  int   numOverlapVars;    /*          The number of local+ghost variables in the ordering */
  int   numNewVars;        /*          The number of global variables introduced by constraints */
  int   numLocNewVars;     /*          The number of local variables introduced by constraints */
  int   numOverlapNewVars; /*          The number of local+ghost variables introduced by constraints */
  int   numTotalFields;    /*  TF:     The total number of fields on the grid */
  /* Offsets */
  int  *firstVar;          /* [P+1]:   The first variable on each processor and the total number of variables */
  int  *offsets;           /* [N+NG]:  The offset of the first variable on each node */
  int  *localOffsets;      /* [NG]:    The local offset of each ghost variable in this domain */
  int **localStart;        /* [TF][C]: The offset of each field (canonical numbering) on a node of a given class */
};

/*
  LocalVarOrdering is an auxiliary object which encapsulates a local variable ordering for a node-based discretization.
*/
struct _LocalVarOrdering {
  PETSCHEADER(int)
  int  numFields;  /*  F    The number of fields in the ordering */
  int *fields;     /* [F]   The fields in the ordering */
  int  elemSize;   /*       The number of shape functions in the element matrix */
  int *elemStart;  /* [TF]: The offset of each field (canonical numbering) in the element matrix/vector (-1 for missing) */
};

/*-------------------------------------------------------------------------------------------------------------------*/

/* Grid Operations - These are the operations associated with all types of grids.
   Here is the basic idea. We have a set of multicomponent fields, each with its
   own discretization. This discretization is applied to each component of the field.
   
   Discretizations know:
   1) Quadrature
   2) Operators

   Operators know:
   1) The size of their local element matrix
   2) Where in the global element matrix their rows and columns start

   Each field is continguous in the global element matrix, and the variables on
   each node are also contiguous. Thus, the structure is

   rows for field 0:
     rows for local node 0:
              |
        <comp[0]> rows
              |
     rows for local node 1:
              |
     rows for local node <funcs[0]>:
              |
   rows for field 1:
              |
   rows for field <fields>:
*/
struct _GridOps {
   int (*gridsetup)(Grid),
       (*gridsetupboundary)(Grid),
       (*gridsetupconstraints)(Grid, PetscConstraintObject),
       (*gridsetupghostscatter)(Grid, VarOrdering, Vec *, VecScatter *),
       (*setfromoptions)(Grid),
       (*gridduplicate)(Grid, Grid *),
       (*gridreform)(Grid, Mesh, GVec, GVec *),
       (*gridcopy)(Grid,Grid),
       (*destroy)(Grid),
       (*view)(Grid, PetscViewer),
       (*getboundarystart)(Grid, int, int, PetscTruth, FieldClassMap, int *, int *),
       (*getboundarynext)(Grid, int, int, PetscTruth, FieldClassMap, int *, int *),
       (*gridreformmesh)(Grid),
       (*gridcreategmat)(Grid, VarOrdering, VarOrdering, PetscTruth, GMat *),
       (*gridcreatevarordering)(Grid, FieldClassMap, VarOrdering *),
       (*gridcreatelocalvarordering)(Grid, int, int *, LocalVarOrdering *),
       (*gridcreatevarscatter)(Grid, VarOrdering, GVec, VarOrdering, GVec, VecScatter *),
       (*gridvarorderingconstrain)(Grid, int, PetscConstraintObject, FieldClassMap, VarOrdering, VarOrdering *),
       (*gridcalcelemvecidx)(Grid, Mesh, int, VarOrdering, VarOrdering, PetscTruth, PetscTruth, ElementVec),
       (*gridcalcelemmatidx)(Grid, int, VarOrdering, VarOrdering, VarOrdering, PetscTruth, ElementMat),
       (*gridcalcboundaryelemvecidx)(Grid, int, int, int, VarOrdering, VarOrdering, PetscTruth, ElementVec),
       (*gridcalcboundaryelemmatidx)(Grid, int, int, int, VarOrdering, VarOrdering, VarOrdering, PetscTruth, ElementMat),
       (*gridprojectelemvec)(Grid, Mesh, int, VarOrdering, VarOrdering, PetscTruth, PetscTruth, ElementVec),
       (*gvecgetlocalworkgvec)(GVec,GVec*),
       (*gvecrestorelocalworkgvec)(GVec,GVec*),
       (*gvecgetworkgvec)(GVec,GVec*),
       (*gvecrestoreworkgvec)(GVec,GVec*),
       (*gvecglobaltolocal)(GVec,InsertMode,GVec),
       (*gveclocaltoglobal)(GVec,InsertMode,GVec),
       (*gvecview)(GVec, PetscViewer),
       (*gridcreaterestriction)(Grid,Grid,GMat*),
       (*gvecevaluatefunction)(Grid, GVec, VarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluatefunctionboundary)(Grid, GVec, int, VarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluatefunctioncollective)(Grid, GVec, VarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluatefunctiongalerkin)(Grid, GVec, int, int *, LocalVarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluatefunctiongalerkincollective)(Grid, GVec, int, int *, LocalVarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluateboundaryfunctiongalerkin)(Grid, GVec, int, int *, LocalVarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluateboundaryfunctiongalerkincollective)(Grid, GVec, int, int *, LocalVarOrdering, PointFunction, PetscScalar, void *),
       (*gvecevaluateoperatorgalerkin)(Grid, GVec, GVec, GVec, VarOrdering, LocalVarOrdering, VarOrdering,
                                       LocalVarOrdering, int, PetscScalar, void *),
       (*gvecevaluatenonlinearoperatorgalerkin)(Grid, GVec, GVec, GVec, int, int *, LocalVarOrdering, NonlinearOperator,
                                                PetscScalar, PetscTruth, void *),
       (*gvecevaluatesystemmatrix)(Grid, GVec, GVec, GVec, void *),
       (*gvecevaluatesystemmatrixdiagonal)(Grid, GVec, GVec, void *),
       (*gmatview)(GMat, PetscViewer),
       (*gmatevaluateoperatorgalerkin)(Grid, GMat, GVec, VarOrdering, LocalVarOrdering, VarOrdering, LocalVarOrdering, int,
                                       PetscScalar, MatAssemblyType, void *),
       (*gmatevaluatealeoperatorgalerkin)(Grid, GMat, int, int *, VarOrdering, LocalVarOrdering,
                                          int *, VarOrdering, LocalVarOrdering, int, PetscScalar, MatAssemblyType, void *),
       (*gmatevaluatealeconstrainedoperatorgalerkin)(Grid, GMat, int, int *, VarOrdering, LocalVarOrdering,
                                                     int *, VarOrdering, LocalVarOrdering, int, PetscScalar, MatAssemblyType, void *),
       (*gmatevaluateboundaryoperatorgalerkin)(Grid, GMat, GVec, VarOrdering, LocalVarOrdering, VarOrdering, LocalVarOrdering,
                                               int, PetscScalar, MatAssemblyType, void *),
       (*gridevaluaterhs)(Grid, GVec, GVec, PetscObject),
       (*gridevaluatesystemmatrix)(Grid, GVec, GMat *, GMat *, MatStructure *, PetscObject);
};

typedef struct _Field {
  char              *name;               /* The field name */
  int                numComp;            /* The number of components */
  DiscretizationType discType;           /* The type of discretization */
  Discretization     disc;               /* The field discretization */
  PetscTruth         isActive;           /* The flag for a field participating in the calculation */
  PetscTruth         isConstrained;      /* The flag for a constrained field */
  int                constraintCompDiff; /* The difference in components between new and constrained field */
} Field;

typedef struct _GridFunc {
  PointFunction func;  /* The PointFunction */
  int           field; /* The field this function acts on */
  PetscScalar   alpha; /* A scalar coefficient */
} GridFunc;

typedef struct _GridOp {
  int               op;          /* The operator */
  NonlinearOperator nonlinearOp; /* The nonlinear operator */
  int               field;       /* The field this operator acts on */
  PetscScalar       alpha;       /* A scalar coefficient */
  PetscTruth        isALE;       /* The flag for an ALE operator */
} GridOp;

typedef struct _GridBC {
  int           boundary; /* [Only for extended BCs] The boundary to apply the condition along */
  int           node;     /* [Only for point BCs]    The node at which to apply the condition */
  double        point[3]; /* [Only for point BCs]    The point at which to apply the condition */
  int           field;    /* The field to constrain */
  PointFunction func;     /* The condition function */
  PetscTruth    reduce;   /* The flag for explicit reduction of the system using the constraint */
} GridBC;

struct _Grid {
  PETSCHEADER(struct _GridOps)
  /* General grid description */
  int                   dim;                    /* grid dimension (1, 2, or 3) */
  Mesh                  mesh;                   /* The associated mesh */
  Grid                  gridparent;             /* The grid that this was refined from */
  PetscTruth            setupcalled;            /* Flag for initialization */
  PetscTruth            bdSetupCalled;          /* Flag for boundary initialization */
  void                 *data;                   /* NOT USED: Holds implementation-specific information */
  void                 *usr;                    /* NOT USED: An optional user-context */
  /* Field variables */
  int                   numFields;              /*  F:      The number of fields in the problem */
  int                   maxFields;              /*          The number of allocated fields */
  Field                *fields;                 /* [F]:     The fields defined on the grid */
  /* Class variables */
  FieldClassMap         cm;                     /* The default class map */
  /* Default variable orderings */
  VarOrdering           order;                  /* The default variable ordering */
  LocalVarOrdering      locOrder;               /* The default local variable ordering */
  /* Ghost variable scatter */
  Vec                   ghostVec;               /* The local vector of solution variables (including ghosts) */
  VecScatter            ghostScatter;           /* The scatter from global vector to local vector with ghost variables */
  /* Constraint variables */
  PetscTruth            isConstrained;          /* The flag for implementation of constraints */
  PetscTruth            explicitConstraints;    /* The flag for directly forming constrained systems */
  int                   numNewFields;           /* The number of new fields on this processor */
  FieldClassMap         constraintCM;           /* The constrained class map */
  VarOrdering           constraintOrder;        /* The variable ordering after constraints are applied */
  IS                    constraintOrdering;     /* Reordering with interior variables before those eliminated by constraints */
  Mat                   constraintMatrix;       /* The projector from the constrained to the unconstrained system */
  Mat                   constraintInverse;      /* The pseudo-inv of the projector from constrained to unconstrained system */
  PetscConstraintObject constraintCtx;          /* The user-specific constraint information */
  /* Problem variables */
  int                   numRhsFuncs;            /* The number of functions in the Rhs */
  int                   maxRhsFuncs;            /* The number of allocated functions */
  GridFunc             *rhsFuncs;               /* Rhs PointFunctions for each active field */
  int                   numRhsOps;              /* The number of operators in the Rhs */
  int                   maxRhsOps;              /* The number of allocated operators */
  GridOp               *rhsOps;                 /* The operators in the Rhs */
  int                   numMatOps;              /* The number of operators in the system matrix */
  int                   maxMatOps;              /* The number of allocated operators */
  GridOp               *matOps;                 /* The operators in the system matrix */
  /* Problem query variables */
  int                   activeMatOp;            /* The current matrix operator being queried */
  int                   activeNonlinearOp;      /* The current nonlinear operator being queried */
  /* Assembly variables */
  int                   numActiveFields;        /* The number of fields in the calculation */
  int                   maxActiveFields;        /* The number of allocated fields */
  int                  *defaultFields;          /* The fields involved in calculation (flagged above) */
  ElementVec            vec;                    /* Element vector for finite element computation */
  ElementMat            mat;                    /* Element matrix for finite element computation */
  ElementVec            ghostElementVec;        /* Element vector of solution variables */
  PetscTruth            ALEActive;              /* The flag for activating ALE support */
  PetscTruth            activeOpTypes[3];       /* Flags for different function types which contribute to calculation */
  /* Boundary condition variables */
  PetscTruth            reduceSystem;           /* Flag for reduction in global system */
  PetscTruth            reduceElement;          /* Flag for implicit reduction using element matrices */
  PetscTruth            reduceElementArgs;      /* Flag for implicit reduction using element matrices of argument vectors */
  FieldClassMap         reductionCM;            /* The class map on the space of reduced variables */
  VarOrdering           reduceOrder;            /* Variable ordering for eliminated unknowns */
  LocalVarOrdering      locReduceOrder;         /* Local variable ordering for eliminated unknowns */
  GVec                  bdReduceVec;            /* The solution evaluated on the boundary */
  GVec                  bdReduceVecOld;         /* The old solution evaluated on the boundary */
  GVec                  bdReduceVecDiff;        /* The difference of bdReduceVec and bdReduceVecOld */
  GVec                  bdReduceVecCur;         /* The current solution vector used to reduce the system */
  GMat                  bdReduceMat;            /* The block eliminated by boundary conditions */
  GVec                  reduceVec;              /* The product of bdReduceMat and bdReduceVec */
  PetscScalar           reduceAlpha;            /* Multiplier for reduction values, -1 in a nonlinear system */
  void                 *reduceContext;          /* An optional user-context passed to reduction assembly routines */
  int                   numBC;                  /* The number of boundary conditions */
  int                   maxBC;                  /* The number of allocated boundary conditions */
  GridBC               *bc;                     /* The boundary conditions */
  int                   numPointBC;             /* The number of boundary conditions to apply */
  int                   maxPointBC;             /* Maximum number of boundary conditions to apply */
  GridBC               *pointBC;                /* The point boundary conditions */
  /* Boundary iteration variables */
  int                   numBd;                  /*  B:     The number of boundaries in the problem */
  int                 **bdSize;                 /* [B][F]: Size of given boundary for a given field */
  VarOrdering           bdOrder;                /*         The global variable ordering along the boundary */
  LocalVarOrdering      bdLocOrder;             /*         The local variable ordering for nodes on the boundary */
  /* Matrix-free variables */
  PetscTruth            isMatrixFree;           /* The flag for construction of matrix-free operators */
  GVec                  matrixFreeArg;          /* The argument to the matrix-free operator */
  void                 *matrixFreeContext;      /* The application context for the matrix-free operator */
  /* Interpolation variables */
  InterpolationType     interpolationType;      /* The method used to project existing fields onto new meshes */
  /* Graphics Extras */
  int                   viewField;              /* The field being visualized */
  int                   viewComp;               /* The component being visualized */
};

#endif /* GRIDIMPL_H */
