// @HEADER
// *****************************************************************************
//            LOCA: Library of Continuation Algorithms Package
//
// Copyright 2001-2005 NTESS and the LOCA contributors.
// SPDX-License-Identifier: BSD-3-Clause
// *****************************************************************************
// @HEADER

// Finite Element Problem Class
/* Provides function (F) and Jacobian evaluations for the following equation
 * via a 1D linear finite element discretization with Epetra objects.
 *
 * d2u
 * --- - k * u**2 = 0
 * dx2
 *
 * subject to @ x=0, u=1
 */

#ifndef _NOX_EXAMPLE_EPETRA_NONLINEAR_FINITEELEMENTPROBLEM_H
#define _NOX_EXAMPLE_EPETRA_NONLINEAR_FINITEELEMENTPROBLEM_H

// This is needed to get the FillType enum values from NOX_Epetra_Interface
#include "NOX_Epetra.H"

// Forward Declarations
class Epetra_Comm;
class Epetra_Map;
class Epetra_Vector;
class Epetra_Import;
class Epetra_CrsGraph;
class Epetra_CrsMatrix;

// Flag to tell the evaluate routine what objects to fill
enum FillType { F_ONLY, MATRIX_ONLY, ALL };

// Flag to tell how to order the unknowns - Currently not used
enum StoreUnknowns {Interleaved, Staggered};

// Finite Element Problem Class
class Brusselator {

public:

  // Flag to tell the evaluate routine how to ghost shared information
  enum OverlapType { NODES, ELEMENTS };

  // Constructor
  Brusselator( int NumGlobalUnknowns, Epetra_Comm& Comm,
               OverlapType OType = ELEMENTS );

  // Destructor
  ~Brusselator();

  // Reset problem for next parameter (time) step.
  // For now, this simply updates oldsoln with the given Epetra_Vector
  void setxDot(const Epetra_Vector& xdot);

  // Set initial condition for solution vector
  void initializeSoln();

  // Set parameters alpha, beta
  void setParameters(const double alpha_, const double beta_);

  // Evaluates the function (F) and/or the Jacobian using the solution
  // values in solnVector.
  bool evaluate(NOX::Epetra::Interface::Required::FillType fType,
                const Epetra_Vector *solnVector,
        Epetra_Vector *rhsVector, Epetra_RowMatrix *matrix,
                double jac_coeff, double mass_coeff);

  // Return a reference to the Epetra_Vector with the initial guess
  // that is generated by the Brusselator class.
  Epetra_Vector& getSolution();

  // Return a reference to the Epetra_Vector with the Jacobian
  // that is generated by the Brusselator class.
  Epetra_CrsMatrix& getJacobian();

  // Return a reference to the Epetra_Vector with the mesh positions
  Epetra_Vector& getMesh();

  // Return a reference to the Epetra_Vector with the old solution
  Epetra_Vector& getSolnDot();

  // Return a reference to the Epetra_CrsGraph that is generated by
  // the Brusselator problem class.
  Epetra_CrsGraph& getGraph();

private:

  // inserts the global column indices into the Graph
  Epetra_CrsGraph& generateGraphUsingNodes(Epetra_CrsGraph& AA);

  // inserts the global column indices into the Graph
  Epetra_CrsGraph& generateGraphUsingElements(Epetra_CrsGraph& AA);

  // Private to prohibit copying
  Brusselator(const Brusselator&);
  Brusselator& operator=(const Brusselator&);

private:

  double xmin;
  double xmax;
  Epetra_Comm *Comm;
  OverlapType overlapType;
  int NumGlobalNodes;     // Total Number of nodes
  Epetra_Import *ColumnToOverlapImporter;
  Epetra_CrsGraph *AA;
  Epetra_CrsMatrix *A;
  double alpha, beta;     // Model Parameters

  // Default initialization for these
  double dx;
  FillType flag;
  Epetra_Map *StandardNodeMap;
  Epetra_Map *OverlapNodeMap;
  Epetra_Map *StandardMap;
  Epetra_Map *OverlapMap;
  Epetra_Import *Importer;
  Epetra_Import *nodeImporter;
  Epetra_Vector *xptr;
  Epetra_Vector *initialSolution;
  Epetra_Vector *solnDot;
  Epetra_Vector *rhs;

  int MyPID;              // Process number
  int NumProc;            // Total number of processes

  int NumSpecies;         // Number of unknowns owned by this process
  enum { NUMSPECIES = 2}; // Needed for SGI build
  int NumMyNodes;         // Number of nodes owned by this process
  int NumMyUnknowns;      // Number of unknowns owned by this process
  int NumGlobalUnknowns;  // Total Number of unknowns

};
#endif




