/*
 * solutions.h: 
 */

#ifndef SOLUTIONS_H_
#define SOLUTIONS_H_

#include "../classes/objects/objects.h"
#include "../io/io.h"
#include "../toolkits/toolkits.h"

struct OptArgs;
class FemModel;

/*cores: */
void adjointdiagnostic_core(FemModel* femmodel);
void adjointbalancethickness_core(FemModel* femmodel);
void gradient_core(FemModel* femmodel,int n=0,bool orthogonalize=false);
void diagnostic_core(FemModel* femmodel);
void hydrology_core(FemModel* femmodel);
void hydrology_core_step(FemModel* femmodel,int step, IssmDouble time);
void thermal_core(FemModel* femmodel);
void enthalpy_core(FemModel* femmodel);
void surfaceslope_core(FemModel* femmodel);
void bedslope_core(FemModel* femmodel);
void control_core(FemModel* femmodel);
void controltao_core(FemModel* femmodel);
void prognostic_core(FemModel* femmodel);
void balancethickness_core(FemModel* femmodel);
void slopecompute_core(FemModel* femmodel);
void steadystate_core(FemModel* femmodel);
void transient_core(FemModel* femmodel);
void dakota_core(FemModel* femmodel);
void ad_core(FemModel* femmodel);
IssmDouble objectivefunction(IssmDouble search_scalar,OptArgs* optargs);

//convergence:
void convergence(bool* pconverged, Matrix<IssmDouble>* K_ff,Vector<IssmDouble>* p_f,Vector<IssmDouble>* u_f,Vector<IssmDouble>* u_f_old,Parameters* parameters);
bool controlconvergence(IssmDouble J,IssmDouble tol_cm);
bool steadystateconvergence(FemModel* femmodel);

//optimization
int GradJSearch(IssmDouble* search_vector,FemModel* femmodel,int step);

//diverse
void ProcessArguments(int* solution,char** pbinname,char** poutbinname,char** ppetscname,char** plockname,char** prootpath,int argc,char **argv);
void WriteLockFile(char* filename);
void controlrestart(FemModel* femmodel,IssmDouble* J);
void ResetBoundaryConditions(FemModel* femmodel, int analysis_type);
COMM EnvironmentInit(int argc,char** argv);
void EnvironmentFinalize(void);
int  DakotaSpawnCore(double* responses, int numresponses, double* variables, char** variables_descriptors,int numvariables, void* femmodel,int counter);
void PrintBanner(void);

//solution configuration
void AnalysisConfiguration(int** panalyses,int* pnumanalyses, int solutiontype);
void CorePointerFromSolutionEnum(void (**psolutioncore)(FemModel*),Parameters* parameters,int solutiontype);
void WrapperCorePointerFromSolutionEnum(void (**psolutioncore)(FemModel*),Parameters* parameters,int solutiontype,bool nodakotacore=false);
void AdjointCorePointerFromSolutionEnum(void (**padjointcore)(FemModel*),int solutiontype);

#endif
