// Define interface class
TriKota::DirectApplicInterface::DirectApplicInterface(
                                ProblemDescDB& problem_db_,
                                const Teuchos::RCP<EpetraExt::ModelEvaluator> App_,
				int p_index_, int g_index_)
  : Dakota::DirectApplicInterface(problem_db_),
    App(App_),
    p_index(p_index_),
    g_index(g_index_),
    orientation(EEME::DERIV_MV_BY_COL)
{
  Teuchos::RCP<Teuchos::FancyOStream>
    out = Teuchos::VerboseObjectBase::getDefaultOStream();

  if (App != Teuchos::null) {
    model_p = Teuchos::rcp(new Epetra_Vector(*(App->get_p_init(p_index))));
    //    model_g = Teuchos::rcp(new Epetra_Vector(*(App->get_g_map(g_index))));
    model_g = Teuchos::rcp(new Epetra_Vector((const Epetra_BlockMap&) *(App->get_g_map(g_index)), true));

    numParameters = model_p->GlobalLength();
    numResponses  = model_g->GlobalLength();

    *out << "TriKota:: ModeEval has " << numParameters <<
            " parameters and " << numResponses << " responses." << std::endl;

    EEME::DerivativeSupport supportDgDp = App->createOutArgs().supports(EEME::OUT_ARG_DgDp, g_index, p_index);
    supportsSensitivities = !(supportDgDp.none());

    // Create the MultiVector, then the Derivative object
    if (supportsSensitivities) {
      *out << "TriKota:: ModeEval supports gradients calculation." << std::endl;

      if (supportDgDp.supports(EEME::DERIV_TRANS_MV_BY_ROW)) {
        orientation = EEME::DERIV_TRANS_MV_BY_ROW;
        model_dgdp = Teuchos::rcp(new Epetra_MultiVector(model_p->Map(), numResponses ));
      }
      else if (supportDgDp.supports(EEME::DERIV_MV_BY_COL)) {
        orientation = EEME::DERIV_MV_BY_COL;
        model_dgdp = Teuchos::rcp(new Epetra_MultiVector(model_g->Map(), numParameters));
      }
      else {
        TEUCHOS_TEST_FOR_EXCEPTION(!supportDgDp.none(), std::logic_error,
              "TriKota Adapter Error: DgDp data type not implemented");
      }
    }

    *out << "TriKota:: Setting initial guess from Model Evaluator to Dakota " << std::endl;

    Model& first_model = *(problem_db_.model_list().begin());
    unsigned int num_dakota_vars =  first_model.acv();
    Dakota::RealVector drv(num_dakota_vars);

    TEUCHOS_TEST_FOR_EXCEPTION(num_dakota_vars > numParameters, std::logic_error,
                       "TriKota Adapter Error: number of parameters in ModelEvaluator  "
                       <<  numParameters << "\n is less then the number of continuous variables\n"
                       << " specified in the dakota.in input file " << num_dakota_vars << "\n" );

    for (unsigned int i=0; i<num_dakota_vars; i++) drv[i] = (*model_p)[i];
    first_model.continuous_variables(drv);

  }
  else {
    *out << "Warning in TriKota::DirectApplicInterface constructor\n" 
         << "\tModelEvaluator is null. This is OK iff Dakota has assigned"
         << " MPI_COMM_NULL to this Proc " << std::endl;
  }
}
// Define interface class
TriKota::ThyraDirectApplicInterface::ThyraDirectApplicInterface(
              ProblemDescDB& problem_db_,
              const Teuchos::RCP<Thyra::ModelEvaluatorDefaultBase<double> > App_)
  : Dakota::DirectApplicInterface(problem_db_),
    App(App_),
    orientation(MEB::DERIV_MV_BY_COL)
{
  Teuchos::RCP<Teuchos::FancyOStream>
    out = Teuchos::VerboseObjectBase::getDefaultOStream();

  if (App != Teuchos::null) {
    model_p = Thyra::createMember<double>(App->get_p_space(0));
    model_g = Thyra::createMember<double>(App->get_g_space(0));

    Thyra::DetachedVectorView<double> my_p(model_p);
    Thyra::DetachedVectorView<double> my_g(model_g);
    
    numParameters = my_p.subDim();
    numResponses  = my_g.subDim();

    *out << "TriKota:: ModeEval has " << numParameters <<
            " parameters and " << numResponses << " responses." << std::endl;

    MEB::DerivativeSupport supportDgDp = App->createOutArgs().supports(MEB::OUT_ARG_DgDp, 0, 0);
    supportsSensitivities = !(supportDgDp.none());

    // Create the MultiVector, then the Derivative object
    if (supportsSensitivities) {
      *out << "TriKota:: ModeEval supports gradients calculation." << std::endl;

      if (supportDgDp.supports(MEB::DERIV_TRANS_MV_BY_ROW)) {
        orientation = MEB::DERIV_TRANS_MV_BY_ROW;
        model_dgdp = Thyra::createMembers<double>(App->get_p_space(0), numResponses);
      }
      else if (supportDgDp.supports(MEB::DERIV_MV_BY_COL)) {
        orientation = MEB::DERIV_MV_BY_COL;
        model_dgdp = Thyra::createMembers<double>(App->get_g_space(0), numParameters);
      }
      else {
        TEST_FOR_EXCEPTION(!supportDgDp.none(), std::logic_error,
              "TriKota Adapter Error: DgDp data type not implemented");
      }
    }

    *out << "TriKota:: Setting initial guess from Model Evaluator to Dakota " << std::endl;
    const Thyra::ConstDetachedVectorView<double> my_pinit(App->getNominalValues().get_p(0));
    for (unsigned int i=0; i<numParameters; i++) my_p[i] = my_pinit[i];

    Model& first_model = *(problem_db_.model_list().begin());
    unsigned int num_dakota_vars =  first_model.acv();
    Dakota::RealVector drv(num_dakota_vars);

    TEST_FOR_EXCEPTION(num_dakota_vars > numParameters, std::logic_error,
                       "TriKota Adapter Error: number of parameters in ModelEvaluator  "
                       <<  numParameters << "\n is less then the number of continuous variables\n"
                       << " specified in the dakota.in input file " << num_dakota_vars << "\n" );

    for (unsigned int i=0; i<num_dakota_vars; i++) drv[i] = my_p[i];
    first_model.continuous_variables(drv);

  }
  else {
    *out << "Warning in TriKota::ThyraDirectApplicInterface constructor\n" 
         << "\tModelEvaluator is null. This is OK iff Dakota has assigned"
         << " MPI_COMM_NULL to this Proc " << std::endl;
  }
}
TriKota::MPDirectApplicInterface::
MPDirectApplicInterface(
  ProblemDescDB& problem_db_,
  const Teuchos::RCP<Piro::Epetra::StokhosMPSolver>& model_,
  int p_index_, int g_index_) : 
  Dakota::DirectApplicInterface(problem_db_),
  model(model_),
  p_index(p_index_),
  g_index(g_index_),
  orientation(EEME::DERIV_MV_BY_COL)
{
  out = Teuchos::VerboseObjectBase::getDefaultOStream();

  if (model != Teuchos::null) {

    // Make sure we support multi-point
    TEUCHOS_TEST_FOR_EXCEPTION(
      !model->createInArgs().supports(EEME::IN_ARG_p_mp, p_index), 
      std::logic_error,
      "Model does not support multi-point parameter " << g_index << "!");
    TEUCHOS_TEST_FOR_EXCEPTION(
      !model->createOutArgs().supports(EEME::OUT_ARG_g_mp, g_index), 
      std::logic_error,
      "Model does not support multi-point response " << g_index << "!");

    // Create product vectors 
    model_p = model->create_p_mp(p_index);
    model_g = model->create_g_mp(g_index);
    numParameters = (*model_p)[0].GlobalLength();
    numResponses  = (*model_g)[0].GlobalLength();
    block_size = model_p->map()->NumMyElements();

    *out << "TriKota:: ModeEval has " << numParameters <<
            " parameters and " << numResponses << " responses." << std::endl;
    
    // Create dg/dp
    EEME::DerivativeSupport supportDgDp = 
      model->createOutArgs().supports(EEME::OUT_ARG_DgDp_mp, g_index, p_index);
    supportsSensitivities =
      supportDgDp.supports(EEME::DERIV_TRANS_MV_BY_ROW) ||
      supportDgDp.supports(EEME::DERIV_MV_BY_COL);
    if (supportsSensitivities) {
      *out << "TriKota:: ModeEval supports gradients calculation." << std::endl;
      if (supportDgDp.supports(EEME::DERIV_TRANS_MV_BY_ROW)) {
        orientation = EEME::DERIV_TRANS_MV_BY_ROW;
        model_dgdp = model->create_p_mv_mp(p_index, numResponses);
      }
      else {
        orientation = EEME::DERIV_MV_BY_COL;
        model_dgdp = model->create_g_mv_mp(g_index, numParameters);
      }
    }

    *out << "TriKota:: Setting initial guess from Model Evaluator to Dakota " 
	 << std::endl;
    Model& first_model = *(problem_db_.model_list().begin());
    unsigned int num_dakota_vars =  first_model.acv();
    Dakota::RealVector drv(num_dakota_vars);
    TEUCHOS_TEST_FOR_EXCEPTION(
      num_dakota_vars > numParameters, std::logic_error,
      "TriKota Adapter Error: number of parameters in ModelEvaluator  "
      <<  numParameters 
      << "\n is less then the number of continuous variables\n"
      << " specified in the dakota.in input file " << num_dakota_vars << "\n" );
    for (unsigned int i=0; i<num_dakota_vars; i++) 
      drv[i] = (*model_p)[0][i];
    first_model.continuous_variables(drv);

  }
  else {
    *out << "Warning in TriKota::MPDirectmodellicInterface constructor\n" 
         << "\tModelEvaluator is null. This is OK iff Dakota has assigned"
         << " MPI_COMM_NULL to this Proc " << std::endl;
  }
}