// 
// File:          TaoSolver_Component_Impl.cc
// Symbol:        TaoSolver.Component-v0.0.3
// Symbol Type:   class
// Babel Version: 0.10.2
// Description:   Server-side implementation for TaoSolver.Component
// 
// WARNING: Automatically generated; only changes within splicers preserved
// 
// babel-version = 0.10.2
// 
#include "TaoSolver_Component_Impl.hh"

// DO-NOT-DELETE splicer.begin(TaoSolver.Component._includes)
#include <iostream>
#include <ctype.h>
#include "sidl.hh"
#include "Solver_OptimizationSolver.hh"
#include "Solver_ProjectState.hh"
#include "Solver_TerminateReason.hh"
#include "gov_cca_Port.hh"
#include "gov_cca_Services.hh"

#include "parameters/parametersStar.h"
#include "port/portInterfaces.h"
#include "port/supportInterfaces.h"
#include "dc/babel/babel-cca/server/ccaffeine_ports_PortTranslator.hh"
// DO-NOT-DELETE splicer.end(TaoSolver.Component._includes)

// user-defined constructor.
void TaoSolver::Component_impl::_ctor() {
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component._ctor)
  this->tao_environment = 0;
  this->tao = 0;
  this->model = 0;
  this->myServices = 0;
  //  this->dynTestDone = false;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component._ctor)
}

// user-defined destructor.
void TaoSolver::Component_impl::_dtor() {
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component._dtor)
  
  // DO-NOT-DELETE splicer.end(TaoSolver.Component._dtor)
}

// static class initializer.
void TaoSolver::Component_impl::_load() {
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component._load)
  // Insert-Code-Here {TaoSolver.Component._load} (class initialization)
  // DO-NOT-DELETE splicer.end(TaoSolver.Component._load)
}

// user-defined static methods: (none)

// user-defined non-static methods:
/**
 * Starts up a component presence in the calling framework.
 * @param Svc the component instance's handle on the framework world.
 * Contracts concerning Svc and setServices:
 * 
 * The component interaction with the CCA framework
 * and Ports begins on the call to setServices by the framework.
 * 
 * This function is called exactly once for each instance created
 * by the framework.
 * 
 * The argument Svc will never be nil/null.
 * 
 * Those uses ports which are automatically connected by the framework
 * (so-called service-ports) may be obtained via getPort during
 * setServices.
 */
void
TaoSolver::Component_impl::setServices (
  /* in */ ::gov::cca::Services services ) 
throw ( 
  ::gov::cca::CCAException
){
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.setServices)
  if (services._is_nil()) {
    return;
  }
  gov::cca::Port myport = self;
  std::cout << "cat myport=self..." << std::endl;
  if (myport._is_nil()) {
    std::cerr << "unable to cast self as port (TaoSolver::Component_impl) in TaoSolver::Component_impl::setServices" << std::endl;
  }
  
  myServices = services;
  if (myServices._is_nil()) {
    std::cout << "myServices is nil" << std::endl;
    return;
  }

  gov::cca::TypeMap tm = myServices.createTypeMap(); // empty typemap
  std::cout << "created typemap..." << std::endl;




  try {
    myServices.addProvidesPort(self,
			       ::std::string("OptimizationSolver"),
			       ::std::string("OptimizationPorts.SolverPort"),
			       0);
  } catch (gov::cca::CCAException e) {
    std::cerr << "Error adding providesPort in TaoSolver: " << e.getNote() << std::endl;
  }


  try { 
    myServices.registerUsesPort(::std::string("OptimizationModel"),
				::std::string("OptimizationPorts.ModelPort"),
				0);
  } catch (gov::cca::CCAException e) {
    std::cerr << "Error adding providesPort in TaoSolver: " << e.getNote() << std::endl;
  }
    
  

  try {
    this->myServices.registerUsesPort("classicParam",
                                      "gov.cca.ParameterPortFactoryService",
                                      tm);
  } catch (gov::cca::CCAException e) {
    std::cerr << "Error registering 'classicParam' usesPort in TaoSolver: " << e.getNote() << std::endl;
  }


  gov::cca::Port p = myServices.getPort("classicParam");
  std::cout << "set p to classicParam..." << std::endl;

  // Get the underlying classic parameter port
  ccaffeine::ports::PortTranslator portX = p;
  std::cout << "cast p to portX ..." << std::endl;

  if (portX._not_nil()) {
    classic::gov::cca::Port *cp =
      static_cast<classic::gov::cca::Port *>(portX.getClassicPort());
    std::cout << "cast p to portX.getClassicPort() to cp ..." << std::endl;
    if (!cp) 
     std::cerr << "Could not cast classic port to classic::gov::cca::Port" << std::endl;

    ConfigurableParameterFactory *cpf =0;
    cpf =  dynamic_cast<ConfigurableParameterFactory *>(cp);
    std::cout << "cast cp to cpf ..." << std::endl;

    if (!cpf)
      std::cerr << "could not cast port to ConfigurableParameterFactory" << std::endl;
    ConfigurableParameterPort *cpp = 0;

    std::cout << "calling setupParameters ..." << std::endl;
    cpp = setupParameters(cpf);

    classic::gov::cca::Port *clscp = dynamic_cast<classic::gov::cca::Port*>(cpp);
    std::cout << "cast cpp to clscp" << std::endl;
    if (clscp == NULL)
      std::cerr << "Cannot cast ConfigurableParameterPort* to classic::gov::cca::Port*" << std::endl;

    // Pass the configurable parameter port to the Port Translator
    void * vp = static_cast<void*>(clscp);
    std::cout << "cast clscp to vp" << std::endl;
    if (!vp) {
      std::cerr << "Could not cast clscp to void*" << std::endl;
    }

    ccaffeine::ports::PortTranslator provideX =
      ccaffeine::ports::PortTranslator::createFromClassic(vp);
    std::cout << "created provideX" << std::endl;

    // Add the configure port we want to provide
    myServices.addProvidesPort(provideX, "configure", "ParameterPort", tm);
    std::cout << "added provides port" <<std::endl;

    // release classic parameter
    //    myServices.releasePort("classicParam");
    //    myServices.unregisterUsesPort("classicParam");
    std::cout << "released classicParam" << std::endl;
  }

  std::cout << "paramport stuff done..." << std::endl;
  try {
    myServices.registerUsesPort(::std::string("LAFactory"),
				::std::string("OptimizationPorts.LAFactoryPort"),
				0);
  } catch (gov::cca::CCAException e) {
    std::cerr << "Error registering UsesPort in TaoSolver: " << e.getNote() << std::endl;
  }

  // DO-NOT-DELETE splicer.end(TaoSolver.Component.setServices)
}

/**
 * Method:  Create[]
 */
int32_t
TaoSolver::Component_impl::Create (
  /* in */ const ::std::string& method ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.Create)
  int info;
  info = tao.Create(method);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.Create)
}

/**
 * Method:  Destroy[]
 */
int32_t
TaoSolver::Component_impl::Destroy ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.Destroy)
  int info;
  info = tao.Destroy();
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.Destroy)
}

/**
 * Method:  SetTolerances[]
 */
int32_t
TaoSolver::Component_impl::SetTolerances (
  /* in */ double fatol,
  /* in */ double frtol,
  /* in */ double catol,
  /* in */ double crtol ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetTolerances)
  int info;
  info = tao.SetTolerances(fatol, frtol, catol, crtol);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetTolerances)
}

/**
 * Method:  SolveApplication[]
 */
int32_t
TaoSolver::Component_impl::SolveApplication (
  /* in */ ::Optimize::OptimizationModel app ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SolveApplication)
  int info;
  info = tao.SolveApplication(app);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SolveApplication)
}

/**
 * Method:  View[]
 */
int32_t
TaoSolver::Component_impl::View ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.View)
  int info;
  info = tao.View();
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.View)
}

/**
 * Method:  GetIterationData[]
 */
int32_t
TaoSolver::Component_impl::GetIterationData (
  /* out */ int32_t& iterate,
  /* out */ double& f,
  /* out */ double& gnorm,
  /* out */ double& cnorm,
  /* out */ double& xdiff,
  /* out */ ::Solver::TerminateReason& reason ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.GetIterationData)
  int info;
  info = tao.GetIterationData(iterate,f,gnorm,cnorm,xdiff,reason);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.GetIterationData)
}

/**
 * Method:  GetMethod[]
 */
int32_t
TaoSolver::Component_impl::GetMethod (
  /* out */ ::std::string& type ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.GetMethod)
  int info;
  info = tao.GetMethod(type);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.GetMethod)
}

/**
 * Method:  SetFunctionLowerBound[]
 */
int32_t
TaoSolver::Component_impl::SetFunctionLowerBound (
  /* in */ double fmin ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetFunctionLowerBound)
  int info;
  info = tao.SetFunctionLowerBound(fmin);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetFunctionLowerBound)
}

/**
 * Method:  GetGradientTolerances[]
 */
int32_t
TaoSolver::Component_impl::GetGradientTolerances (
  /* out */ double& gatol,
  /* out */ double& grtol,
  /* out */ double& gttol ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.GetGradientTolerances)
  int info;
  info = tao.GetGradientTolerances(gatol, grtol, gttol);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.GetGradientTolerances)
}

/**
 * Method:  SetGradientTolerances[]
 */
int32_t
TaoSolver::Component_impl::SetGradientTolerances (
  /* in */ double gatol,
  /* in */ double grtol,
  /* in */ double gttol ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetGradientTolerances)
  int info;
  info = tao.SetGradientTolerances(gatol, grtol, gttol);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetGradientTolerances)
}

/**
 * Method:  SetMaximumFunctionEvaluations[]
 */
int32_t
TaoSolver::Component_impl::SetMaximumFunctionEvaluations (
  /* in */ int32_t nfcn ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetMaximumFunctionEvaluations)
  int info;
  info = tao.SetMaximumFunctionEvaluations(nfcn);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetMaximumFunctionEvaluations)
}

/**
 * Method:  SetMaximumIterates[]
 */
int32_t
TaoSolver::Component_impl::SetMaximumIterates (
  /* in */ int32_t maxits ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetMaximumIterates)
  int info;
  info = tao.SetMaximumIterates(maxits);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetMaximumIterates)
}

/**
 * Method:  SetMethod[]
 */
int32_t
TaoSolver::Component_impl::SetMethod (
  /* in */ const ::std::string& type ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetMethod)
  int info;
  info = tao.SetMethod(type);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetMethod)
}

/**
 * Method:  SetLAFactory[]
 */
int32_t
TaoSolver::Component_impl::SetLAFactory (
  /* in */ ::LinearAlgebra::Factory factory ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetLAFactory)
  int info;
  info = tao.SetLAFactory(factory);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetLAFactory)
}

/**
 * Method:  SetFromOptions[]
 */
int32_t
TaoSolver::Component_impl::SetFromOptions ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.SetFromOptions)
  int info;
  info = tao.SetFromOptions();
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.SetFromOptions)
}

/**
 * Method:  GetSolverHandle[]
 */
int32_t
TaoSolver::Component_impl::GetSolverHandle (
  /* out */ void*& handle ) 
throw () 
{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.GetSolverHandle)
  int info;
  info = tao.GetSolverHandle(handle);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.GetSolverHandle)
}

/**
 * Method:  Initialize[]
 */
int32_t
TaoSolver::Component_impl::Initialize ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.Initialize)
  int info;   
  sidl::DLL envdll = sidl::Loader::findLibrary("TAO.Environment", "ior/impl", sidl::Scope_GLOBAL, sidl::Resolve_SCLRESOLVE);
  sidl::DLL soldll = sidl::Loader::findLibrary("TAO.Solver", "ior/impl", sidl::Scope_GLOBAL, sidl::Resolve_SCLRESOLVE);
  if (envdll._not_nil() && soldll._not_nil()) {
    this->tao_environment = envdll.createClass("TAO.Environment");
    this->tao = soldll.createClass("TAO.Solver");
  } else {
    std::cout <<"Could not load TAO.Solver. Check SIDL_DLL_PATH." << std::endl;
    return -1;
  }


  gov::cca::Port myModelPort = myServices.getPort("OptimizationModel");
  
  this->model = myModelPort;

  gov::cca::Port myFactoryPort = myServices.getPort("LAFactory");
  if (myFactoryPort._is_nil()) {
    std::cout << "Could not find LAFactory component -- using default PETSc" << std::endl;
    this->factory = 0;
  } else {
    this->factory = myFactoryPort;
    this->factory.initialize();
  }

  // parse options string (% delimited string)
  sidl::array<std::string> args;
  if (strncmp(options->value,"",1)) {
    int i,argc=1;
    char *charPtr=options->value;
    // Count # of delimiters
    while (*charPtr && !isspace(*charPtr)) {
      if (*charPtr == '%') {
	*charPtr = 0;
	if (charPtr != options->value && *(charPtr-1))
	  argc++;
      } 
      charPtr++;
    }
    
    //reset charPtr to start
    charPtr = options->value;
    args = sidl::array<std::string>::create1d(argc+1);
    args.set(0,"TaoSolverComponent");
    args.set(1,charPtr);
    for (i=2;i<=argc;i++) {
      while (*charPtr)
	charPtr++;
      while (!*charPtr)
	charPtr++;
      args.set(i,charPtr);
    }
  } else {
    args = sidl::array<std::string>::create1d(1);
    args.set(0,"TaoSolverComponent");
  }


  //Initialize PETSc and TAO
  info = tao_environment.Initialize(args);

  // create the solver
  info = Create("tao_lmvm");

  // Set parameter info
  SetMethod(method->value);
  SetMaximumIterates(max_its->value);
  SetMaximumFunctionEvaluations(max_funcs->value);
  SetTolerances(fatol->value, frtol->value,0,0);
  SetGradientTolerances(gatol->value,grtol->value,gttol->value);
  SetLAFactory(this->factory);

  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.Initialize)
}

/**
 * Method:  Solve[]
 */
int32_t
TaoSolver::Component_impl::Solve ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.Solve)
  int info;
  info = SetFromOptions();
  info = SolveApplication(this->model);
  return info;
  // DO-NOT-DELETE splicer.end(TaoSolver.Component.Solve)
}

/**
 * Method:  Finalize[]
 */
int32_t
TaoSolver::Component_impl::Finalize ()
throw () 

{
  // DO-NOT-DELETE splicer.begin(TaoSolver.Component.Finalize)
  //  tao_environment.Finalize();
  if (this->model._not_nil()) {
    this->model.finalize();
    this->myServices.releasePort("OptimizationModel");
  }

  if (this->factory._not_nil()) {
    this->factory.finalize();
    this->myServices.releasePort("LAFactory");
  }
  std::cout << "Calling tao_environment.Finalize()" << std::endl;
  
  return 0;

  // DO-NOT-DELETE splicer.end(TaoSolver.Component.Finalize)
}


// DO-NOT-DELETE splicer.begin(TaoSolver.Component._misc)
ConfigurableParameterPort *
TaoSolver::Component_impl::setupParameters(ConfigurableParameterFactory *cpf)
{
  std::cout << "setupParameters..." << std::endl;
  ConfigurableParameterPort *pp = cpf->createConfigurableParameterPort();
  std::cout << "created configurableparameterport..." << std::endl;
  /*
  ParameterGetListener *pgl = dynamic_cast<ParameterGetListener *>(this);
  if (pgl == NULL)
    std::cerr << "could not cast this to ParameterGetListener" << std::endl;
  pp->setUpdater(pgl);
  */
  max_its = new IntParameter("tao_max_its","Maximum iterations for TAO Solver","MaxIters",500,0,100000000);
  max_funcs = new IntParameter("tao_max_func","Maximum function evaluations for TAO Solver","tao_max_func",10000000,0,10000000);
  
  options = new StringParameter("tao_options","%delimited options","tao_options","");

  method = new StringParameter("tao_method","Choose algorithm to use in TAO Solver",
			       "tao_method", "tao_lmvm");

  method->addChoice("tao_lmvm");
  method->addChoice("tao_cg_fr");
  method->addChoice("tao_cg_pr");
  method->addChoice("tao_cg_prp");
  method->addChoice("tao_ntr");
  method->addChoice("tao_nls");
  method->addChoice("tao_blmvm");
  method->addChoice("tao_tron");
  method->addChoice("tao_bqpip");
  method->addChoice("tao_gpcg");
  method->addChoice("tao_ssils");
  method->addChoice("tao_ssfls");
  method->addChoice("tao_kt");

  fatol = new DoubleParameter("tao_fatol","Absolute objective value tolerance",
			      "tao_fatol",
			      0,0,10000000);
  frtol = new DoubleParameter("tao_frtol","Relative objective value tolerance",
			      "tao_frtol",
			      0,0,10000000);
  gatol = new DoubleParameter("tao_gatol","Absolute gradient norm tolerance",
			      "tao_gatol",
			      1e-8,0,10000000);
  grtol = new DoubleParameter("tao_grtol","Relative gradient norm tolerance",
			      "tao_grtol",
			      1e-8,0,10000000);
  gttol = new DoubleParameter("tao_gttol","Total reduction in gradient tolerance",
			      "tao_gttol",
			      1e-8,0,10000000);
  steptol = new DoubleParameter("tao_steptol","Minimum Trust Region radius",
				"tao_steptol",
				0,0,10000000);
  lmvm_lm = new IntParameter("tao_lmvm_lm",
			     "The number of previous points and gradients to be used",
			     "tao_lmvm_lm",
			     20,1,10000);
  lmvm_initH = new DoubleParameter("tao_lmvm_initH",
				   "Diagonal for initial Hessian",
				   "tao_lmvm_initH",
				   0,1e20,0);
				 
  /*  taomonitor = new BoolParameter("tao_monitor","Use default TAO monitor","tao_monitor",0);
  taoview = new BoolParameter("tao_view","View TAO Solver information","tao_view",0);
  */
  std::cout << "created parameters..." << std::endl;
  pp->setBatchTitle("TaoSolver Configuration");
  pp->setGroupName("General Solver Options");
  pp->addRequest(options);
  pp->addRequest(method);
  pp->addRequest(max_its);
  pp->addRequest(max_funcs);
  pp->addRequest(fatol);
  pp->addRequest(frtol);
  pp->addRequest(gatol);
  pp->addRequest(grtol);
  pp->addRequest(gttol);
  pp->addRequest(lmvm_lm);
  pp->addRequest(steptol);
  pp->addRequest(lmvm_initH);
  /*  pp->addRequest(taomonitor);
      pp->addRequest(taoview);*/
  std::cout << "registered parameters..." << std::endl;
  return pp;

}

/*
bool
TaoSolver::Component_impl::updateParameterPort(ConfigurableParameterPort *opp)
{
  std::cout << "updating ParameterPort..." << std::endl;
  if (!(this->cpp == opp)) {
    return false;
  }

  if (!this->dynTestDone) {
    this->cpp->addRequest(utest);
    this->dynTestDone = true;
    return true;
  }
  
  return false;
}
*/

// DO-NOT-DELETE splicer.end(TaoSolver.Component._misc)

