#include "src/fortran/custom/zpetsc.h"
#include "petscksp.h"
#include "tao.h"
/*
#include "src/externaltao/petsctao/vector/taovec_petsc.h"
#include "src/externaltao/petsctao/matrix/taomat_petsc.h"
#include "src/externaltao/petsctao/indexset/taois_petsc.h"
#include "src/externaltao/petsctao/linearsolver/taolinearsolver_petsc.h"
#include "src/externaltao/petsctao/application/taoapp_petsc.h"
*/


#ifdef PETSC_HAVE_FORTRAN_CAPS

#define taowrappetscvec_       TAOWRAPPETSCVEC
#define taowrappetscmat_       TAOWRAPPETSCMAT
#define taovecgetpetscvec_     TAOVECGETPETSCVEC
#define taomatgetpetscmat_     TAOMATGETPETSCMAT

#define taowrapis_       TAOWRAPIS
#define taowrapksp_     TAOWRAPKSP

#define taoindexsetgetis_         TAOINDEXSETGETIS
#define taolinearsolvergetpetscksp_   TAOLINEARSOLVERGETPETSCKSP

#define taopetscapplicationcreate_     TAOPETSCAPPLICATIONCREATE
#define taoapplicationcreate_          TAOAPPLICATIONCREATE
#define taoapplicationdestroy_          TAOAPPLICATIONDESTROY
#define taosetapplication_          TAOSETAPPLICATION
/* #define taosetfromoptions_          TAOSETFROMOPTIONS */

/*
#define taosetobjectivefunctionroutine_          TAOSETOBJECTIVEFUNCTIONROUTINE
#define taosetobjectivefunctiongradientroutine_  TAOSETOBJECTIVEFUNCTIONGRADIENTROUTINE
#define taosetgradientroutine_                   TAOSETGRADIENTROUTINE
#define taosethessianroutine_                    TAOSETHESSIANROUTINE
#define taosetvariableboundsroutine_             TAOSETVARIABLEBOUNDSROUTINE
*/

#define taoappsetobjectiveandgradientroutine_    TAOAPPSETOBJECTIVEANDGRADIENTROUTINE
#define taoappsetobjectiveandgradientro_         TAOAPPSETOBJECTIVEANDGRADIENTRO
#define taoappsetobjectiveroutine_               TAOAPPSETOBJECTIVEROUTINE
#define taoappsetgradientroutine_                TAOAPPSETGRADIENTROUTINE
#define taoappsethessianroutine_                 TAOAPPSETHESSIANROUTINE
#define taoappsetvariableboundsroutine_          TAOAPPSETVARIABLEBOUNDSROUTINE
#define taoappsetjacobianroutine_                TAOAPPSETJACOBIANROUTINE
#define taoappsetconstraintroutine_              TAOAPPSETCONSTRAINTROUTINE

/* Grid application */
#define daappsethessianroutine_                         DAAPPSETHESSIANROUTINE
#define daappsetobjectiveandgradientroutine_            DAAPPSETOBJECTIVEANDGRADIENTROUTINE
#define daappsetobjectiveandgradientrou_                DAAPPSETOBJECTIVEANDGRADIENTROU
#define daappsetgradientroutine_                        DAAPPSETGRADIENTROUTINE
#define daappsetobjectiveroutine_                       DAAPPSETOBJECTIVEROUTINE
#define daappsetvariableboundsroutine_                  DAAPPSETVARIABLEBOUNDSROUTINE
#define daappsetconstraintroutine_                      DAAPPSETCONSTRAINTROUTINE
#define daappsetjacobianroutine_                        DAAPPSETJACOBIANROUTINE
#define daappsetbeforemonitor_                          DAAPPSETBEFOREMONITOR
#define daappsetaftermonitor_                           DAAPPSETAFTERMONITOR
#define daappsetelementobjectiveandgradientroutine_     DAAPPSETELEMENTOBJECTIVEANDGRADIENTROUTINE
#define daappsetelementobjectiveandgrad_                DAAPPSETELEMENTOBJECTIVEANDGRAD
#define daappsetelementhessianroutine_                  DAAPPSETELEMENTHESSIANROUTINE


/* deprecated */
#define taosetpetscfunction_             TAOSETPETSCFUNCTION
#define taosetpetscfunctiongradient_     TAOSETPETSCFUNCTIONGRADIENT
#define taosetpetscgradient_             TAOSETPETSCGRADIENT
#define taosetpetschessian_              TAOSETPETSCHESSIAN


#define taodefaultcomputehessian_   TAODEFAULTCOMPUTEHESSIAN
#define taodefaultcomputehessiancolor_ TAODEFAULTCOMPUTEHESSIANCOLOR
#define taosetpetscjacobian_             TAOSETPETSCJACOBIAN
#define taosetjacobianroutine_             TAOSETJACOBIANROUTINE
#define taosetconstraintroutine_           TAOSETCONSTRAINTROUTINE
#define taosetjacobianmat_                 TAOSETJACOBIANMAT
#define taosetconstraintvec_               TAOSETCONSTRAINTVEC

#define taosetpetscvariablebounds_       TAOSETPETSCVARIABLEBOUNDS
#define taosetpetscinitialvector_        TAOSETPETSCINITIALVECTOR
#define taogetksp_                      TAOGETKSP

#elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)

#define taowrappetscvec_       taowrappetscvec
#define taowrappetscmat_       taowrappetscmat
#define taovecgetpetscvec_     taovecgetpetscvec
#define taomatgetpetscmat_     taomatgetpetscmat

#define taowrapis_       taowrapis
#define taowrapksp_     taowrapksp

#define taoindexsetgetpetscis_         taoindexsetgetpetscis
#define taolinearsolvergetksp_   taolinearsolvergetksp

#define taopetscapplicationcreate_     taopetscapplicationcreate 
#define taoapplicationcreate_                taoapplicationcreate 
#define taoapplicationdestroy_                taoapplicationdestroy 
#define taosetapplication_                taosetapplication 
/* #define taosetfromoptions_          taosetfromoptions */

/*
#define taosetobjectivefunctionroutine_          taosetobjectivefunctionroutine
#define taosetobjectivefunctiongradientroutine_  taosetobjectivefunctiongradientroutine
#define taosetgradientroutine_                   taosetgradientroutine
#define taosethessianroutine_                    taosethessianroutine
#define taosetvariableboundsroutine_             taosetvariableboundsroutine
*/

#define taoappsetobjectiveandgradientroutine_    taoappsetobjectiveandgradientroutine
#define taoappsetobjectiveandgradientro_         taoappsetobjectiveandgradientro
#define taoappsetobjectiveroutine_               taoappsetobjectiveroutine
#define taoappsetgradientroutine_                taoappsetgradientroutine
#define taoappsethessianroutine_                 taoappsethessianroutine
#define taoappsetvariableboundsroutine_          taoappsetvariableboundsroutine
#define taoappsetjacobianroutine_                taoappsetjacobianroutine
#define taoappsetconstraintroutine_              taoappsetconstraintroutine


/* Grid application */
#define daappsethessianroutine_                         daappsethessianroutine
#define daappsetobjectiveandgradientroutine_            daappsetobjectiveandgradientroutine
#define daappsetobjectiveandgradientrou_                daappsetobjectiveandgradientrou
#define daappsetgradientroutine_                        daappsetgradientroutine
#define daappsetobjectiveroutine_                       daappsetobjectiveroutine
#define daappsetvariableboundsroutine_                  daappsetvariableboundsroutine
#define daappsetconstraintroutine_                      daappsetconstraintroutine
#define daappsetjacobianroutine_                        daappsetjacobianroutine
#define daappsetbeforemonitor_                          daappsetbeforemonitor
#define daappsetaftermonitor_                           daappsetaftermonitor
#define daappsetelementobjectiveandgradientroutine_     daappsetelementobjectiveandgradientroutine
#define daappsetelementobjectiveandgrad_                daappsetelementobjectiveandgrad
#define daappsetelementhessianroutine_                  daappsetelementhessianroutine

/* deprecated */
#define taosetpetscfunction_             taosetpetscfunction
#define taosetpetscfunctiongradient_     taosetpetscfunctiongradient
#define taosetpetscgradient_             taosetpetscgradient
#define taosetpetschessian_              taosetpetschessian
#define taodefaultcomputehessian_   taodefaultcomputehessian
#define taodefaultcomputehessiancolor_ taodefaultcomputehessiancolor

#define taosetpetscjacobian_             taosetpetscjacobian
#define taosetconstraintsfunction_  taosetconstraintsfunction

#define taosetjacobianroutine_             taosetjacobianroutine
#define taosetconstraintroutine_           taosetconstraintroutine
#define taosetjacobianmat_                 taosetjacobianmat
#define taosetconstraintvec_               taosetconstraintvec

#define taosetpetscvariablebounds_       taosetpetscvariablebounds
#define taosetpetscinitialvector_        taosetpetscinitialvector
#define taogetksp_                      taogetksp

#endif

EXTERN_C_BEGIN
void PETSC_STDCALL taowrappetscvec_(Vec *V, TaoVecPetsc **TV,  int *ierr)
{
  *ierr = TaoWrapPetscVec(*V,TV);
}

void PETSC_STDCALL taovecgetpetscvec_(TaoVec* *TV, Vec *V,  int *ierr)
{
  *ierr=TaoVecGetPetscVec(*TV,V);
}


void PETSC_STDCALL taowrappetscmat_(Mat *M, TaoMatPetsc **TM,  int *ierr)
{
  *ierr = TaoWrapPetscMat(*M,TM);
}


void PETSC_STDCALL taomatgetpetscmat_(TaoMat* *TM, Mat *M,  int *ierr)
{
  *ierr=TaoMatGetPetscMat(*TM,M);
}


void PETSC_STDCALL taowrappetscis_(IS *M, int *imax,TaoIndexSetPetsc **TM,  int *ierr)
{
  *ierr = TaoWrapPetscIS(*M,*imax,TM);
}


void PETSC_STDCALL taoindexsetgetpetscis_(TaoIndexSet* *TM, IS *M,  int *ierr)
{
  *ierr=TaoIndexSetGetPetscIS(*TM,M);
}


void PETSC_STDCALL taowrapksp_( KSP *M, TaoLinearSolverPetsc **TM,  int *ierr)
{
  *ierr = TaoWrapKSP(*M,TM);
}

void PETSC_STDCALL taolinearsolvergetksp_(TaoLinearSolver **TM, KSP *M,  int *ierr)
{
  *ierr=TaoLinearSolverGetKSP(*TM,M);
}

void PETSC_STDCALL taopetscapplicationcreate_(MPI_Comm *comm,TAO_APPLICATION  *outtao,int *ierr){

  *ierr = TaoPetscApplicationCreate((MPI_Comm)PetscToPointerComm(*comm),outtao);

}

void PETSC_STDCALL taoapplicationcreate_(MPI_Comm *comm,TAO_APPLICATION  *outtao,int *ierr){

  *ierr = TaoApplicationCreate((MPI_Comm)PetscToPointerComm(*comm),outtao);

}

void PETSC_STDCALL taoapplicationdestroy_(TAO_APPLICATION  *outtao,int *ierr){

  *ierr = TaoApplicationDestroy(*outtao);

}

/* Very Old routine  must get rid of it .  Here only for backward compatibility */
void PETSC_STDCALL taosetapplication_(TAO_SOLVER *tao, TAO_APPLICATION  *outtao, int *ierr){

  *ierr = TaoSetupApplicationSolver(*outtao, *tao);

}

/* Very Old routine  must get rid of it .  Here only for backward compatibility */
/*
void PETSC_STDCALL taosetfromoptions_(TAO_SOLVER *tao, int *ierr){

  *ierr = TaoSetOptions(*tao);

}
*/
/* -------------- Setting call-back routines ---------------- */

static void (PETSC_STDCALL *f1a)(TAO_SOLVER*,Vec*,double*,Vec*,void*,int*);
static void (PETSC_STDCALL *f1)(TAO_APPLICATION*,Vec*,double*,Vec*,void*,int*);

EXTERN_C_END

static int ourtaominfunctiongradientroutine(TAO_SOLVER tao,Vec x,double *f,Vec r,void *ctx)
{
  int info = 0;
  (*f1a)(&tao,&x,f,&r,ctx,&info);CHKERRQ(info);
  return 0;
}

static int ourtaominfunctiongradientroutine2(TAO_APPLICATION taoapp,Vec x,double *f,Vec r,void *ctx)
{
  int info = 0;
  (*f1)(&taoapp,&x,f,&r,ctx,&info);CHKERRQ(info);
  return 0;
}

EXTERN_C_BEGIN


void PETSC_STDCALL taosetpetscfunctiongradient_(TAO_APPLICATION  *taoapp,Vec *x,Vec *r,void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,double*,Vec*,void*,int*),void *ctx,int *info){
  f1a = func;
  *info = TaoSetPetscFunctionGradient(*taoapp,*x,*r,ourtaominfunctiongradientroutine,ctx);
}

void PETSC_STDCALL taoappsetobjectiveandgradientroutine_(TAO_APPLICATION  *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,double*,Vec*,void*,int*),void *ctx,int *info){
  f1 = func;
  *info = TaoAppSetObjectiveAndGradientRoutine(*taoapp,ourtaominfunctiongradientroutine2,ctx);
}
void PETSC_STDCALL taoappsetobjectiveandgradientro_(TAO_APPLICATION  *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,double*,Vec*,void*,int*),void *ctx,int *info){
  f1 = func;
  *info = TaoAppSetObjectiveAndGradientRoutine(*taoapp,ourtaominfunctiongradientroutine2,ctx);
}


static void (PETSC_STDCALL *f2a)(TAO_SOLVER*,Vec*,double*,void*,int*);
static void (PETSC_STDCALL *f2)(TAO_APPLICATION*,Vec*,double*,void*,int*);
EXTERN_C_END
static int ourtaominfunction(TAO_SOLVER tao,Vec x,double* d,void *ctx)
{
  int info = 0;
  (*f2a)(&tao,&x,d,ctx,&info);CHKERRQ(info);
  return 0;
}
static int ourtaominfunction2(TAO_APPLICATION taoapp,Vec x,double* d,void *ctx)
{
  int info = 0;
  (*f2)(&taoapp,&x,d,ctx,&info);CHKERRQ(info);
  return 0;
}
EXTERN_C_BEGIN

void PETSC_STDCALL taosetpetscfunction_(TAO_APPLICATION  *taoapp,Vec *x,
          void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,double*,void*,int*),void *ctx,int *info){
  f2a = func;
  *info = TaoSetPetscFunction(*taoapp,*x,ourtaominfunction,ctx);
}

void PETSC_STDCALL taoappsetobjectiveroutine(TAO_APPLICATION  *taoapp,
	  void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,double*,void*,int*),void *ctx,int *info){
  f2 = func;
  *info = TaoAppSetObjectiveRoutine(*taoapp,ourtaominfunction2,ctx);
}



static void (PETSC_STDCALL *f3a)(TAO_SOLVER*,Vec*,Vec *,void*,int*);
static void (PETSC_STDCALL *f3)(TAO_APPLICATION*,Vec*,Vec *,void*,int*);
EXTERN_C_END

static int ourtaogradientfunction(TAO_SOLVER tao,Vec x,Vec d,void *ctx)
{
  int info = 0;
  (*f3a)(&tao,&x,&d,ctx,&info);CHKERRQ(info);
  return 0;
}
static int ourtaogradientfunction2(TAO_APPLICATION taoapp,Vec x,Vec d,void *ctx)
{
  int info = 0;
  (*f3)(&taoapp,&x,&d,ctx,&info);CHKERRQ(info);
  return 0;
}
EXTERN_C_BEGIN

void PETSC_STDCALL taosetpetscgradient_(TAO_APPLICATION *taoapp,Vec *r,void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,Vec*,void*,int*),void *ctx,int *info){
  f3a = func;
  *info = TaoSetPetscGradient(*taoapp,*r,ourtaogradientfunction,ctx);
}

void PETSC_STDCALL taoappsetgradientroutine_(TAO_APPLICATION *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,Vec*,void*,int*),void *ctx,int *info){
  f3 = func;
  *info = TaoAppSetGradientRoutine(*taoapp,ourtaogradientfunction2,ctx);
}


/* ---------------------------------------------------------*/
/*
  taodefaultcomputehessian() and taodefaultcomputehessiancolor().
  These routines can be used directly from Fortran, but the following is done
  primarily so that a Fortran call to TaoSetPetscHessian() will properly handle the
  defaults being passed in.

  functions, hence no STDCALL
*/
void taodefaultcomputehessian_(TAO_APPLICATION *tao,Vec *x,Mat *m,Mat *p,MatStructure* type,
                               void *ctx,int *info)
{
  *info = TaoAppDefaultComputeHessian(*tao,*x,m,p,type,ctx);
}

void  taodefaultcomputehessiancolor_(TAO_APPLICATION *tao,Vec *x,Mat *m,Mat *p,
                                     MatStructure* type,void *ctx,int *info)
{
  *info = TaoAppDefaultComputeHessianColor(*tao,*x,m,p,type,*(MatFDColoring*)ctx);
}

static void (PETSC_STDCALL *f4a)(TAO_SOLVER*,Vec*,Mat*,Mat*,MatStructure*,void*,int*);
static void (PETSC_STDCALL *f4)(TAO_APPLICATION*,Vec*,Mat*,Mat*,MatStructure*,void*,int*);
EXTERN_C_END

static int ourtaohessian(TAO_SOLVER tao,Vec x,Mat* m,Mat* p,MatStructure* type,void*ctx)
{
  int info = 0;
  (*f4a)(&tao,&x,m,p,type,ctx,&info);CHKERRQ(info);
  return 0;
}
static int ourtaohessian2(TAO_APPLICATION taoapp,Vec x,Mat* m,Mat* p,MatStructure* type,void*ctx)
{
  int info = 0;
  (*f4)(&taoapp,&x,m,p,type,ctx,&info);CHKERRQ(info);
  return 0;
}

EXTERN_C_BEGIN

void PETSC_STDCALL taosetpetschessian_(TAO_APPLICATION  *taoapp,Mat *A,Mat *B,void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,Mat*,Mat*,
                                  MatStructure*,void*,int*),void *ctx,int *info)
{
  f4a = func;
  *info = TaoSetPetscHessian(*taoapp,*A,*B,ourtaohessian,ctx);  
}

void PETSC_STDCALL taoappsethessianroutine_(TAO_APPLICATION  *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,Mat*,Mat*,
                                  MatStructure*,void*,int*),void *ctx,int *info)
{
  if ((void(*)())func == (void(*)()) taodefaultcomputehessian_) {
    *info = TaoAppSetHessianRoutine(*taoapp,TaoAppDefaultComputeHessian,ctx);
  } else if ( (void(*)()) func == (void(*)()) taodefaultcomputehessiancolor_) {
    *info = TaoAppSetHessianRoutine(*taoapp,TaoAppDefaultComputeHessianColor,*(MatFDColoring*)ctx);
  } else {
    f4 = func;
    *info = TaoAppSetHessianRoutine(*taoapp,ourtaohessian2,ctx);
  }
}


static void (PETSC_STDCALL *fb)(TAO_APPLICATION*, Vec*,Vec *,void*,int*);

EXTERN_C_END

static int ourtaovariableboundsroutine(TAO_APPLICATION tao, Vec x,Vec d,void *ctx)
{
  int info = 0;
  (*fb)(&tao,&x,&d,ctx,&info);CHKERRQ(info);
  return 0;
}

EXTERN_C_BEGIN


void PETSC_STDCALL taoappsetvariableboundsroutine_(TAO_APPLICATION *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,Vec*,void*,int*),void *ctx,int *info){
  fb = func;
  *info = TaoAppSetVariableBoundsRoutine(*taoapp,ourtaovariableboundsroutine,ctx);
}


static void (PETSC_STDCALL *f6a)(TAO_SOLVER*,Vec*,Vec *,void*,int*);
static void (PETSC_STDCALL *f6)(TAO_APPLICATION*,Vec*,Vec *,void*,int*);
EXTERN_C_END
static int ourtaoconstraintsfunction(TAO_SOLVER tao,Vec x,Vec d,void *ctx)
{
  int info = 0;
  (*f6a)(&tao,&x,&d,ctx,&info);CHKERRQ(info);
  return 0;
}
static int ourtaoconstraintsfunction2(TAO_APPLICATION taoapp,Vec x,Vec d,void *ctx)
{
  int info = 0;
  (*f6)(&taoapp,&x,&d,ctx,&info);CHKERRQ(info);
  return 0;
}
EXTERN_C_BEGIN

void PETSC_STDCALL taosetpetscconstraintsfunction_(TAO_APPLICATION  *taoapp,Vec *r,void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,Vec*,void*,int*),void *ctx,int *info){
  f6a = func;
  *info = TaoSetPetscConstraintsFunction(*taoapp,*r,ourtaoconstraintsfunction,ctx);
}

void PETSC_STDCALL taoappsetconstraintroutine_(TAO_APPLICATION  *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,Vec*,void*,int*),void *ctx,int *info){
  f6 = func;
  *info = TaoAppSetConstraintRoutine(*taoapp,ourtaoconstraintsfunction2,ctx);
}

void PETSC_STDCALL taosetconstraintvec_(TAO_APPLICATION  *taoapp, Vec *r, int *info){
  *info = TaoAppSetFunctionVec(*taoapp,*r);
}

static void (PETSC_STDCALL *f7a)(TAO_SOLVER*,Vec*,Mat *,void*,int*);
static void (PETSC_STDCALL *f7)(TAO_APPLICATION*,Vec*,Mat *,Mat*, MatStructure*,void*,int*);
EXTERN_C_END
static int ourtaojacobianfunction(TAO_SOLVER tao,Vec x,Mat *J,void *ctx)
{
  int info = 0;
  (*f7a)(&tao,&x,J,ctx,&info);CHKERRQ(info);
  return 0;
}
static int ourtaojacobianfunction2(TAO_APPLICATION tao,Vec x,Mat *J,Mat *JP, MatStructure *flag,void *ctx)
{
  int info = 0;
  (*f7)(&tao,&x,J,JP,flag,ctx,&info);CHKERRQ(info);
  return 0;
}
EXTERN_C_BEGIN

void PETSC_STDCALL taosetpetscjacobian_(TAO_APPLICATION  *taoapp, Mat*J, void (PETSC_STDCALL *func)(TAO_SOLVER*,Vec*,Mat*,void*,int*),void *ctx,int *info){
  f7a = func;
  *info = TaoSetPetscJacobian(*taoapp,*J,ourtaojacobianfunction,ctx);
}

void PETSC_STDCALL taoappsetjacobianroutine_(TAO_APPLICATION  *taoapp,void (PETSC_STDCALL *func)(TAO_APPLICATION*,Vec*,Mat*,Mat*,MatStructure*,void*,int*),void *ctx,int *info){
  f7 = func;
  *info = TaoAppSetJacobianRoutine(*taoapp,ourtaojacobianfunction2,ctx);
}

void PETSC_STDCALL taosetjacobianmat_(TAO_APPLICATION  *taoapp,Mat *J, Mat *JP,int *info){
  *info = TaoAppSetJacobianMat(*taoapp,*J,*JP);
}


void PETSC_STDCALL taogetksp_(TAO_SOLVER  *tao,KSP *tksp, int *info ){
  *info = TaoGetKSP(*tao,tksp);
}

EXTERN_C_END

#include "taodaapplication.h"

/* Grid Application routines */
EXTERN_C_BEGIN
static void (PETSC_STDCALL *grid1)(TAO_APPLICATION*, DA*, Vec*, Mat*, void*, int*);
static void (PETSC_STDCALL *grid2)(TAO_APPLICATION*, DA*, Vec*, double*, Vec*, void*, int*);
static void (PETSC_STDCALL *grid3)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*);
static void (PETSC_STDCALL *grid4)(TAO_APPLICATION*, DA*, Vec*, double*, void*, int*);
static void (PETSC_STDCALL *grid5)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*);
static void (PETSC_STDCALL *grid6)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*);
static void (PETSC_STDCALL *grid7)(TAO_APPLICATION*, DA*, Vec*, Mat*, void*, int*);
static void (PETSC_STDCALL *grid8)(TAO_APPLICATION*, DA*, int*, void*, int*);
static void (PETSC_STDCALL *grid9)(TAO_APPLICATION*, DA*, int*, void*, int*);
/* Grid Application Element routines */
static void (PETSC_STDCALL *grid10)(int[2], double[4], double*, double[4], void*, int*);
static void (PETSC_STDCALL *grid11)(int[2], double[4], double[4][4], void*, int*);
EXTERN_C_END
static int ourdaappsethessianroutine(TAO_APPLICATION daapp, DA da, Vec x, Mat H, void *ctx) {
  int info = 0;
  (*grid1)(&daapp, &da, &x, &H, ctx, &info);
  return info;
}
static int ourdaappsetobjectiveandgradientroutine(TAO_APPLICATION daapp, DA da, Vec x, double *f, Vec G, void *ctx) {
  int info = 0;
  (*grid2)(&daapp, &da, &x, f, &G, ctx, &info);
  return info;
}
static int ourdaappsetgradientroutine(TAO_APPLICATION daapp, DA da, Vec x, Vec g, void *ctx) {
  int info = 0;
  (*grid3)(&daapp, &da, &x, &g, ctx, &info);
  return info;
}
static int ourdaappsetobjectiveroutine(TAO_APPLICATION daapp, DA da, Vec x, double *f, void *ctx) {
  int info = 0;
  (*grid4)(&daapp, &da, &x, f, ctx, &info);
  return info;
}
static int ourdaappsetvariableboundsroutine(TAO_APPLICATION daapp, DA da, Vec L, Vec U, void *ctx) {
  int info = 0;
  (*grid5)(&daapp, &da, &L, &U, ctx, &info);
  return info;
}
static int ourdaappsetconstraintroutine(TAO_APPLICATION daapp, DA da, Vec X, Vec R, void *ctx) {
  int info = 0;
  (*grid6)(&daapp, &da, &X, &R, ctx, &info);
  return info;
}
static int ourdaappsetjacobianroutine(TAO_APPLICATION daapp, DA da, Vec X, Mat J, void *ctx) {
  int info = 0;
  (*grid7)(&daapp, &da, &X, &J, ctx, &info);
  return info;
}
static int ourdaappsetbeforemonitor(TAO_APPLICATION daapp, DA da, int levels, void *ctx) {
  int info = 0;
  (*grid8)(&daapp, &da, &levels, ctx, &info);
  return info;
}
static int ourdaappsetaftermonitor(TAO_APPLICATION daapp, DA da, int levels, void *ctx) {
  int info = 0;
  (*grid9)(&daapp, &da, &levels, ctx, &info);
  return info;
}
static int ourdaappsetelementobjectiveandgradientroutine(int coord[2], double x[4], double *f, double g[4], void *ctx) {
  int info = 0;
  (*grid10)(coord, x, f, g, ctx, &info);
  return info;
}
static int ourdaappsetelementhessianroutine(int coord[2], double x[4], double H[4][4], void *ctx) {
  int info = 0;
  (*grid11)(coord, x, H, ctx, &info);
  return info;
}
EXTERN_C_BEGIN
void PETSC_STDCALL daappsethessianroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*,DA*,Vec*, Mat*, void*, int*),void *ctx, int *info) {
  grid1 = func;
  *info = DAAppSetHessianRoutine(*daapp, ourdaappsethessianroutine, ctx);
}
void PETSC_STDCALL daappsetobjectiveandgradientroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, double*, Vec*, void*, int*), void *ctx, int *info) {
  grid2 = func;
  *info = DAAppSetObjectiveAndGradientRoutine(*daapp, ourdaappsetobjectiveandgradientroutine, ctx);
}
void PETSC_STDCALL daappsetobjectiveandgradientrou_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, double*, Vec*, void*, int*), void *ctx, int *info) {
  grid2 = func;
  *info = DAAppSetObjectiveAndGradientRoutine(*daapp, ourdaappsetobjectiveandgradientroutine, ctx);
}

void PETSC_STDCALL daappsetgradientroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*), void *ctx, int *info) {
  grid3 = func;
  *info = DAAppSetGradientRoutine(*daapp, ourdaappsetgradientroutine, ctx);
}
void PETSC_STDCALL daappsetobjectiveroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, double*, void*, int*), void *ctx, int *info) {
  grid4 = func;
  *info = DAAppSetObjectiveRoutine(*daapp, ourdaappsetobjectiveroutine, ctx);
}
void PETSC_STDCALL daappsetvariableboundsroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*), void *ctx, int *info) {
  grid5 = func;
  *info = DAAppSetVariableBoundsRoutine(*daapp, ourdaappsetvariableboundsroutine, ctx);
}
void PETSC_STDCALL daappsetconstraintroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, Vec*, void*, int*), void *ctx, int *info) {
  grid6 = func;
  *info = DAAppSetConstraintRoutine(*daapp, ourdaappsetconstraintroutine, ctx);
}
void PETSC_STDCALL daappsetjacobianroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, Vec*, Mat*, void*, int*), void *ctx, int *info) {
  grid7 = func;
  *info = DAAppSetJacobianRoutine(*daapp, ourdaappsetjacobianroutine, ctx);
}
void PETSC_STDCALL daappsetbeforemonitor_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, int*, void*, int*), void *ctx, int *info) {
  grid8 = func;
  *info = DAAppSetBeforeMonitor(*daapp, ourdaappsetbeforemonitor, ctx);
}
void PETSC_STDCALL daappsetaftermonitor_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(TAO_APPLICATION*, DA*, int*, void*, int*), void *ctx, int *info) {
  grid9 = func;
  *info = DAAppSetAfterMonitor(*daapp, ourdaappsetaftermonitor, ctx);
}
void PETSC_STDCALL daappsetelementobjectiveandgradientroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(int[2], double[4], double*, double[4], void*, int*), int *flops, void *ctx, int *info) {
  grid10 = func;
  *info = DAAppSetElementObjectiveAndGradientRoutine(*daapp, ourdaappsetelementobjectiveandgradientroutine, *flops, ctx);
}
void PETSC_STDCALL daappsetelementobjectiveandgrad_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(int[2], double[4], double*, double[4], void*, int*), int *flops, void *ctx, int *info) {
  grid10 = func;
  *info = DAAppSetElementObjectiveAndGradientRoutine(*daapp, ourdaappsetelementobjectiveandgradientroutine, *flops, ctx);
}
void PETSC_STDCALL daappsetelementhessianroutine_(TAO_APPLICATION *daapp, void (PETSC_STDCALL *func)(int[2], double[4], double[4][4], void*, int*), int *flops, void *ctx, int *info) {
  grid11 = func;
  *info = DAAppSetElementHessianRoutine(*daapp, ourdaappsetelementhessianroutine, *flops, ctx);
}
EXTERN_C_END
