#ifndef TAOPETSCAPP_H
#define TAOPETSCAPP_H


#include "taoappobject.h"
#include "../../vector/taovec_petsc.h"
#include "../../matrix/taomat_petsc.h"
#include "petscksp.h"

//#include "taoapp.h"

typedef struct _p_TAO_SOLVER* TAO_SOLVER;
typedef struct _p_TAOAPPLICATION* TAO_APPLICATION;


class TaoPetscApplication: public TaoApplication{

 protected:


  MPI_Comm comm;
 public:
  TaoPetscApplication(MPI_Comm comm);
  TaoPetscApplication(){};
  int Setup();

  ~TaoPetscApplication();
  int TakeDown();

  TAO_SOLVER tao;
  TAO_APPLICATION papp;

  int Monitor();
  int Monitor2(TaoVec *xx, TaoVec *gl, TaoVec *dx,TaoTruth *flag);

  /* Function Evaluation */
  int InitializeVariables(TaoVec *x);

  TaoVecPetsc *taox;    /* The Variable Vector */
  int GetVariableVector(TaoVec **xx);
  int EvaluateObjectiveFunction(TaoVec *xx, double *ff);

  /* Gradient Evaluation */
  int EvaluateGradient(TaoVec *xx, TaoVec *gg);

  /* Function and Gradient */
  int EvaluateObjectiveAndGradient(TaoVec *xx, double *ff, TaoVec *gg);


  /* Hessian Evaluation */
  TaoMatPetsc *taoh;    /* The Hessian Matrix */
  int GetHessianMatrix(TaoMat **HH);
  int EvaluateHessian(TaoVec *xx, TaoMat *HH);

  int HessianSolve(TaoVec *vv, TaoVec *ww, TaoTruth *flag);

  /* Set Variable Bounds */
  int EvaluateVariableBounds(TaoVec *, TaoVec *);

  KSP ksptmp;
  int GetLinearSolver(TaoMat *, int, TaoLinearSolver **);

  /* Routines below this are very preliminary */
  TaoMatPetsc *taoj;    /* The Jacobian Matrix */
  int GetJacobianMatrix(TaoMat **JJ);
  int EvaluateJacobian(TaoVec *xx, TaoMat *JJ);

  TaoVecPetsc *taofv;
  int GetConstraintVector(TaoVec** rr);
  int EvaluateConstraints(TaoVec *xx, TaoVec *RR);
 
  virtual int GetInequalityConstraints(TaoVec**, TaoMat **, TaoVec **);

  TaoVecPetsc *taofvll;
  TaoVecPetsc *taofvuu;
  TaoMatPetsc *taoAA;

  int CreateATDAMatrix(TaoMat *,TaoVec*,TaoVec*, TaoMat**);

};

int TaoAppGetTaoPetscApp(TAO_APPLICATION, TaoPetscApplication**);


#endif


