/*!\file:  DakotaPlugin.cpp (see DakotaPlugin.h for explanations)
 * \brief  header file for derived DirectApplicInterface class. 
 * \sa SpwanCore.cpp and \sa qmu.cpp
 *
 * This class needs to be understood simultaneously with qmu.cpp and SpwanCore.cpp. 
 * This call is derived from the Dakota DirectApplicInterface class. This is the 
 * only way to plug ISSM's own routines into the Dakota engine. The derived class 
 * has one function called derived_map_ac, which is called by Dakota to drive the 
 * entire snesitivity analysis. 
 *
 * We use this routine (which gets variables, variable_descriptors from the Dakota 
 * engine, and requests responses from the ISSM solution sequences), to call our 
 * own solutoin cores. This routines calls the SpawnCore routine, which will drive 
 * the entire computations. 
 */ 


#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

/*Standard ISSM includes: */
#include "../shared/shared.h"
#include "../include/include.h"
#include "../objects/objects.h"
#include "../modules/Dakotax/Dakotax.h"

/*Standard includes: */
#include <string>

#ifdef _HAVE_DAKOTA_ //only works if dakota library has been compiled in.

//Dakota headers
#include "DakotaResponse.H"
#include "ParamResponsePair.H"
#include "DakotaPlugin.h"
#include "system_defs.h"
#include "ProblemDescDB.H"
#include "ParallelLibrary.H"

namespace SIM {

//constructor
DakotaPlugin::DakotaPlugin(const Dakota::ProblemDescDB& problem_db,void* in_femmodel):Dakota::DirectApplicInterface(problem_db){


	femmodel=in_femmodel;
	counter=0;
}

//destructor
DakotaPlugin::~DakotaPlugin(){ /* Virtual destructor handles referenceCount at Interface level. */ }

int DakotaPlugin::derived_map_ac(const Dakota::String& driver) {

	int i;
	IssmDouble* variables=NULL;
	char** variable_descriptors=NULL;
	char*  variable_descriptor=NULL;
	IssmDouble* responses=NULL;

	/*increae counter: */
	counter++;

	/*Before launching analysis, we need to transfer the dakota inputs into Issm 
	 *readable variables: */

	/*First, the variables: */
	variables=xNew<IssmDouble>(numACV);
	for(i=0;i<numACV;i++){
		variables[i]=xC[i];
	}
	/*The descriptors: */
	variable_descriptors=xNew<char*>(numACV);
	for(i=0;i<numACV;i++){
		string label=xCLabels[i];
		variable_descriptor=xNew<char>(strlen(label.c_str())+1);
		memcpy(variable_descriptor,label.c_str(),(strlen(label.c_str())+1)*sizeof(char));

		
		variable_descriptors[i]=variable_descriptor;
	}

	/*Initialize responses: */
	responses=xNewZeroInit<IssmDouble>(numFns);

	/*run core solution: */
	SpawnCore(responses,numFns, variables,variable_descriptors,numACV,femmodel,counter);

	/*populate responses: */
	for(i=0;i<numFns;i++){
		fnVals[i]=responses[i];
	}


	/*Free ressources:*/
	xDelete<IssmDouble>(variables);
	for(i=0;i<numACV;i++){
		variable_descriptor=variable_descriptors[i];
		xDelete<char>(variable_descriptor);
	}
	xDelete<char*>(variable_descriptors);
	xDelete<IssmDouble>(responses);

	return 0;
}
  

int DakotaPlugin::GetCounter(){
	return counter;
}

} // namespace SIM


#endif //only works if dakota library has been compiled in.
