Index: /issm/trunk-jpl/src/c/Makefile.am
===================================================================
--- /issm/trunk-jpl/src/c/Makefile.am	(revision 27695)
+++ /issm/trunk-jpl/src/c/Makefile.am	(revision 27696)
@@ -130,4 +130,5 @@
 	./classes/Params/Parameters.cpp \
 	./classes/Params/BoolParam.cpp \
+	./classes/Params/ControlParam.cpp \
 	./classes/Params/IntParam.cpp \
 	./classes/Params/IntVecParam.cpp \
Index: /issm/trunk-jpl/src/c/classes/IoModel.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/IoModel.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/IoModel.cpp	(revision 27696)
@@ -1022,4 +1022,33 @@
 }
 /*}}}*/
+void  IoModel::FetchData(IssmDouble** pscalar, const char* data_name){/*{{{*/
+
+   /*output: */
+   IssmPDouble *scalar = NULL;
+   int          code   = 0;
+
+   /*recover my_rank:*/
+   int my_rank=IssmComm::GetRank();
+
+   /*Set file pointer to beginning of the data: */
+   fid=this->SetFilePointerToData(&code,NULL,data_name);
+   if(code!=3)_error_("expecting a IssmDouble for \""<<data_name<<"\"");
+
+   /*Now fetch: */
+
+   /*We have to read a matrix from disk. First read the dimensions of the matrix, then the whole matrix: */
+
+   /*Now allocate matrix: */
+   /*Read matrix on node 0, then broadcast: */
+   scalar=xNew<IssmPDouble>(1);
+   if(my_rank==0) if(fread(scalar,sizeof(IssmPDouble),1,fid)!=1) _error_("could not read matrix ");
+   ISSM_MPI_Bcast(scalar,1,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm());
+
+   _printf0_("scalar: " << *scalar << "\n");
+   *pscalar=xNew<IssmDouble>(1);
+   *pscalar[0]=scalar[0];
+   xDelete<IssmPDouble>(scalar);
+}
+/*}}}*/
 void  IoModel::FetchData(char** pstring,const char* data_name){/*{{{*/
 
@@ -1425,4 +1454,30 @@
 	if(pM) *pM=M;
 	if(pN) *pN=N;
+}
+/*}}}*/
+void  IoModel::FetchData(IssmPDouble** pscalar,const char* data_name){/*{{{*/
+
+   /*output: */
+   IssmPDouble   *scalar = NULL;
+   int      code;
+
+   /*recover my_rank:*/
+   int my_rank=IssmComm::GetRank();
+
+   /*Set file pointer to beginning of the data: */
+   fid=this->SetFilePointerToData(&code,NULL,data_name);
+
+   if(code!=3)_error_("expecting a IssmDouble for \""<<data_name<<"\"");
+
+   /*We have to read a scalar from disk. First read the dimensions of the scalar, then the scalar: */
+   scalar=xNew<IssmPDouble>(1);
+   if(my_rank==0){
+      if(fread(scalar,sizeof(IssmPDouble),1,fid)!=1)_error_("could not read scalar ");
+   }
+   ISSM_MPI_Bcast(scalar,1,ISSM_MPI_PDOUBLE,0,IssmComm::GetComm());
+
+
+   /*Assign output pointers: */
+   *pscalar=scalar;
 }
 /*}}}*/
Index: /issm/trunk-jpl/src/c/classes/IoModel.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/IoModel.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/IoModel.h	(revision 27696)
@@ -133,4 +133,5 @@
 		void        FetchData(int* pinteger,const char* data_name);
 		void        FetchData(IssmDouble* pscalar,const char* data_name);
+		void        FetchData(IssmDouble** pscalar, const char* data_name);	
 		void        FetchData(char** pstring,const char* data_name);
 		void        FetchData(char*** pstrings,int* pnumstrings,const char* data_name);
@@ -140,4 +141,5 @@
 #if _HAVE_AD_  && !defined(_WRAPPERS_)
 		void        FetchData(IssmPDouble**  pscalarmatrix,int* pM,int* pN,const char* data_name);
+		void        FetchData(IssmPDouble** pscalar,const char* data_name);
 #endif
 		void        FetchData(IssmDouble*** pmatrixarray,int** pmdims,int** pndims, int* pnumrecords,const char* data_name);
Index: /issm/trunk-jpl/src/c/classes/Params/BoolParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/BoolParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/BoolParam.h	(revision 27696)
@@ -49,4 +49,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -62,4 +63,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -70,4 +72,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/ControlParam.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/ControlParam.cpp	(revision 27696)
+++ /issm/trunk-jpl/src/c/classes/Params/ControlParam.cpp	(revision 27696)
@@ -0,0 +1,204 @@
+/*!\file ControlParam.c
+ * \brief: implementation of the ControlParam object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include "../classes.h"
+#include "shared/shared.h"
+
+/*ControlParam constructors and destructor*/
+ControlParam::ControlParam(){/*{{{*/
+	return;
+}
+/*}}}*/
+ControlParam::ControlParam(IssmDouble* in_value, IssmDouble* in_minvalue, IssmDouble* in_maxvalue, IssmDouble* in_savedvalue, IssmDouble* in_gradient, int in_enum_type, int in_M){/*{{{*/
+
+	M=in_M;
+
+	if(M){
+		value=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(value,in_value,M);
+		
+		minvalue=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(minvalue,in_minvalue,M);
+		
+		maxvalue=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(maxvalue,in_maxvalue,M);
+		
+		savedvalue=NULL;
+		gradient=NULL;
+		
+	}
+	else{
+		value=NULL;
+		minvalue=NULL;
+		maxvalue=NULL;
+		savedvalue=NULL;
+		gradient=NULL;
+	}
+
+	enum_type=in_enum_type;
+}
+/*}}}*/
+ControlParam::ControlParam(IssmDouble* in_value, IssmDouble* in_minvalue, IssmDouble* in_maxvalue, int in_enum_type, int in_M){/*{{{*/
+
+	enum_type=in_enum_type;
+	M=in_M;
+
+	if(M){
+		value=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(value,in_value,M);
+		
+		minvalue=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(minvalue,in_minvalue,M);
+		
+		maxvalue=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(maxvalue,in_maxvalue,M);
+	
+		savedvalue=NULL;
+		gradient=NULL;
+	}
+	else{
+		value=NULL;
+		minvalue=NULL;
+		maxvalue=NULL;
+		savedvalue=NULL;
+		gradient=NULL;
+	}
+
+}
+/*}}}*/
+ControlParam::~ControlParam(){/*{{{*/
+	xDelete<IssmDouble>(value);
+	xDelete<IssmDouble>(minvalue);
+	xDelete<IssmDouble>(maxvalue);
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+Param* ControlParam::copy() {/*{{{*/
+
+	return new ControlParam(this->value,this->minvalue,this->maxvalue,this->savedvalue,this->gradient,this->enum_type,this->M);
+
+}
+/*}}}*/
+void ControlParam::DeepEcho(void){/*{{{*/
+
+	_printf_(setw(22)<<"   ControlParam "<<setw(35)<<left<<EnumToStringx(this->enum_type)<<"\n ");
+	if (value) _printf_("---value: ");
+	for(int i=0;i<this->M;i++) _printf_(" "<< this->value[i]);
+	_printf_("]\n");
+	if (savedvalue) _printf_("---savedvalue: " << this->savedvalue << "\n");
+	if (minvalue) _printf_("---minvalue: ");
+	for(int i=0;i<this->M;i++) _printf_(" "<< this->minvalue[i]);
+	_printf_("]\n");
+	if (maxvalue) _printf_("---maxvalue: ");
+	for(int i=0;i<this->M;i++) _printf_(" "<< this->maxvalue[i]);
+	_printf_("]\n");
+	if (gradient) _printf_("---gradient: " << this->gradient << "\n");
+}
+/*}}}*/
+void ControlParam::Echo(void){/*{{{*/
+	this->DeepEcho();
+}
+/*}}}*/
+int  ControlParam::Id(void){ return -1; }/*{{{*/
+/*}}}*/
+void ControlParam::Marshall(MarshallHandle* marshallhandle){ /*{{{*/
+
+	int object_enum = ControlParamEnum;
+   marshallhandle->call(object_enum);
+	marshallhandle->call(this->enum_type);
+	marshallhandle->call(this->M);
+	marshallhandle->call(this->value,this->M);
+	marshallhandle->call(this->minvalue,this->M);
+	marshallhandle->call(this->maxvalue,this->M);
+	marshallhandle->call(this->savedvalue,this->M);
+	marshallhandle->call(this->gradient,this->M);
+
+}
+/*}}}*/
+int  ControlParam::ObjectEnum(void){/*{{{*/
+
+	return ControlParamEnum;
+
+}
+/*}}}*/
+
+void  ControlParam::GetParameterValue(IssmDouble** poutput,int* pM, const char* data){/*{{{*/
+
+	IssmDouble* output=xNew<IssmDouble>(M);
+	
+	if(strcmp(data,"value")==0){
+		xMemCpy<IssmDouble>(output,value,M);
+	}
+	else if(strcmp(data,"savedvalues")==0){
+		xMemCpy<IssmDouble>(output,savedvalue,M);
+	}
+	else if (strcmp(data,"lowerbound")==0){
+		xMemCpy<IssmDouble>(output,minvalue,M);
+	}
+	else if (strcmp(data,"upperbound")==0){
+		xMemCpy<IssmDouble>(output,maxvalue,M);
+	}
+	else if (strcmp(data,"gradient")==0){
+		xMemCpy<IssmDouble>(output,gradient,M);
+	}
+	else{
+		_error_("Data " << data << " not supported yet");
+	}
+	
+	/*Assign output pointers:*/
+	if(pM) *pM=M;
+	*poutput=output;
+}
+/*}}}*/
+void  ControlParam::GetParameterValue(IssmDouble* poutput){/*{{{*/
+
+	xMemCpy<IssmDouble>(poutput,value,M);
+	
+}
+/*}}}*/
+void  ControlParam::GetParameterValue(IssmDouble** poutput, int* pM){/*{{{*/
+
+	IssmDouble* output=NULL;
+
+	if(M){
+		output=xNew<IssmDouble>(M);
+		xMemCpy<IssmDouble>(output,value,M);
+	}
+	
+	/*Assign output pointers:*/
+	if(pM) *pM=M;
+	*poutput=output;
+	
+}
+/*}}}*/
+void  ControlParam::SetValue(IssmDouble* poutput, int in_M){/*{{{*/
+
+	/*avoid leak: */
+	xDelete<IssmDouble>(this->value);
+	
+	this->value=xNew<IssmDouble>(in_M);
+	xMemCpy<IssmDouble>(this->value,poutput,in_M);
+
+	this->M=in_M;
+}
+/*}}}*/
+void  ControlParam::SetGradient(IssmDouble* poutput, int in_M){/*{{{*/
+
+	/*avoid leak: */
+	xDelete<IssmDouble>(this->gradient);
+	
+	this->gradient=xNew<IssmDouble>(in_M);
+	xMemCpy<IssmDouble>(this->gradient,poutput,in_M);
+
+	this->M=in_M;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/Params/ControlParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/ControlParam.h	(revision 27696)
+++ /issm/trunk-jpl/src/c/classes/Params/ControlParam.h	(revision 27696)
@@ -0,0 +1,84 @@
+/*! \file ControlParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+#ifndef _CONTROLPARAM_H_
+#define _CONTROLPARAM_H_
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include "./Param.h"
+#include "../../shared/shared.h"
+/*}}}*/
+
+class ControlParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		IssmDouble* value;
+		IssmDouble* minvalue;
+		IssmDouble* maxvalue;
+		IssmDouble* savedvalue;
+		IssmDouble* gradient; 
+		int        enum_type;
+		int        M;
+
+	public:
+		/*ControlParam constructors, destructors: {{{*/
+		ControlParam();
+		ControlParam(IssmDouble* in_value, IssmDouble* in_minvalue, IssmDouble* in_maxvalue, IssmDouble* in_savedvalue, IssmDouble* in_gradient, int in_enum_type, int in_M);
+		ControlParam(IssmDouble* in_value, IssmDouble* in_minvalue, IssmDouble* in_maxvalue, int in_enum_type, int in_M);
+		~ControlParam();
+		/*}}}*/
+		/*Object virtual functions definitions:{{{ */
+		Param* copy();
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void Marshall(MarshallHandle* marshallhandle);
+		int   ObjectEnum();
+		/*}}}*/
+		/*Param virtual functions definitions: {{{*/
+		void  GetParameterValue(bool* pbool){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a bool");}
+		void  GetParameterValue(int* pinteger){_error_("Param "<< EnumToStringx(enum_type) << " cannot return an integer");}
+		void  GetParameterValue(int** pintarray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return an integer");}
+		void  GetParameterValue(int** pintarray,int* pM,int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix");}
+		void  GetParameterValue(IssmDouble* pIssmDouble);
+		void  GetParameterValue(IssmDouble* pdouble,IssmDouble time){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble for a given time");}
+		void  GetParameterValue(char** pstring){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a string array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM);
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data);
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
+		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
+		void  GetParameterValue(Matrix<IssmDouble>** pmat){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Mat");}
+		void  GetParameterValue(FILE** pfid){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a FILE");}
+		void  GetParameterValue(DataSet** pdataset){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a DataSet");}
+		int   InstanceEnum(){return enum_type;}
+
+		void  SetEnum(int enum_in){this->enum_type = enum_in;};
+		void  SetValue(bool boolean){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a boolean");}
+		void  SetValue(int integer){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an integer");}
+		void  SetValue(IssmDouble scalar){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a scalar");}
+		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
+		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a scalar");}
+		void  SetValue(IssmDouble* IssmDoublearray,int M);
+		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble mat array");}
+		void  SetValue(int* intarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot return an integer");}
+		void  SetValue(int* pintarray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a int mat array");}
+		void  SetValue(Vector<IssmDouble>* vec){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a Vec");}
+		void  SetValue(Matrix<IssmDouble>* mat){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a Mat");}
+		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
+		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M);
+		/*}}}*/
+};
+#endif  /* _DOUBLEPARAM_H */
Index: /issm/trunk-jpl/src/c/classes/Params/DataSetParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/DataSetParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/DataSetParam.h	(revision 27696)
@@ -51,4 +51,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("DataSet param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -64,4 +65,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a file pointer");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -72,4 +74,5 @@
 		void  SetValue(DataSet* dataset);
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("DataSet param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/DoubleMatArrayParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/DoubleMatArrayParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/DoubleMatArrayParam.h	(revision 27696)
@@ -52,4 +52,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << "cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << "cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims);
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << "cannot return a Vec");}
@@ -65,4 +66,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << "cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << "cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << "cannot hold a IssmDouble vec array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << "cannot hold a IssmDouble mat array");}
@@ -73,4 +75,5 @@
 		void  SetValue(FILE* fid){_error_("Bool param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array);
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/DoubleMatParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/DoubleMatParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/DoubleMatParam.h	(revision 27696)
@@ -52,4 +52,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM,int* pN);
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble vec array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M,int N);
@@ -72,4 +74,5 @@
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
 		void  SetEnum(int enum_in){this->enum_type = enum_in;};
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 		/*DoubleMatParam specific routines:{{{*/
Index: /issm/trunk-jpl/src/c/classes/Params/DoubleParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/DoubleParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/DoubleParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM);
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN);
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/DoubleVecParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/DoubleVecParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/DoubleVecParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM);
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN);
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M);
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble mat array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 		/*DoubleVecParam specific routines:{{{*/
Index: /issm/trunk-jpl/src/c/classes/Params/FileParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/FileParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/FileParam.h	(revision 27696)
@@ -49,4 +49,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("File param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -62,4 +63,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -70,4 +72,5 @@
 		void  SetValue(FILE* fid){_error_("File param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("File param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/GenericParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/GenericParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/GenericParam.h	(revision 27696)
@@ -77,4 +77,5 @@
                 void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot return a IssmDouble array");}
                 void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot return a IssmDouble array");}
+					 void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot return a IssmDouble array");}
                 void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot return a matrix array");}
                 void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot return a Vec");}
@@ -91,4 +92,5 @@
                 void  SetValue(char* string){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a string");}
                 void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a string array");}
+					 void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a IssmDouble array");}
                 void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a IssmDouble array");}
                 void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a IssmDouble array");}
@@ -97,4 +99,5 @@
                 void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold a FILE");}
                 void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold an array of matrices");}
+					 void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(myEnumVal) << " cannot hold an IssmDouble");};
 
                 /*}}}*/
Index: /issm/trunk-jpl/src/c/classes/Params/IntMatParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/IntMatParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/IntMatParam.h	(revision 27696)
@@ -51,4 +51,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM,int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");};
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -64,4 +65,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble vec array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble vec array");};
@@ -72,4 +74,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/IntParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/IntParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/IntParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -65,4 +66,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/IntVecParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/IntVecParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/IntVecParam.h	(revision 27696)
@@ -51,4 +51,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array (maybe in serial?)");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -64,4 +65,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble mat array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble mat array");}
@@ -72,4 +74,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/MatrixParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/MatrixParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/MatrixParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/Param.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/Param.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/Param.h	(revision 27696)
@@ -39,4 +39,5 @@
 		virtual void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM)=0;
 		virtual void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM,int* pN)=0;
+		virtual void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data)=0;
 		virtual void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims)=0;
 		virtual void  GetParameterValue(Vector<IssmDouble>** pvec)=0;
@@ -56,4 +57,5 @@
 		virtual void  SetValue(DataSet* dataset){_error_("not implemented yet");};
 		virtual void  SetValue(IssmDouble* IssmDoublearray,int M)=0;
+		virtual void  SetValue(IssmDouble* IssmDoublearray)=0;
 		virtual void  SetValue(IssmDouble* pIssmDoublearray,int M,int N)=0;
 		virtual void  SetValue(int* intarray,int M)=0;
@@ -63,4 +65,5 @@
 		virtual void  SetValue(FILE* fid)=0;
 		virtual void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array)=0;
+		virtual void  SetGradient(IssmDouble* poutput, int M)=0;
 };
 #endif
Index: /issm/trunk-jpl/src/c/classes/Params/Parameters.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/Parameters.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/Parameters.cpp	(revision 27696)
@@ -20,4 +20,5 @@
 
 #include "./BoolParam.h"
+#include "./ControlParam.h"
 #include "./DoubleMatParam.h"
 #include "./DataSetParam.h"
@@ -232,4 +233,10 @@
 				this->AddObject(transarrayparam);
 			}
+			else if(obj_enum==ControlParamEnum){
+				ControlParam* controlparam=NULL;
+				controlparam=new ControlParam();
+				controlparam->Marshall(marshallhandle);
+				this->AddObject(controlparam);
+			}
 			else if(obj_enum==GenericParamEnum){
 				/*Skip for now (we don't want to Marhsall Comms)*/
@@ -417,4 +424,40 @@
 	if(pM)   *pM   = n;
 }/*}}}*/
+void Parameters::FindControlParam(IssmDouble** pvec,int* pM, int param_enum, const char* data){ _assert_(this);/*{{{*/
+
+	int index = EnumToIndex(param_enum);
+
+	/*Output*/
+	int         n;
+	IssmDouble* vector = NULL;
+
+	if(!this->params[index]) _error_("Parameter " << EnumToStringx(param_enum) <<" not set");
+	this->params[index]->GetParameterValue(pvec,pM,data);
+
+}/*}}}*/
+void Parameters::FindControlParamAndMakePassive(IssmPDouble** pvec,int* pM, int param_enum, const char* data){ _assert_(this);/*{{{*/
+
+	int index = EnumToIndex(param_enum);
+
+	/*Output*/
+	int         n;
+	IssmDouble* vector = NULL;
+
+	if(!this->params[index]) _error_("Parameter " << EnumToStringx(param_enum) <<" not set");
+	this->params[index]->GetParameterValue(&vector,&n,data);
+
+	/*Make output passive*/
+	#ifdef _HAVE_AD_
+	IssmPDouble* output = xNew<IssmPDouble>(n);
+	for(int i=0;i<n;i++) output[i] = reCast<IssmPDouble>(vector[i]);
+	xDelete<IssmDouble>(vector);
+	if(pvec) *pvec = output;
+	#else
+	if(pvec) *pvec = vector;
+	#endif
+
+	/*assign output pointers*/
+	if(pM)   *pM   = n;
+}/*}}}*/
 void Parameters::FindParamInDataset(IssmDouble** pIssmDoublearray,int* pM,int* pN,int dataset_type,int enum_type){/*{{{*/
 	_assert_(this);
@@ -524,4 +567,16 @@
 }
 /*}}}*/
+void   Parameters::SetParam(IssmDouble* IssmDoublearray, int enum_type){/*{{{*/
+
+	Param* param=NULL;
+
+	/*first, figure out if the param has already been created: */
+	param=xDynamicCast<Param*>(this->FindParamObject(enum_type));
+	if(param) param->SetValue(IssmDoublearray); //already exists, just set it.
+	else _error_("Param "<< EnumToStringx(enum_type) << " cannot setValue");
+
+	 //this->AddObject(new ControlParam(enum_type,IssmDoublearray,M,N)); //just add the new parameter.
+}
+/*}}}*/
 void   Parameters::SetParam(int* intarray,int M, int enum_type){/*{{{*/
 
@@ -592,4 +647,27 @@
 		this->AddObject(new DataSetParam(enum_type,dataset)); //just add the new parameter.
 	}
+}
+/*}}}*/
+void   Parameters::SetControlParam(IssmDouble* IssmDoublearray,int M, int enum_type){/*{{{*/
+
+	Param* param=NULL;
+
+	/*first, figure out if the param has already been created: */
+	param=xDynamicCast<Param*>(this->FindParamObject(enum_type));
+
+	if(param) param->SetValue(IssmDoublearray,M); //already exists, just set it.
+	else _error_("Param "<< EnumToStringx(enum_type) << " cannot setValue");
+}
+/*}}}*/
+void   Parameters::ControlParamSetGradient(IssmDouble* IssmDoublearray, int M, int enum_type){/*{{{*/
+
+	Param* param=NULL;
+
+	/*first, figure out if the param has already been created: */
+	param=xDynamicCast<Param*>(this->FindParamObject(enum_type));
+	if(param) param->SetGradient(IssmDoublearray,M); //already exists, just set it.
+	else _error_("Param "<< EnumToStringx(enum_type) << " cannot setValue");
+
+	 //this->AddObject(new ControlParam(enum_type,IssmDoublearray,M,N)); //just add the new parameter.
 }
 /*}}}*/
Index: /issm/trunk-jpl/src/c/classes/Params/Parameters.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/Parameters.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/Parameters.h	(revision 27696)
@@ -55,4 +55,6 @@
 		void  FindParamAndMakePassive(IssmPDouble* pscalar, int enum_type);
 		void  FindParamAndMakePassive(IssmPDouble** pvec,int* pM,int enum_type);
+		void  FindControlParam(IssmDouble** pvec,int* pM, int param_enum, const char* data);
+		void  FindControlParamAndMakePassive(IssmPDouble** pvec,int* pM, int param_enum, const char* data);
 		void  FindParamInDataset(IssmDouble** pIssmDoublearray,int* pM,int* pN,int dataset_type,int enum_type);
 		IssmDouble FindParam(int enum_type);
@@ -65,4 +67,5 @@
 		void  SetParam(IssmDouble* IssmDoublearray,int M,int enum_type);
 		void  SetParam(IssmDouble* IssmDoublearray,int M,int N,int enum_type);
+		void  SetParam(IssmDouble* IssmDoublearray, int enum_type);
 		void  SetParam(int* intarray,int M,int enum_type);
 		void  SetParam(int* intarray,int M,int N,int enum_type);
@@ -71,5 +74,6 @@
 		void  SetParam(FILE* fid,int enum_type);
 		void  SetParam(DataSet* dataset,int enum_type);
-
+		void  SetControlParam(IssmDouble* IssmDoublearray,int M, int enum_type);
+		void  ControlParamSetGradient(IssmDouble* IssmDoublearray, int M, int enum_type);
 		Param* FindParamObject(int enum_type);
 
Index: /issm/trunk-jpl/src/c/classes/Params/StringArrayParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/StringArrayParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/StringArrayParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Vec param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M);
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/StringParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/StringParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/StringParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string);
 		void  SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/TransientArrayParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/TransientArrayParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/TransientArrayParam.h	(revision 27696)
@@ -55,4 +55,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM,int* pN){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -68,4 +69,5 @@
 		void  SetValue(char* string){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a IssmDouble vec array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M,int N){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -76,4 +78,5 @@
 		void  SetValue(FILE* fid){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/TransientParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/TransientParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/TransientParam.h	(revision 27696)
@@ -53,4 +53,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM,int* pN){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Vector<IssmDouble>** pvec){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot return a Vec");}
@@ -66,4 +67,5 @@
 		void  SetValue(char* string){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a IssmDouble vec array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M,int N){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
@@ -74,4 +76,5 @@
 		void  SetValue(FILE* fid){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Parameter " <<EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/Params/VectorParam.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Params/VectorParam.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/Params/VectorParam.h	(revision 27696)
@@ -50,4 +50,5 @@
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
+		void  GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");}
 		void  GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a matrix array");}
 		void  GetParameterValue(Matrix<IssmDouble>** pmat){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Mat");}
@@ -63,4 +64,5 @@
 		void  SetValue(char* string){_error_("Vector of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a string");}
 		void  SetValue(char** stringarray,int M){_error_("Vector of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a string array");}
+		void  SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* IssmDoublearray,int M){_error_("Vector of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a IssmDouble array");}
 		void  SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Vector of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a IssmDouble array");}
@@ -71,4 +73,5 @@
 		void  SetValue(FILE* fid){_error_("Vector of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold a FILE");}
 		void  SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an array of matrices");}
+		void  SetGradient(IssmDouble* poutput, int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");};
 		/*}}}*/
 };
Index: /issm/trunk-jpl/src/c/classes/classes.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/classes.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/classes/classes.h	(revision 27696)
@@ -90,4 +90,5 @@
 #include "./Params/GenericParam.h"
 #include "./Params/BoolParam.h"
+#include "./Params/ControlParam.h"
 #include "./Params/DoubleMatParam.h"
 #include "./Params/DoubleTransientMatParam.h"
Index: /issm/trunk-jpl/src/c/cores/controladm1qn3_core.cpp
===================================================================
--- /issm/trunk-jpl/src/c/cores/controladm1qn3_core.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/cores/controladm1qn3_core.cpp	(revision 27696)
@@ -234,6 +234,12 @@
 	double  *XL = NULL;
 	double  *XU = NULL;
-	GetPassiveVectorFromControlInputsx(&XL,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound");
-	GetPassiveVectorFromControlInputsx(&XU,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound");
+	if(IsParamEnum(control_enum[0])){
+		femmodel->parameters->FindControlParamAndMakePassive(&XL,NULL,control_enum[0],"lowerbound");
+		femmodel->parameters->FindControlParamAndMakePassive(&XU,NULL,control_enum[0],"upperbound");
+	}
+	else{
+		GetPassiveVectorFromControlInputsx(&XL,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound");
+		GetPassiveVectorFromControlInputsx(&XU,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound");
+	}
 
 	int offset = 0;
@@ -251,5 +257,18 @@
 	#ifdef _HAVE_CODIPACK_
 	if(checkpoint_frequency && solution_type == TransientSolutionEnum){
-		SetControlInputsFromVectorx(femmodel,X);
+		if(IsParamEnum(control_enum[0])){
+#ifdef _HAVE_AD_
+			IssmDouble* aX=xNew<IssmDouble>(intn,"t");
+#else
+			IssmDouble* aX=xNew<IssmDouble>(intn);
+#endif
+			for(int i=0;i<intn;i++) {
+				aX[i]=X[i];
+			}
+			femmodel->parameters->SetControlParam(aX,M[0],control_enum[0]);	
+		}
+		else{
+			SetControlInputsFromVectorx(femmodel,X);
+		}
 		*pf = transient_ad(femmodel, G, &Jlist[(*Jlisti)*JlistN]);
 	}
@@ -304,5 +323,10 @@
 
 		ISSM_MPI_Bcast(aX,intn,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());
-		SetControlInputsFromVectorx(femmodel,aX);
+		if(IsParamEnum(control_enum[0])){
+			femmodel->parameters->SetControlParam(aX,M[0],control_enum[0]);
+		}
+		else{
+			SetControlInputsFromVectorx(femmodel,aX);
+		}
 		xDelete<IssmDouble>(aX);
 
@@ -574,5 +598,11 @@
 
 	/*Get initial guess*/
-	GetPassiveVectorFromControlInputsx(&X,&intn,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"value");
+	if(IsParamEnum(control_enum[0])){
+		femmodel->parameters->FindControlParamAndMakePassive(&X,NULL,control_enum[0],"value");
+		intn=M[0];
+	}
+	else{
+		GetPassiveVectorFromControlInputsx(&X,&intn,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"value");
+	}
 
 	/*Get problem dimension and initialize gradient and initial guess*/
@@ -632,6 +662,12 @@
 	double  *XL = NULL;
 	double  *XU = NULL;
-	GetPassiveVectorFromControlInputsx(&XL,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound");
-	GetPassiveVectorFromControlInputsx(&XU,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound");
+	if(IsParamEnum(control_enum[0])){
+		femmodel->parameters->FindControlParamAndMakePassive(&XL,NULL,control_enum[0],"lowerbound");
+		femmodel->parameters->FindControlParamAndMakePassive(&XU,NULL,control_enum[0],"upperbound");
+	}
+	else{
+		GetPassiveVectorFromControlInputsx(&XL,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"lowerbound");
+		GetPassiveVectorFromControlInputsx(&XU,NULL,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"upperbound");
+	}
 
    offset = 0;
@@ -654,8 +690,13 @@
 		aG[i] = reCast<IssmDouble>(G[i]);
 	}
-
-	ControlInputSetGradientx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,aG);
-	SetControlInputsFromVectorx(femmodel,aX);
-
+	
+	if(IsParamEnum(control_enum[0])){
+		//femmodel->parameters->ControlParamSetGradient(aG,M[0],control_enum[0]);
+		femmodel->parameters->SetControlParam(aX,M[0],control_enum[0]);	
+	}
+	else{
+		ControlInputSetGradientx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,aG);
+		SetControlInputsFromVectorx(femmodel,aX);
+	}
 	xDelete(aX);
 
Index: /issm/trunk-jpl/src/c/cores/transient_core.cpp
===================================================================
--- /issm/trunk-jpl/src/c/cores/transient_core.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/cores/transient_core.cpp	(revision 27696)
@@ -274,4 +274,6 @@
 	int        step,timestepping;
 	int        checkpoint_frequency,num_responses;
+	int		 *M = NULL;
+	int		 *control_enum;
 
 	/*Get rank*/
@@ -286,4 +288,6 @@
 	femmodel->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);
 	femmodel->parameters->FindParam(&checkpoint_frequency,SettingsCheckpointFrequencyEnum); _assert_(checkpoint_frequency>0);
+	femmodel->parameters->FindParam(&control_enum,NULL,InversionControlParametersEnum);
+	femmodel->parameters->FindParam(&M,NULL,ControlInputSizeMEnum);
 
 	std::vector<IssmDouble> time_all;
@@ -356,6 +360,11 @@
 	/*Get X (control)*/
 	IssmDouble *X = NULL; int Xsize;
-	GetVectorFromControlInputsx(&X,&Xsize,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"value");
-
+	if(IsParamEnum(control_enum[0])){
+		femmodel->parameters->FindControlParam(&X,NULL,control_enum[0],"value");
+		Xsize=M[0];
+	}
+	else{
+		GetVectorFromControlInputsx(&X,&Xsize,femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,"value");
+	}
 	/*Initialize model state adjoint (Yb)*/
 	double *Yb  = xNewZeroInit<double>(Ysize);
@@ -383,6 +392,12 @@
 	delete hdl_regin;
 	if(my_rank==0) for(int i=0; i < Xsize; i++) tape_codi.registerInput(X[i]);
-	SetControlInputsFromVectorx(femmodel,X);
-
+	
+	if(IsParamEnum(control_enum[0])){
+		femmodel->parameters->SetControlParam(X,M[0],control_enum[0]);
+	}
+	else{
+		SetControlInputsFromVectorx(femmodel,X);
+	}
+	
 	IssmDouble J     = 0.;
 	int        count = 0;
@@ -446,5 +461,11 @@
 		/*Tell codipack that X is the independent*/
 		for(int i=0; i<Xsize; i++) tape_codi.registerInput(X[i]);
-		SetControlInputsFromVectorx(femmodel,X);
+		
+		if(IsParamEnum(control_enum[0])){
+			femmodel->parameters->SetControlParam(X,M[0],control_enum[0]);
+		}
+		else{
+			SetControlInputsFromVectorx(femmodel,X);
+		}
 
 		/*Get New state*/
@@ -510,4 +531,6 @@
 	xDelete<double>(Yb);
 	xDelete<int>(Yin);
+	xDelete<int>(control_enum);
+	xDelete<int>(M);
 	return J.getValue();
 }/*}}}*/
Index: /issm/trunk-jpl/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp
===================================================================
--- /issm/trunk-jpl/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp	(revision 27696)
@@ -283,5 +283,8 @@
 			}
 			else if(IsParamEnum(input_enum)){
-				_error_("not supported yet");
+				//_error_("not supported yet");
+				Interp_all[i] = P0Enum;
+				parameters->AddObject(new ControlParam(independent,independents_min,independents_max,input_enum,M_all[i]));
+
 			}
 			xDelete<IssmDouble>(independent);
Index: /issm/trunk-jpl/src/c/shared/Enum/Enum.vim
===================================================================
--- /issm/trunk-jpl/src/c/shared/Enum/Enum.vim	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/Enum/Enum.vim	(revision 27696)
@@ -1412,4 +1412,5 @@
 syn keyword cConstant ControlInputMinsEnum
 syn keyword cConstant ControlInputValuesEnum
+syn keyword cConstant ControlParamEnum
 syn keyword cConstant CrouzeixRaviartEnum
 syn keyword cConstant CuffeyEnum
@@ -1777,4 +1778,5 @@
 syn keyword cType Contours
 syn keyword cType ControlInput
+syn keyword cType ControlParam
 syn keyword cType Covertree
 syn keyword cType DatasetInput
Index: /issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h
===================================================================
--- /issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/Enum/EnumDefinitions.h	(revision 27696)
@@ -1411,4 +1411,5 @@
 	ControlInputMinsEnum,
 	ControlInputValuesEnum,
+	ControlParamEnum,
 	CrouzeixRaviartEnum,
 	CuffeyEnum,
Index: /issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp
===================================================================
--- /issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/Enum/EnumToStringx.cpp	(revision 27696)
@@ -1414,4 +1414,5 @@
 		case ControlInputMinsEnum : return "ControlInputMins";
 		case ControlInputValuesEnum : return "ControlInputValues";
+		case ControlParamEnum : return "ControlParam";
 		case CrouzeixRaviartEnum : return "CrouzeixRaviart";
 		case CuffeyEnum : return "Cuffey";
Index: /issm/trunk-jpl/src/c/shared/Enum/Enumjl.vim
===================================================================
--- /issm/trunk-jpl/src/c/shared/Enum/Enumjl.vim	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/Enum/Enumjl.vim	(revision 27696)
@@ -1405,4 +1405,5 @@
 syn keyword juliaConstC ControlInputMinsEnum
 syn keyword juliaConstC ControlInputValuesEnum
+syn keyword juliaConstC ControlParamEnum
 syn keyword juliaConstC CrouzeixRaviartEnum
 syn keyword juliaConstC CuffeyEnum
Index: /issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp
===================================================================
--- /issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/Enum/StringToEnumx.cpp	(revision 27696)
@@ -1447,4 +1447,5 @@
 	      else if (strcmp(name,"ControlInputMins")==0) return ControlInputMinsEnum;
 	      else if (strcmp(name,"ControlInputValues")==0) return ControlInputValuesEnum;
+	      else if (strcmp(name,"ControlParam")==0) return ControlParamEnum;
 	      else if (strcmp(name,"CrouzeixRaviart")==0) return CrouzeixRaviartEnum;
 	      else if (strcmp(name,"Cuffey")==0) return CuffeyEnum;
@@ -1489,9 +1490,9 @@
 	      else if (strcmp(name,"FSpressure")==0) return FSpressureEnum;
 	      else if (strcmp(name,"FSvelocity")==0) return FSvelocityEnum;
-	      else if (strcmp(name,"FemModel")==0) return FemModelEnum;
          else stage=13;
    }
    if(stage==13){
-	      if (strcmp(name,"FileParam")==0) return FileParamEnum;
+	      if (strcmp(name,"FemModel")==0) return FemModelEnum;
+	      else if (strcmp(name,"FileParam")==0) return FileParamEnum;
 	      else if (strcmp(name,"FixedTimestepping")==0) return FixedTimesteppingEnum;
 	      else if (strcmp(name,"FloatingArea")==0) return FloatingAreaEnum;
@@ -1612,9 +1613,9 @@
 	      else if (strcmp(name,"MatrixParam")==0) return MatrixParamEnum;
 	      else if (strcmp(name,"MaxAbsVx")==0) return MaxAbsVxEnum;
-	      else if (strcmp(name,"MaxAbsVy")==0) return MaxAbsVyEnum;
          else stage=14;
    }
    if(stage==14){
-	      if (strcmp(name,"MaxAbsVz")==0) return MaxAbsVzEnum;
+	      if (strcmp(name,"MaxAbsVy")==0) return MaxAbsVyEnum;
+	      else if (strcmp(name,"MaxAbsVz")==0) return MaxAbsVzEnum;
 	      else if (strcmp(name,"MaxDivergence")==0) return MaxDivergenceEnum;
 	      else if (strcmp(name,"MaxVel")==0) return MaxVelEnum;
@@ -1735,9 +1736,9 @@
 	      else if (strcmp(name,"StressbalanceAnalysis")==0) return StressbalanceAnalysisEnum;
 	      else if (strcmp(name,"StressbalanceConvergenceNumSteps")==0) return StressbalanceConvergenceNumStepsEnum;
-	      else if (strcmp(name,"StressbalanceSIAAnalysis")==0) return StressbalanceSIAAnalysisEnum;
          else stage=15;
    }
    if(stage==15){
-	      if (strcmp(name,"StressbalanceSolution")==0) return StressbalanceSolutionEnum;
+	      if (strcmp(name,"StressbalanceSIAAnalysis")==0) return StressbalanceSIAAnalysisEnum;
+	      else if (strcmp(name,"StressbalanceSolution")==0) return StressbalanceSolutionEnum;
 	      else if (strcmp(name,"StressbalanceVerticalAnalysis")==0) return StressbalanceVerticalAnalysisEnum;
 	      else if (strcmp(name,"StringArrayParam")==0) return StringArrayParamEnum;
Index: /issm/trunk-jpl/src/c/shared/io/Marshalling/IoCodeConversions.cpp
===================================================================
--- /issm/trunk-jpl/src/c/shared/io/Marshalling/IoCodeConversions.cpp	(revision 27695)
+++ /issm/trunk-jpl/src/c/shared/io/Marshalling/IoCodeConversions.cpp	(revision 27696)
@@ -166,4 +166,9 @@
 		const char* field = "md.calving.stress_threshold_groundedice";
 		input_enum        = CalvingStressThresholdGroundediceEnum;
+		fieldname=xNew<char>((strlen(field)+1)); xMemCpy<char>(fieldname,field,(strlen(field)+1));
+	}
+	else if(strcmp(string_in,"CalvingADStressThresholdGroundedice")==0){
+		const char* field = "md.calving.stress_threshold_groundedice";
+		input_enum        = CalvingADStressThresholdGroundediceEnum;
 		fieldname=xNew<char>((strlen(field)+1)); xMemCpy<char>(fieldname,field,(strlen(field)+1));
 	}
