#include "tao_general.h"

#ifdef TAO_USE_PETSC

#include "taovec_petsc.h"
#include "../indexset/taois_petsc.h"

int VecMedian(Vec, Vec, Vec, Vec);
int VecPointwiseMax(Vec, Vec, Vec);
int VecPointwiseMin(Vec, Vec, Vec);
int VecFischer(Vec, Vec, Vec, Vec, Vec);
int VecSFischer(Vec, Vec, Vec, Vec, double, Vec);
int VecBoundProjection(Vec, Vec, Vec, Vec, Vec);
int VecCreateSubVec(Vec, IS, Vec *);
int VecISAXPY(Vec, double, Vec, IS);
int VecStepMax(Vec, Vec, double*);
int VecStepMax2(Vec, Vec,Vec, Vec, double*);
int VecCompare(Vec, Vec, PetscTruth *);
int VecBoundStepInfo(Vec, Vec, Vec, Vec, PetscReal *, PetscReal *, PetscReal *);

static int petscminmaxevent=0;

#undef __FUNCT__
#define __FUNCT__ "TaoWrapPetscVec"
/*@C
   TaoWrapPetscVec - Creates a new TaoVec object using an existing
   PETSc Vec.

   Input Parameter:
+  V -  a PETSc vector
-  TV -  the address of a pointer to a TaoVecPetsc

   Output Parameter:
.  TV - pointer to a new TaoVecPetsc

   Note:  A TaoVecPetsc is an object with the methods of an abstract
   TaoVec object.  A TaoVecPetsc contains an implementation of the TaoVec
   methods.  Routines using these vectors should declare a pointer to 
   a TaoVec, assign this pointer to the address of a TaoVec object, 
   use the pointer to invoke methods on the object, and use this pointer
   as an argument when calling other routines.  This usage is different
   from the usage of a PETSc Vec.  In PETSc, applications will typically
   declare a Vec, and pass it as an argument into routines.  That is,
   applications will typically declare a pointer to a TaoVec and use the
   pointer, or declare a Vec and use it directly.
  
   Note:
   The user us repsonsible for destroying the Vec V, in addition to
   to TaoVecPetsc vector TV.  The Vec can be destroyed immediately
   after this routine.

   Level: developer

.seealso TaoVecGetPetscVec(), TaoVecDestroy()

@*/
int TaoWrapPetscVec( Vec V, TaoVecPetsc* *TV){
  int info;
  PetscFunctionBegin;
  *TV = new  TaoVecPetsc(V);
  info=(*TV)->SetVec(V); CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecGetPetscVec"
/*@C
   TaoVecGetPetscVec - Set the address of a Vec equal to the location
   of the underlying Vec structure in this TaoVecPetsc object. 

   Input Parameter:
+  TV - the TaoVecPetsc 
-  V -  the address of Vec

   Output Parameter:
.  V -  the address of a specific Vec

   Note:  
   This routine does not create a Vec.  It sets a pointer
   to the location of an existing Vec.

   Note:
   The underlying PETSc Vec may also be obtained by
   Vec VV = (Vec) TV->VecObject;

   Note:
   
   VecObject is a void* pointer that can be cast to the underlying Vec object.

   Level: advanced

@*/
int TaoVecGetPetscVec( TaoVec* TV, Vec *V){
  PetscFunctionBegin;
  if (TV && V){
    *V=(Vec)(TV->VecObject);
  } else if (V){
    *V=0;
  }
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::TaoVecPetsc"
TaoVecPetsc::TaoVecPetsc(Vec VV){
  this->pv=0;
  this->pvecviewer=0;
  if (VV){ 
    this->SetVec(VV);
  }
  if (petscminmaxevent==0){
    PetscLogEventRegister(&petscminmaxevent,"PointwiseMinMax",VEC_COOKIE);
  }
  return;
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::~TaoVecPetsc"
TaoVecPetsc::~TaoVecPetsc(){
  this->SetVec(0);
  return;
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SetVec"
/*@C
   SetVec - Set or replace the underlying Vec object in this TaoVec.

   Input Parameter:
.  V -  a PETSc vector

   Note:
   The user us repsonsible for destroying the Vec V, in addition to
   to TaoVecPetsc vector TV.  The Vec can be destroyed immediately
   after this routine.

   Level: developer

.seealso TaoWrapPetscVec(), TaoVecDestroy()

@*/
int TaoVecPetsc::SetVec(Vec VV){
  int info;
  PetscFunctionBegin;
  if (VV){
    PetscValidHeaderSpecific(VV,VEC_COOKIE,1);
    PetscObjectReference((PetscObject)VV); 
    //    info = PetscLogInfo((VV,"Set the PETSc Vec in a TaoVec .\n")); CHKERRQ(info);
  }
  if (this->pv){
    info=VecDestroy(this->pv); CHKERRQ(info);
  }
  this->pv=VV;
  this->VecObject=(void*)VV;
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Clone"
int TaoVecPetsc::Clone(TaoVec**ntv){
  int info;
  TaoVecPetsc *nptv;
  Vec npv;
  PetscFunctionBegin;
  info=VecDuplicate(pv,&npv); CHKERRQ(info);
  info = TaoWrapPetscVec(npv,&nptv); CHKERRQ(info);
  *ntv=nptv;
  info = VecDestroy(npv); CHKERRQ(info);
  nptv->pvecviewer=this->pvecviewer;
  PetscFunctionReturn(0);
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Compatible"
int TaoVecPetsc::Compatible(TaoVec *tv, TaoTruth *flag){
  TaoVecPetsc *vv = (TaoVecPetsc *)(tv);
  PetscTruth flg=PETSC_TRUE;
  int info=0;

  PetscFunctionBegin;
  if (vv==0){
    *flag=TAO_FALSE;
    PetscFunctionReturn(0);
  }
  info = VecCompare(pv, vv->pv, &flg); CHKERRQ(info);
  if (flg==PETSC_FALSE){
    *flag=TAO_FALSE;
  } else {
    *flag=TAO_TRUE;
  }
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SetToConstant"
int TaoVecPetsc::SetToConstant( double cc ){
  int info;
  PetscScalar c=cc;
  PetscFunctionBegin;
  info=VecSet(pv, c);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SetToZero"
int TaoVecPetsc::SetToZero(){
  PetscScalar zero=0.0;
  int info;
  PetscFunctionBegin;
  info=VecSet(pv, zero);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::CopyFrom"
int TaoVecPetsc::CopyFrom( TaoVec* tv ){
  Vec pv2 = (Vec)(tv->VecObject);
  int info;
  PetscFunctionBegin;
  info=VecCopy(pv2,pv);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::ScaleCopyFrom"
int TaoVecPetsc::ScaleCopyFrom( double a, TaoVec* tv ){
  Vec v = (Vec) tv->VecObject;
  PetscScalar alpha=a, zero=0.0;
  int info;
  PetscFunctionBegin;
  info=VecAXPBY(this->pv,alpha,zero,v);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::NormInfinity"
int TaoVecPetsc::NormInfinity(double *vnorm){
  int info;
  PetscReal vv;
  PetscFunctionBegin;
  info=VecNorm(pv,NORM_INFINITY,&vv);  CHKERRQ(info);
  *vnorm=(double)vv;
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Norm1"
int TaoVecPetsc::Norm1(double *vnorm){
  int info;
  PetscReal vv;
  PetscFunctionBegin;
  info=VecNorm(pv,NORM_1,&vv);  CHKERRQ(info);
  *vnorm=(double)vv;
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Norm2"
int TaoVecPetsc::Norm2(double *vnorm){
  int info;
  PetscReal vv;
  PetscFunctionBegin;
  info=VecNorm(pv,NORM_2,&vv);  CHKERRQ(info);
  *vnorm=(double)vv;
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Norm2squared"
int TaoVecPetsc::Norm2squared(double *vnorm){
  int info;
  PetscReal vv;
  PetscFunctionBegin;
  info=VecNorm(pv,NORM_2,&vv);  CHKERRQ(info);
  *vnorm=(double)(vv*vv);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Scale"
int TaoVecPetsc::Scale( double alpha ){
  int info;
  PetscScalar aalpha=alpha;
  PetscFunctionBegin;
  info=VecScale(pv, aalpha);  CHKERRQ(info);
  PetscFunctionReturn(0);
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Axpy"
int TaoVecPetsc::Axpy( double alpha, TaoVec* tv ){
  Vec v = (Vec) tv->VecObject;
  PetscScalar aalpha=alpha;
  int info;
  PetscFunctionBegin;
  info=VecAXPY(this->pv, aalpha, v);  CHKERRQ(info);
  PetscFunctionReturn(0);
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Axpby"
int TaoVecPetsc::Axpby( double alpha, TaoVec* tv, double beta ){
  Vec v = (Vec) tv->VecObject;
  PetscScalar aalpha = alpha, bbeta = beta;
  int info;
  PetscFunctionBegin;
  info=VecAXPBY(this->pv,aalpha,bbeta,v);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Aypx"
int TaoVecPetsc::Aypx( double alpha, TaoVec* x ){
  Vec X = (Vec) x->VecObject;
  PetscScalar aalpha = alpha;
  int info;
  PetscFunctionBegin;
  info=VecAYPX(this->pv,aalpha,X);  CHKERRQ(info);
  PetscFunctionReturn(0);
}
 
#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::AddConstant"
int TaoVecPetsc::AddConstant( double cc ){
  int info;
  PetscScalar c=cc;
  PetscFunctionBegin;
  info=VecShift(pv, c);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Dot"
int TaoVecPetsc::Dot( TaoVec* tv, double *vDotv ){
  Vec v = (Vec) tv->VecObject;
  PetscScalar c;
  int info;
  PetscFunctionBegin;
  info=VecDot(v,this->pv,&c);  CHKERRQ(info);
  *vDotv=c;
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Negate"
int TaoVecPetsc::Negate(){ 
  PetscScalar m1=-1.0; 
  int info;
  PetscFunctionBegin;
  info=VecScale(pv, m1);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Reciprocal"
int TaoVecPetsc::Reciprocal(){ 
  int info;
  PetscFunctionBegin;
  info=VecReciprocal(pv);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::GetDimension"
int TaoVecPetsc::GetDimension(int *n){
  int info;
  PetscFunctionBegin;
  info=VecGetSize(pv,n);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::PointwiseMultiply"
int TaoVecPetsc::PointwiseMultiply( TaoVec* tv, TaoVec* tw ){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  int info;
  PetscFunctionBegin;
  info=VecPointwiseMult(this->pv, w, v);  CHKERRQ(info);
  PetscFunctionReturn(0);
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::PointwiseDivide"
int TaoVecPetsc::PointwiseDivide( TaoVec* tv , TaoVec* tw){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  int info;
  PetscFunctionBegin;
  info=VecPointwiseDivide(this->pv, v, w);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Median"
int TaoVecPetsc::Median( TaoVec* tv, TaoVec* tw, TaoVec* tx){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  Vec x = (Vec) tx->VecObject;
  int info;
  PetscFunctionBegin;
  info=PetscLogEventBegin(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  info=VecMedian(v,w,x,this->pv); CHKERRQ(info);
  info=PetscLogEventEnd(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::PointwiseMinimum"
int TaoVecPetsc::PointwiseMinimum( TaoVec* tv, TaoVec* tw){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  int info;
  PetscFunctionBegin;
  info=PetscLogEventBegin(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  info=VecPointwiseMin(this->pv, w, v); CHKERRQ(info);
  info=PetscLogEventEnd(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Fischer"
int TaoVecPetsc::Fischer(TaoVec *tx, TaoVec *tf, TaoVec *tl, TaoVec *tu) 
{
  TaoVecPetsc *xx = (TaoVecPetsc *)(tx);
  TaoVecPetsc *ff = (TaoVecPetsc *)(tf);
  TaoVecPetsc *ll = (TaoVecPetsc *)(tl);
  TaoVecPetsc *uu = (TaoVecPetsc *)(tu);
  int info;

  PetscFunctionBegin;
  info=VecFischer(xx->pv, ff->pv, ll->pv, uu->pv, pv); CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SFischer"
int TaoVecPetsc::SFischer(TaoVec *tx, TaoVec *tf,
                          TaoVec *tl, TaoVec *tu, double mu)
{
  TaoVecPetsc *xx = (TaoVecPetsc *)(tx);
  TaoVecPetsc *ff = (TaoVecPetsc *)(tf);
  TaoVecPetsc *ll = (TaoVecPetsc *)(tl);
  TaoVecPetsc *uu = (TaoVecPetsc *)(tu);
  int info;

  PetscFunctionBegin;
  if ((mu >= -TAO_EPSILON) && (mu <= TAO_EPSILON)) {
    Fischer(tx, tf, tl, tu);
  }
  else {
    info=VecSFischer(xx->pv, ff->pv, ll->pv, uu->pv, mu, pv); CHKERRQ(info);
  }
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::PointwiseMaximum"
int TaoVecPetsc::PointwiseMaximum( TaoVec* tv, TaoVec* tw){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  int info;
  PetscFunctionBegin;
  info=PetscLogEventBegin(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  info=VecPointwiseMax(this->pv, w, v);  CHKERRQ(info);
  info=PetscLogEventEnd(petscminmaxevent,0,0,0,0); CHKERRQ(info);
  PetscFunctionReturn(0); 
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::Waxpby"
int TaoVecPetsc::Waxpby  ( double aa, TaoVec* tv, double bb, TaoVec* tw){
  Vec v = (Vec) tv->VecObject;
  Vec w = (Vec) tw->VecObject;
  int info;
  PetscScalar a=aa, b=bb, zero=0.0;

  PetscFunctionBegin;
  if (a==1){
    info = VecWAXPY(this->pv,b,w,v); CHKERRQ(info);
  } else if (b==1) {
    info = VecWAXPY(this->pv,a,v,w); CHKERRQ(info);
  } else if (a==0) {
    info = VecSet(pv, zero); CHKERRQ(info);
    info = VecAXPY(this->pv, b, w); CHKERRQ(info);
  } else if (b==0) {
    info = VecSet(pv, zero); CHKERRQ(info);
    info = VecAXPY(this->pv, a, v); CHKERRQ(info);
  } else {    
    info = VecCopy(w,pv); CHKERRQ(info);
    info = VecAXPBY(this->pv,a,b,v); CHKERRQ(info);
  }
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::AbsoluteValue"
int TaoVecPetsc::AbsoluteValue(){
  int info;
  PetscFunctionBegin;
  info=VecAbs(pv);  CHKERRQ(info);
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::min"
int TaoVecPetsc::MinElement(double*val){
  int info, p;
  PetscScalar a;
  PetscFunctionBegin;
  info = VecMin(this->pv,&p, &a);CHKERRQ(info);
  *val=a;
  PetscFunctionReturn(0);  
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::GetArray"
int TaoVecPetsc::GetArray(TaoScalar **dptr, int *n){
  int info;
  PetscScalar *pptr;
  PetscFunctionBegin;
  if (sizeof(TaoScalar)==sizeof(PetscScalar)){
    info = VecGetLocalSize(pv,n);CHKERRQ(info);
    info = VecGetArray(pv,&pptr);CHKERRQ(info);
    *dptr=(TaoScalar*)pptr;
  } else {
    SETERRQ(1,"Incompatible data types");
  }
  PetscFunctionReturn(0);
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::RestoreArray"
int TaoVecPetsc::RestoreArray(TaoScalar **dptr,int *n){
  int info;
  PetscScalar *pptr;
  PetscFunctionBegin;
  if (sizeof(TaoScalar)==sizeof(PetscScalar)){
    pptr=(PetscScalar*)(*dptr);
    info = VecRestoreArray(pv,&pptr); CHKERRQ(info);
    *dptr=PETSC_NULL;
    *n=0;
  } else {
    SETERRQ(1,"Incompatible data types");
  }
  PetscFunctionReturn(0);
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SetReducedVec"
int TaoVecPetsc::SetReducedVec(TaoVec*VV,TaoIndexSet*SS){
  int info,nn,nnn,nred;
  TaoPetscISType type;
  Vec R, V = (Vec) VV->VecObject;
  TaoIndexSetPetsc *TSS = (TaoIndexSetPetsc*) SS;
  IS S2;
  MPI_Comm comm;

  PetscFunctionBegin;
  info = SS->GetSize(&nn); CHKERRQ(info); 
  info = VV->GetDimension(&nnn); CHKERRQ(info); 
  info = TSS->GetReducedType(&type); CHKERRQ(info);
  if (type==TaoMaskFullSpace){

  } else if (nn==nnn){
    info = VecDuplicate(V,&R); CHKERRQ(info);
    info = this->SetVec(R); CHKERRQ(info);
    PetscObjectDereference((PetscObject)R);
  } else {
    info = TSS->RedistributeIS(&S2); CHKERRQ(info);
    info = ISGetLocalSize(S2,&nred); CHKERRQ(info);
    info = PetscObjectGetComm((PetscObject)V,&comm);CHKERRQ(info);
    info = VecCreateMPI(comm,nred,nn,&R);CHKERRQ(info);
    info = this->SetVec(R); CHKERRQ(info);
    PetscObjectDereference((PetscObject)R);
  }
  info=this->ReducedCopyFromFull(VV,SS);CHKERRQ(info);

  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::ReducedXPY"
int TaoVecPetsc::ReducedXPY(TaoVec*VV,TaoIndexSet*SS){
  VecScatter scatterit;
  TaoIndexSetPetsc *TSS = (TaoIndexSetPetsc*) SS;
  Vec R = (Vec) VV->VecObject;
  Vec V=this->pv;
  int info;

  PetscFunctionBegin;

  info = TSS->GetReducedVecScatter(R,V, &scatterit);CHKERRQ(info); 
  
  info = VecScatterBegin(R,V,ADD_VALUES,SCATTER_REVERSE,scatterit);
  CHKERRQ(info); 
  info = VecScatterEnd(R,V,ADD_VALUES,SCATTER_REVERSE, scatterit);
  CHKERRQ(info);

  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::ReducedCopyFromFull"
int TaoVecPetsc::ReducedCopyFromFull(TaoVec*VV,TaoIndexSet*SS){
  int info;
  PetscScalar zero=0.0;
  TaoIndexSetPetsc *TSS = (TaoIndexSetPetsc*) SS;
  VecScatter scatterit;
  Vec V = (Vec) VV->VecObject;
  Vec R=this->pv;

  PetscFunctionBegin;

  info = VecSet(R, zero); CHKERRQ(info); 
  info = TSS->GetReducedVecScatter(V,R, &scatterit);CHKERRQ(info); 
  info = VecScatterBegin(V,R,INSERT_VALUES,SCATTER_FORWARD,scatterit);
  CHKERRQ(info); 
  info = VecScatterEnd(V,R,INSERT_VALUES,SCATTER_FORWARD, scatterit);
  CHKERRQ(info);

  PetscFunctionReturn(0);  
}



#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::StepMax"
int TaoVecPetsc::StepMax(TaoVec*tv,double*step){
  Vec dx = (Vec) tv->VecObject;
  PetscReal pstep;
  int info;
  PetscFunctionBegin;
  info = VecStepMax(this->pv, dx,&pstep);CHKERRQ(info);
  *step=pstep;
  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::StepBoundInfo"
int TaoVecPetsc::StepBoundInfo(TaoVec *TXL ,TaoVec *TXU, TaoVec*S, double* bmin1,double* bmin2, double* bmax){
  int info;
  PetscReal p1,p2,p3;
  Vec X=(Vec)this->VecObject, DX=(Vec)S->VecObject;
  Vec XL=(Vec)TXL->VecObject, XU=(Vec)TXU->VecObject;
  PetscFunctionBegin;
  info=VecBoundStepInfo(X,XL,XU,DX,&p1,&p2,&p3); CHKERRQ(info);
  *bmin1=p1; *bmin2=p2; *bmax=p3;
  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::SetPetscViewer"
/*@C
   SetPetscViewer

   Input Parameter:
.  viewer - a viewer object to be used with this->View() and VecView()

   Level: advanced

@*/
int TaoVecPetsc::SetPetscViewer(PetscViewer viewer){
  PetscFunctionBegin;  
  this->pvecviewer= viewer;
  PetscFunctionReturn(0);  
}


#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::View"
int TaoVecPetsc::View(){
  int info;
  PetscFunctionBegin;  
  info=VecView(this->pv,this->pvecviewer);CHKERRQ(info);
  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::BoundGradientProjection"
int TaoVecPetsc::BoundGradientProjection(TaoVec*GG,TaoVec*XXL,TaoVec*XX, TaoVec*XXU){
  Vec v = (Vec) XXL->VecObject;
  Vec w = (Vec) XXU->VecObject;
  Vec x = (Vec) XX->VecObject;
  Vec g = (Vec) GG->VecObject;
  int info;
  PetscFunctionBegin;
  info = PetscLogEventBegin(petscminmaxevent,0,0,0,0);CHKERRQ(info);
  info = VecBoundProjection(g,x,v,w,this->pv);CHKERRQ(info);
  info = PetscLogEventEnd(petscminmaxevent,0,0,0,0);CHKERRQ(info);
  PetscFunctionReturn(0);  
}

#undef __FUNCT__
#define __FUNCT__ "TaoVecPetsc::CreateIndexSet"
int TaoVecPetsc::CreateIndexSet(TaoIndexSet**SSS){
  TaoIndexSetPetsc *SS;

  PetscFunctionBegin;  
  SS = new TaoIndexSetPetsc(this->pv);
  *SSS=SS;
  PetscFunctionReturn(0);  
}


#endif





