Index: /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp	(revision 18930)
@@ -6,20 +6,20 @@
 
 /*Model processor*/
+void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
 int  AdjointBalancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
 }/*}}}*/
+void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
 void AdjointBalancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
@@ -106,8 +106,8 @@
 
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void           AdjointBalancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/*The gradient of the cost function is calculated in 2 parts.
 	 *
@@ -146,5 +146,48 @@
 
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble lambda,Jdet; 
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
+
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsP1(basis,gauss);
+
+		adjoint_input->GetInputValue(&lambda,gauss);
+
+		/*Build gradient vector (actually -dJ/da): */
+		for(int i=0;i<numvertices;i++){
+			ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(ge);
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+}/*}}}*/
+void           AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
@@ -195,51 +238,8 @@
 	delete gauss;
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble lambda,Jdet; 
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
-
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		adjoint_input->GetInputValue(&lambda,gauss);
-
-		/*Build gradient vector (actually -dJ/da): */
-		for(int i=0;i<numvertices;i++){
-			ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(ge);
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-}/*}}}*/
-void AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           AdjointBalancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	element->InputUpdateFromSolutionOneDof(solution,AdjointEnum);
 }/*}}}*/
-void AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           AdjointBalancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,10 +26,10 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp	(revision 18930)
@@ -6,20 +6,20 @@
 
 /*Model processor*/
+void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
 int  AdjointBalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
 }/*}}}*/
+void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
 void AdjointBalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
@@ -147,8 +147,8 @@
 	return pe;
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-	_error_("not implemented yet");
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+	_error_("not implemented yet");
+}/*}}}*/
+void           AdjointBalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/*The gradient of the cost function is calculated in 2 parts.
 	 *
@@ -196,99 +196,5 @@
 
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
-	Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(4);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
-		thickness_input->GetInputValue(&thickness, gauss);
-		thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dD): */
-		for(int i=0;i<numvertices;i++){
-			ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
-	Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(4);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
-		thickness_input->GetInputValue(&thickness, gauss);
-		thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dvy): */
-		for(int i=0;i<numvertices;i++){
-			ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Fetch number of vertices for this finite element*/
@@ -314,5 +220,99 @@
 	xDelete<int>(vertexpidlist);
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
+		thickness_input->GetInputValue(&thickness, gauss);
+		thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dD): */
+		for(int i=0;i<numvertices;i++){
+			ge[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+}/*}}}*/
+void           AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* thickness_input = element->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* adjoint_input   = element->GetInput(AdjointEnum);   _assert_(adjoint_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		adjoint_input->GetInputDerivativeValue(&Dlambda[0],xyz_list,gauss);
+		thickness_input->GetInputValue(&thickness, gauss);
+		thickness_input->GetInputDerivativeValue(&dp[0],xyz_list,gauss);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dvy): */
+		for(int i=0;i<numvertices;i++){
+			ge[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+}/*}}}*/
+void           AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -328,5 +328,5 @@
 	}
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,11 +26,11 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18930)
@@ -6,20 +6,20 @@
 
 /*Model processing*/
+void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	   _error_("not implemented yet");
+}/*}}}*/
+void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	   _error_("not implemented yet");
+}/*}}}*/
+void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	   _error_("not implemented yet");
+}/*}}}*/
 int  AdjointHorizAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	_error_("not implemented");
 }/*}}}*/
-void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	   _error_("not implemented yet");
-}/*}}}*/
 void AdjointHorizAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	   _error_("not implemented yet");
-}/*}}}*/
-void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	   _error_("not implemented yet");
-}/*}}}*/
-void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void AdjointHorizAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
@@ -54,4 +54,175 @@
 	}
 }/*}}}*/
+ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	bool        incomplete_adjoint;
+	int         dim,epssize;
+	IssmDouble  Jdet,mu_prime;
+	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij;
+	IssmDouble  eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
+	IssmDouble *xyz_list = NULL;
+
+	/*Get problem dimension*/
+	element->FindParam(&dim,DomainDimensionEnum);
+	if(dim==2) epssize = 3;
+	else       epssize = 6;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int vnumnodes = element->NumberofNodesVelocity();
+	int pnumnodes = element->NumberofNodesPressure();
+	int numdof    = vnumnodes*dim + pnumnodes;
+
+	/*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/
+	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
+	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
+	ElementMatrix* Ke=analysis->CreateKMatrix(element);
+	delete analysis;
+	if(incomplete_adjoint) return Ke;
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input);
+	Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input);
+	Input* vz_input = NULL;
+	if(dim==3){
+		vz_input = element->GetInput(VzEnum);
+	}
+	else{
+		_error_("Not implemented yet");
+	}
+
+	/*Allocate dbasis*/
+	IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(5);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+		element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
+		element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]);
+		eps1[0]=epsilon[0];   eps2[0]=epsilon[2];   eps3[0]=epsilon[3];
+		eps1[1]=epsilon[2];   eps2[1]=epsilon[1];   eps3[1]=epsilon[4];
+		eps1[2]=epsilon[3];   eps2[2]=epsilon[4];   eps3[2]= -epsilon[0] -epsilon[1];
+
+		for(int i=0;i<vnumnodes;i++){
+			for(int j=0;j<vnumnodes;j++){
+				eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i];
+				eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j];
+				eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i];
+				eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j];
+				eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i];
+				eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j];
+
+				Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
+				Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
+				Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii;
+
+				Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
+				Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
+				Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii;
+
+				Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii;
+				Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii;
+				Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii;
+			}
+		}
+	}
+
+	/*Transform Coordinate System*/
+	element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
+
+	/*Clean up and return*/
+	delete gauss;
+	xDelete<IssmDouble>(dbasis);
+	xDelete<IssmDouble>(xyz_list);
+	return Ke;
+}/*}}}*/
+ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	bool        incomplete_adjoint;
+	IssmDouble  Jdet,mu_prime;
+	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
+	IssmDouble  eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
+	IssmDouble *xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/
+	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
+	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
+	ElementMatrix* Ke=analysis->CreateKMatrix(element);
+	delete analysis;
+	if(incomplete_adjoint) return Ke;
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
+
+	/*Allocate dbasis*/
+	IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(5);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+		element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
+		element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]);
+		eps1[0]=2.*epsilon[0]+epsilon[1];   eps2[0]=epsilon[2];
+		eps1[1]=epsilon[2];                 eps2[1]=epsilon[0]+2.*epsilon[1];
+		eps1[2]=epsilon[3];                 eps2[2]=epsilon[4];
+
+		for(int i=0;i<numnodes;i++){
+			for(int j=0;j<numnodes;j++){
+				eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i];
+				eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j];
+				eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i];
+				eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j];
+
+				Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
+				Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
+				Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
+				Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
+			}
+		}
+	}
+
+	/*Transform Coordinate System*/
+	element->TransformStiffnessMatrixCoord(Ke,XYEnum);
+
+	/*Clean up and return*/
+	delete gauss;
+	xDelete<IssmDouble>(dbasis);
+	xDelete<IssmDouble>(xyz_list);
+	return Ke;
+}/*}}}*/
+ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/
+
+	/*Intermediaries*/
+	bool incomplete_adjoint;
+
+	/*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/
+	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
+	ElementMatrix* Ke=analysis->CreateKMatrix(element);
+	delete analysis;
+
+	/*return*/
+	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
+	if(!incomplete_adjoint){
+		_error_("Exact adjoint not supported yet for L1L2 model");
+	}
+	return Ke;
+}/*}}}*/
 ElementMatrix* AdjointHorizAnalysis::CreateKMatrixSSA(Element* element){/*{{{*/
 
@@ -139,175 +310,4 @@
 	xDelete<IssmDouble>(xyz_list);
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
-	return Ke;
-}/*}}}*/
-ElementMatrix* AdjointHorizAnalysis::CreateKMatrixL1L2(Element* element){/*{{{*/
-
-	/*Intermediaries*/
-	bool incomplete_adjoint;
-
-	/*Initialize Jacobian with regular L1L2 (first part of the Gateau derivative)*/
-	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
-	ElementMatrix* Ke=analysis->CreateKMatrix(element);
-	delete analysis;
-
-	/*return*/
-	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
-	if(!incomplete_adjoint){
-		_error_("Exact adjoint not supported yet for L1L2 model");
-	}
-	return Ke;
-}/*}}}*/
-ElementMatrix* AdjointHorizAnalysis::CreateKMatrixHO(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	bool        incomplete_adjoint;
-	IssmDouble  Jdet,mu_prime;
-	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
-	IssmDouble  eps1[3],eps2[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
-	IssmDouble *xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Jacobian with regular HO (first part of the Gateau derivative)*/
-	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
-	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
-	ElementMatrix* Ke=analysis->CreateKMatrix(element);
-	delete analysis;
-	if(incomplete_adjoint) return Ke;
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* vx_input = element->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input = element->GetInput(VyEnum); _assert_(vy_input);
-
-	/*Allocate dbasis*/
-	IssmDouble* dbasis = xNew<IssmDouble>(3*numnodes);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(5);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-		element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
-		element->ViscosityHODerivativeEpsSquare(&mu_prime,&epsilon[0]);
-		eps1[0]=2.*epsilon[0]+epsilon[1];   eps2[0]=epsilon[2];
-		eps1[1]=epsilon[2];                 eps2[1]=epsilon[0]+2.*epsilon[1];
-		eps1[2]=epsilon[3];                 eps2[2]=epsilon[4];
-
-		for(int i=0;i<numnodes;i++){
-			for(int j=0;j<numnodes;j++){
-				eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i]+eps1[2]*dbasis[2*numnodes+i];
-				eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j]+eps1[2]*dbasis[2*numnodes+j];
-				eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i]+eps2[2]*dbasis[2*numnodes+i];
-				eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j]+eps2[2]*dbasis[2*numnodes+j];
-
-				Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
-				Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
-				Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
-				Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
-			}
-		}
-	}
-
-	/*Transform Coordinate System*/
-	element->TransformStiffnessMatrixCoord(Ke,XYEnum);
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(dbasis);
-	xDelete<IssmDouble>(xyz_list);
-	return Ke;
-}/*}}}*/
-ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	bool        incomplete_adjoint;
-	int         dim,epssize;
-	IssmDouble  Jdet,mu_prime;
-	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij,eps3dotdphii,eps3dotdphij;
-	IssmDouble  eps1[3],eps2[3],eps3[3],epsilon[5];/* epsilon=[exx,eyy,exy,exz,eyz];*/
-	IssmDouble *xyz_list = NULL;
-
-	/*Get problem dimension*/
-	element->FindParam(&dim,DomainDimensionEnum);
-	if(dim==2) epssize = 3;
-	else       epssize = 6;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int vnumnodes = element->NumberofNodesVelocity();
-	int pnumnodes = element->NumberofNodesPressure();
-	int numdof    = vnumnodes*dim + pnumnodes;
-
-	/*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/
-	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
-	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
-	ElementMatrix* Ke=analysis->CreateKMatrix(element);
-	delete analysis;
-	if(incomplete_adjoint) return Ke;
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* vx_input = element->GetInput(VxEnum);_assert_(vx_input);
-	Input* vy_input = element->GetInput(VyEnum);_assert_(vy_input);
-	Input* vz_input = NULL;
-	if(dim==3){
-		vz_input = element->GetInput(VzEnum);
-	}
-	else{
-		_error_("Not implemented yet");
-	}
-
-	/*Allocate dbasis*/
-	IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(5);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-		element->StrainRateHO(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
-		element->ViscosityFSDerivativeEpsSquare(&mu_prime,&epsilon[0]);
-		eps1[0]=epsilon[0];   eps2[0]=epsilon[2];   eps3[0]=epsilon[3];
-		eps1[1]=epsilon[2];   eps2[1]=epsilon[1];   eps3[1]=epsilon[4];
-		eps1[2]=epsilon[3];   eps2[2]=epsilon[4];   eps3[2]= -epsilon[0] -epsilon[1];
-
-		for(int i=0;i<vnumnodes;i++){
-			for(int j=0;j<vnumnodes;j++){
-				eps1dotdphii=eps1[0]*dbasis[0*vnumnodes+i]+eps1[1]*dbasis[1*vnumnodes+i]+eps1[2]*dbasis[2*vnumnodes+i];
-				eps1dotdphij=eps1[0]*dbasis[0*vnumnodes+j]+eps1[1]*dbasis[1*vnumnodes+j]+eps1[2]*dbasis[2*vnumnodes+j];
-				eps2dotdphii=eps2[0]*dbasis[0*vnumnodes+i]+eps2[1]*dbasis[1*vnumnodes+i]+eps2[2]*dbasis[2*vnumnodes+i];
-				eps2dotdphij=eps2[0]*dbasis[0*vnumnodes+j]+eps2[1]*dbasis[1*vnumnodes+j]+eps2[2]*dbasis[2*vnumnodes+j];
-				eps3dotdphii=eps3[0]*dbasis[0*vnumnodes+i]+eps3[1]*dbasis[1*vnumnodes+i]+eps3[2]*dbasis[2*vnumnodes+i];
-				eps3dotdphij=eps3[0]*dbasis[0*vnumnodes+j]+eps3[1]*dbasis[1*vnumnodes+j]+eps3[2]*dbasis[2*vnumnodes+j];
-
-				Ke->values[numdof*(4*i+0)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps1dotdphii;
-				Ke->values[numdof*(4*i+0)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps1dotdphii;
-				Ke->values[numdof*(4*i+0)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps1dotdphii;
-
-				Ke->values[numdof*(4*i+1)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps2dotdphii;
-				Ke->values[numdof*(4*i+1)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps2dotdphii;
-				Ke->values[numdof*(4*i+1)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps2dotdphii;
-
-				Ke->values[numdof*(4*i+2)+4*j+0]+=gauss->weight*Jdet*2*mu_prime*eps1dotdphij*eps3dotdphii;
-				Ke->values[numdof*(4*i+2)+4*j+1]+=gauss->weight*Jdet*2*mu_prime*eps2dotdphij*eps3dotdphii;
-				Ke->values[numdof*(4*i+2)+4*j+2]+=gauss->weight*Jdet*2*mu_prime*eps3dotdphij*eps3dotdphii;
-			}
-		}
-	}
-
-	/*Transform Coordinate System*/
-	element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(dbasis);
-	xDelete<IssmDouble>(xyz_list);
 	return Ke;
 }/*}}}*/
@@ -567,4 +567,9 @@
 	return pe;
 }/*}}}*/
+ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/
+
+	/*Same as SSA*/
+	return this->CreatePVectorSSA(element);
+}/*}}}*/
 ElementVector* AdjointHorizAnalysis::CreatePVectorHO(Element* element){/*{{{*/
 
@@ -1042,13 +1047,8 @@
 	return pe;
 }/*}}}*/
-ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/
-
-	/*Same as SSA*/
-	return this->CreatePVectorSSA(element);
-}/*}}}*/
-void AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           AdjointHorizAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/*The gradient of the cost function is calculated in 2 parts.
 	 *
@@ -1138,87 +1138,9 @@
                          
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*return if floating (gradient is 0)*/
-	if(element->IsFloating()) return;
-
-	/*Intermediaries*/
-	int      domaintype,dim;
-	Element* basalelement;
-
-	/*Get basal element*/
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			basalelement = element;
-			dim          = 2;
-			break;
-		case Domain2DverticalEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 1;
-			break;
-		case Domain3DEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 2;
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-
-	/*Intermediaries*/
-	IssmDouble Jdet,weight;
-	IssmDouble dk[3]; 
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = basalelement->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* dbasis        = xNew<IssmDouble>(2*numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	basalelement->GetVerticesCoordinates(&xyz_list);
-	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum);                _assert_(dragcoefficient_input);
-	Input* weights_input         = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=basalelement->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
-		weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
-
-		/*Build alpha_complement_list: */
-		dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
-
-		/*Build gradient vector (actually -dJ/ddrag): */
-		for(int i=0;i<numvertices;i++){
-			if(dim==2){
-				ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
-			}
-			else{
-				ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0];
-			}
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(dbasis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
-
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+	/*WARNING: We use SSA as an estimate for now*/
+	this->GradientJBbarSSA(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
@@ -1295,5 +1217,103 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	   /*Same as SSA*/
+	   return this->GradientJBbarSSA(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*WARNING: We use SSA as an estimate for now*/
+	this->GradientJBbarSSA(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Intermediaries*/
+	int      domaintype,dim;
+	Element* basalelement;
+
+	/*Get basal element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			basalelement = element;
+			dim          = 2;
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 1;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 2;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+	/*Intermediaries*/
+	IssmDouble Jdet,weight;
+	IssmDouble thickness,dmudB;
+	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = basalelement->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	basalelement->GetVerticesCoordinates(&xyz_list);
+	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
+	Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
+	Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
+	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
+	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
+	Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=basalelement->NewGauss(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		thickness_input->GetInputValue(&thickness,gauss);
+		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
+		vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
+		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
+		adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
+
+		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
+
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dB): */
+		for(int i=0;i<numvertices;i++){
+			ge[i]+=-dmudB*thickness*(
+						(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
+						)*Jdet*gauss->weight*basis[i];
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+	/*WARNING: We use HO as an estimate for now*/
+	this->GradientJBHO(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
@@ -1361,8 +1381,81 @@
 	delete gauss;
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*return if floating (gradient is 0)*/
-	if(element->IsFloating()) return;
+void           AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+	/*Intermediaries*/
+	int      domaintype,dim;
+
+	/*Get domaintype*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+
+	/*Intermediaries*/
+	IssmDouble Jdet,weight;
+	IssmDouble thickness,dmudB;
+	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* thickness_input = element->GetInput(ThicknessEnum);             _assert_(thickness_input);
+	Input* vx_input        = element->GetInput(VxEnum);                    _assert_(vx_input);
+	Input* vy_input        = NULL;
+	Input* adjointx_input  = element->GetInput(AdjointxEnum);              _assert_(adjointx_input);
+	Input* adjointy_input  = NULL;
+	Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
+	if(domaintype!=Domain2DverticalEnum){
+		vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
+		adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
+	}
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		thickness_input->GetInputValue(&thickness,gauss);
+		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
+		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
+		dim=2;
+		if(domaintype!=Domain2DverticalEnum){
+			adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss);
+			vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
+			dim=3;
+		}
+
+		element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dB): */
+		for(int i=0;i<numvertices;i++){
+			if(domaintype!=Domain2DverticalEnum){
+				ge[i]+=-dmudB*thickness*(
+							(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
+							)*Jdet*gauss->weight*basis[i];
+			}
+			else{
+				ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i];
+			}
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
@@ -1392,6 +1485,6 @@
 	/*Intermediaries*/
 	IssmDouble Jdet,weight;
-	IssmDouble drag,dalpha2dk;
-	IssmDouble vx,vy,lambda,mu;
+	IssmDouble thickness,dmudB;
+	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
 	IssmDouble *xyz_list= NULL;
 
@@ -1404,15 +1497,13 @@
 	int*        vertexpidlist = xNew<int>(numvertices);
 
-	/*Build friction element, needed later: */
-	Friction* friction=new Friction(basalelement,dim);
-
 	/*Retrieve all inputs we will be needing: */
 	basalelement->GetVerticesCoordinates(&xyz_list);
 	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* vx_input        = basalelement->GetInput(VxEnum);                   _assert_(vx_input);
-	Input* vy_input        = basalelement->GetInput(VyEnum);                   _assert_(vy_input);
-	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);             _assert_(adjointx_input);
-	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);             _assert_(adjointy_input);
-	Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
+	Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
+	Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
+	Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
+	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
+	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
+	Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
 
 	/* Start  looping on the number of gaussian points: */
@@ -1421,18 +1512,20 @@
 		gauss->GaussPoint(ig);
 
-		adjointx_input->GetInputValue(&lambda, gauss);
-		adjointy_input->GetInputValue(&mu, gauss);
-		vx_input->GetInputValue(&vx,gauss);
-		vy_input->GetInputValue(&vy,gauss);
-		dragcoeff_input->GetInputValue(&drag, gauss);
-
-		friction->GetAlphaComplement(&dalpha2dk,gauss);
+		thickness_input->GetInputValue(&thickness,gauss);
+		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
+		vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
+		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
+		adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
+
+		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
 
 		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		basalelement->NodalFunctionsP1(basis,gauss);
 
-		/*Build gradient vector (actually -dJ/dD): */
+		/*Build gradient vector (actually -dJ/dB): */
 		for(int i=0;i<numvertices;i++){
-			ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
+			ge[i]+=-dmudB*thickness*(
+						(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
+						)*Jdet*gauss->weight*basis[i];
 			_assert_(!xIsNan<IssmDouble>(ge[i]));
 		}
@@ -1446,73 +1539,74 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
-	delete friction;
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Same as SSA*/
-	return this->GradientJDragSSA(element,gradient,control_index);
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*return if floating or not on bed (gradient is 0)*/
+void           AdjointHorizAnalysis::GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*return if floating (gradient is 0)*/
 	if(element->IsFloating()) return;
-	if(!element->IsOnBase()) return;
+
+	/*Intermediaries*/
+	int      domaintype,dim;
+	Element* basalelement;
+
+	/*Get basal element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			basalelement = element;
+			dim          = 2;
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 1;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 2;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
 
 	/*Intermediaries*/
 	IssmDouble Jdet,weight;
-	IssmDouble drag,dalpha2dk;
-	IssmDouble vx,vy,lambda,mu;
-	IssmDouble *xyz_list_base= NULL;
-
-	int      domaintype,dim;
-	element->FindParam(&domaintype,DomainTypeEnum);
+	IssmDouble dk[3]; 
+	IssmDouble *xyz_list= NULL;
+
 	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
+	int numvertices = basalelement->GetNumberOfVertices();
 
 	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* dbasis        = xNew<IssmDouble>(2*numvertices);
 	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
 	int*        vertexpidlist = xNew<int>(numvertices);
 
-	/*Build friction element, needed later: */
-	if(domaintype!=Domain2DverticalEnum) dim=3;
-	else dim=2;
-	Friction* friction=new Friction(element,dim);
-
 	/*Retrieve all inputs we will be needing: */
-	element->GetVerticesCoordinatesBase(&xyz_list_base);
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* vx_input        = element->GetInput(VxEnum);                   _assert_(vx_input);
-	Input* vy_input        = NULL;
-	Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
-	Input* adjointy_input  = NULL;
-	Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
-	if(domaintype!=Domain2DverticalEnum){
-		vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
-		adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
-	}
+	basalelement->GetVerticesCoordinates(&xyz_list);
+	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* dragcoefficient_input = basalelement->GetInput(FrictionCoefficientEnum);                _assert_(dragcoefficient_input);
+	Input* weights_input         = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
+
 	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGaussBase(4);
+	Gauss* gauss=basalelement->NewGauss(2);
 	for(int ig=gauss->begin();ig<gauss->end();ig++){
 		gauss->GaussPoint(ig);
 
-		adjointx_input->GetInputValue(&lambda, gauss);
-		vx_input->GetInputValue(&vx,gauss);
-		if(domaintype!=Domain2DverticalEnum){
-			adjointy_input->GetInputValue(&mu, gauss);
-			vy_input->GetInputValue(&vy,gauss);
-		}
-		dragcoeff_input->GetInputValue(&drag, gauss);
-
-		friction->GetAlphaComplement(&dalpha2dk,gauss);
-
-		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dD): */
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
+		weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
+
+		/*Build alpha_complement_list: */
+		dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
+
+		/*Build gradient vector (actually -dJ/ddrag): */
 		for(int i=0;i<numvertices;i++){
-			if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
-			else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i];
+			if(dim==2){
+				ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
+			}
+			else{
+				ge[i]+=-weight*Jdet*gauss->weight*dbasis[0*numvertices+i]*dk[0];
+			}
 			_assert_(!xIsNan<IssmDouble>(ge[i]));
 		}
@@ -1521,12 +1615,13 @@
 
 	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list_base);
-	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(dbasis);
 	xDelete<IssmDouble>(ge);
 	xDelete<int>(vertexpidlist);
 	delete gauss;
-	delete friction;
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*return if floating or not on bed (gradient is 0)*/
@@ -1624,5 +1719,87 @@
 	delete friction;
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Same as SSA*/
+	return this->GradientJDragSSA(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*return if floating or not on bed (gradient is 0)*/
+	if(element->IsFloating()) return;
+	if(!element->IsOnBase()) return;
+
+	/*Intermediaries*/
+	IssmDouble Jdet,weight;
+	IssmDouble drag,dalpha2dk;
+	IssmDouble vx,vy,lambda,mu;
+	IssmDouble *xyz_list_base= NULL;
+
+	int      domaintype,dim;
+	element->FindParam(&domaintype,DomainTypeEnum);
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Build friction element, needed later: */
+	if(domaintype!=Domain2DverticalEnum) dim=3;
+	else dim=2;
+	Friction* friction=new Friction(element,dim);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GetVerticesCoordinatesBase(&xyz_list_base);
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* vx_input        = element->GetInput(VxEnum);                   _assert_(vx_input);
+	Input* vy_input        = NULL;
+	Input* adjointx_input  = element->GetInput(AdjointxEnum);             _assert_(adjointx_input);
+	Input* adjointy_input  = NULL;
+	Input* dragcoeff_input = element->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
+	if(domaintype!=Domain2DverticalEnum){
+		vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
+		adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
+	}
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGaussBase(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		adjointx_input->GetInputValue(&lambda, gauss);
+		vx_input->GetInputValue(&vx,gauss);
+		if(domaintype!=Domain2DverticalEnum){
+			adjointy_input->GetInputValue(&mu, gauss);
+			vy_input->GetInputValue(&vy,gauss);
+		}
+		dragcoeff_input->GetInputValue(&drag, gauss);
+
+		friction->GetAlphaComplement(&dalpha2dk,gauss);
+
+		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
+		element->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dD): */
+		for(int i=0;i<numvertices;i++){
+			if(domaintype!=Domain2DverticalEnum) ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
+			else ge[i]+=-2.*drag*dalpha2dk*(lambda*vx)*Jdet*gauss->weight*basis[i];
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list_base);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+	delete friction;
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*return if floating (gradient is 0)*/
+	if(element->IsFloating()) return;
 
 	/*Intermediaries*/
@@ -1652,5 +1829,90 @@
 	/*Intermediaries*/
 	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudB;
+	IssmDouble drag,dalpha2dk;
+	IssmDouble vx,vy,lambda,mu;
+	IssmDouble *xyz_list= NULL;
+
+	/*Fetch number of vertices for this finite element*/
+	int numvertices = basalelement->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Build friction element, needed later: */
+	Friction* friction=new Friction(basalelement,dim);
+
+	/*Retrieve all inputs we will be needing: */
+	basalelement->GetVerticesCoordinates(&xyz_list);
+	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
+	Input* vx_input        = basalelement->GetInput(VxEnum);                   _assert_(vx_input);
+	Input* vy_input        = basalelement->GetInput(VyEnum);                   _assert_(vy_input);
+	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);             _assert_(adjointx_input);
+	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);             _assert_(adjointy_input);
+	Input* dragcoeff_input = basalelement->GetInput(FrictionCoefficientEnum);  _assert_(dragcoeff_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=basalelement->NewGauss(4);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		adjointx_input->GetInputValue(&lambda, gauss);
+		adjointy_input->GetInputValue(&mu, gauss);
+		vx_input->GetInputValue(&vx,gauss);
+		vy_input->GetInputValue(&vy,gauss);
+		dragcoeff_input->GetInputValue(&drag, gauss);
+
+		friction->GetAlphaComplement(&dalpha2dk,gauss);
+
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->NodalFunctionsP1(basis,gauss);
+
+		/*Build gradient vector (actually -dJ/dD): */
+		for(int i=0;i<numvertices;i++){
+			ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
+			_assert_(!xIsNan<IssmDouble>(ge[i]));
+		}
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(ge);
+	xDelete<int>(vertexpidlist);
+	delete gauss;
+	delete friction;
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
+	/*Intermediaries*/
+	int      domaintype,dim;
+	Element* basalelement;
+
+	/*Get basal element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			basalelement = element;
+			dim          = 2;
+			break;
+		case Domain2DverticalEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 1;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnBase()) return;
+			basalelement = element->SpawnBasalElement();
+			dim          = 2;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+	/*Intermediaries*/
+	IssmDouble Jdet,weight;
+	IssmDouble thickness,dmudD;
 	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
 	IssmDouble *xyz_list= NULL;
@@ -1685,12 +1947,11 @@
 		adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
 
-		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
+		basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input);
 
 		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		basalelement->NodalFunctionsP1(basis,gauss);
 
-		/*Build gradient vector (actually -dJ/dB): */
 		for(int i=0;i<numvertices;i++){
-			ge[i]+=-dmudB*thickness*(
+			ge[i]+=-dmudD*thickness*(
 						(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
 						)*Jdet*gauss->weight*basis[i];
@@ -1708,266 +1969,5 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	   /*Same as SSA*/
-	   return this->GradientJBbarSSA(element,gradient,control_index);
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*WARNING: We use SSA as an estimate for now*/
-	this->GradientJBbarSSA(element,gradient,control_index);
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-	/*WARNING: We use SSA as an estimate for now*/
-	this->GradientJBbarSSA(element,gradient,control_index);
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Intermediaries*/
-	int      domaintype,dim;
-	Element* basalelement;
-
-	/*Get basal element*/
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			basalelement = element;
-			dim          = 2;
-			break;
-		case Domain2DverticalEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 1;
-			break;
-		case Domain3DEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 2;
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-
-	/*Intermediaries*/
-	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudB;
-	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = basalelement->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	basalelement->GetVerticesCoordinates(&xyz_list);
-	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
-	Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
-	Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
-	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
-	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
-	Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=basalelement->NewGauss(4);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		thickness_input->GetInputValue(&thickness,gauss);
-		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
-		vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
-		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
-		adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
-
-		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
-
-		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		basalelement->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dB): */
-		for(int i=0;i<numvertices;i++){
-			ge[i]+=-dmudB*thickness*(
-						(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
-						)*Jdet*gauss->weight*basis[i];
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-	/*Intermediaries*/
-	int      domaintype,dim;
-
-	/*Get domaintype*/
-	element->FindParam(&domaintype,DomainTypeEnum);
-
-	/*Intermediaries*/
-	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudB;
-	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* thickness_input = element->GetInput(ThicknessEnum);             _assert_(thickness_input);
-	Input* vx_input        = element->GetInput(VxEnum);                    _assert_(vx_input);
-	Input* vy_input        = NULL;
-	Input* adjointx_input  = element->GetInput(AdjointxEnum);              _assert_(adjointx_input);
-	Input* adjointy_input  = NULL;
-	Input* rheologyb_input = element->GetInput(MaterialsRheologyBEnum); _assert_(rheologyb_input);
-	if(domaintype!=Domain2DverticalEnum){
-		vy_input        = element->GetInput(VyEnum);                   _assert_(vy_input);
-		adjointy_input  = element->GetInput(AdjointyEnum);             _assert_(adjointy_input);
-	}
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(4);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		thickness_input->GetInputValue(&thickness,gauss);
-		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
-		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
-		dim=2;
-		if(domaintype!=Domain2DverticalEnum){
-			adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list, gauss);
-			vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
-			dim=3;
-		}
-
-		element->dViscositydBHO(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dB): */
-		for(int i=0;i<numvertices;i++){
-			if(domaintype!=Domain2DverticalEnum){
-				ge[i]+=-dmudB*thickness*(
-							(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
-							)*Jdet*gauss->weight*basis[i];
-			}
-			else{
-				ge[i]+=-dmudB*thickness*4*dvx[0]*dadjx[0]*Jdet*gauss->weight*basis[i];
-			}
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-	/*WARNING: We use HO as an estimate for now*/
-	this->GradientJBHO(element,gradient,control_index);
-}/*}}}*/
-void AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-
-	/*Intermediaries*/
-	int      domaintype,dim;
-	Element* basalelement;
-
-	/*Get basal element*/
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			basalelement = element;
-			dim          = 2;
-			break;
-		case Domain2DverticalEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 1;
-			break;
-		case Domain3DEnum:
-			if(!element->IsOnBase()) return;
-			basalelement = element->SpawnBasalElement();
-			dim          = 2;
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-
-	/*Intermediaries*/
-	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudD;
-	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
-	IssmDouble *xyz_list= NULL;
-
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = basalelement->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* basis         = xNew<IssmDouble>(numvertices);
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	basalelement->GetVerticesCoordinates(&xyz_list);
-	basalelement->GradientIndexing(&vertexpidlist[0],control_index);
-	Input* thickness_input = basalelement->GetInput(ThicknessEnum);             _assert_(thickness_input);
-	Input* vx_input        = basalelement->GetInput(VxEnum);                    _assert_(vx_input);
-	Input* vy_input        = basalelement->GetInput(VyEnum);                    _assert_(vy_input);
-	Input* adjointx_input  = basalelement->GetInput(AdjointxEnum);              _assert_(adjointx_input);
-	Input* adjointy_input  = basalelement->GetInput(AdjointyEnum);              _assert_(adjointy_input);
-	Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=basalelement->NewGauss(4);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		thickness_input->GetInputValue(&thickness,gauss);
-		vx_input->GetInputDerivativeValue(&dvx[0],xyz_list,gauss);
-		vy_input->GetInputDerivativeValue(&dvy[0],xyz_list,gauss);
-		adjointx_input->GetInputDerivativeValue(&dadjx[0],xyz_list,gauss);
-		adjointy_input->GetInputDerivativeValue(&dadjy[0],xyz_list,gauss);
-
-		basalelement->dViscositydDSSA(&dmudD,dim,xyz_list,gauss,vx_input,vy_input);
-
-		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		basalelement->NodalFunctionsP1(basis,gauss);
-
-		for(int i=0;i<numvertices;i++){
-			ge[i]+=-dmudD*thickness*(
-						(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
-						)*Jdet*gauss->weight*basis[i];
-			_assert_(!xIsNan<IssmDouble>(ge[i]));
-		}
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(ge);
-	xDelete<int>(vertexpidlist);
-	delete gauss;
-	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
-}/*}}}*/
-void AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           AdjointHorizAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	int approximation;
 	element->GetInputValue(&approximation,ApproximationEnum);
@@ -1979,5 +1979,91 @@
 	}
 }/*}}}*/
-void AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
+void           AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
+	int          i,fe_FS;
+	int*         vdoflist=NULL;
+	int*         pdoflist=NULL;
+	IssmDouble   FSreconditioning;
+
+	int      domaintype,dim;
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			dim          = 3;
+			break;
+		case Domain2DverticalEnum:
+			dim          = 2;
+			break;
+		case Domain3DEnum:
+			dim          = 3;
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int vnumnodes = element->NumberofNodesVelocity();
+	int pnumnodes = element->NumberofNodesPressure();
+	int vnumdof   = vnumnodes*dim;
+	int pnumdof   = pnumnodes*1;
+
+	/*Initialize values*/
+	IssmDouble* values  = xNew<IssmDouble>(vnumdof+pnumdof);
+	IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes);
+	IssmDouble* lambday = xNew<IssmDouble>(vnumnodes);
+	IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes);
+	IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes);
+
+	int* cs_list = xNew<int>(vnumnodes+pnumnodes);
+	if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
+	else       for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum;
+	for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum;
+
+	/*Get dof list: */
+	element->GetDofListVelocity(&vdoflist,GsetEnum);
+	element->GetDofListPressure(&pdoflist,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<vnumdof;i++) values[i]        =solution[vdoflist[i]];
+	for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]];
+
+	/*Transform solution in Cartesian Space*/
+	element->TransformSolutionCoord(values,cs_list);
+
+	/*fill in all arrays: */
+	for(i=0;i<vnumnodes;i++){
+		lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
+		lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
+		if(dim==3){
+			lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector");
+		}
+	}
+	for(i=0;i<pnumnodes;i++){
+		lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Recondition pressure and compute vel: */
+	element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum);
+	for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning;
+
+	/*Add vx and vy as inputs to the tria element: */
+	element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation());
+	element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation());
+	if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation());
+
+	element->FindParam(&fe_FS,FlowequationFeFSEnum);
+	if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum)	
+	 element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation());	
+
+	/*Free ressources:*/
+	xDelete<int>(vdoflist);
+	xDelete<int>(pdoflist);
+	xDelete<int>(cs_list);
+	xDelete<IssmDouble>(lambdap);
+	xDelete<IssmDouble>(lambdaz);
+	xDelete<IssmDouble>(lambday);
+	xDelete<IssmDouble>(lambdax);
+	xDelete<IssmDouble>(values);
+}/*}}}*/
+void           AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
 	int  i;
 	int* doflist=NULL;
@@ -2025,91 +2111,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
-	int          i,fe_FS;
-	int*         vdoflist=NULL;
-	int*         pdoflist=NULL;
-	IssmDouble   FSreconditioning;
-
-	int      domaintype,dim;
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			dim          = 3;
-			break;
-		case Domain2DverticalEnum:
-			dim          = 2;
-			break;
-		case Domain3DEnum:
-			dim          = 3;
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int vnumnodes = element->NumberofNodesVelocity();
-	int pnumnodes = element->NumberofNodesPressure();
-	int vnumdof   = vnumnodes*dim;
-	int pnumdof   = pnumnodes*1;
-
-	/*Initialize values*/
-	IssmDouble* values  = xNew<IssmDouble>(vnumdof+pnumdof);
-	IssmDouble* lambdax = xNew<IssmDouble>(vnumnodes);
-	IssmDouble* lambday = xNew<IssmDouble>(vnumnodes);
-	IssmDouble* lambdaz = xNew<IssmDouble>(vnumnodes);
-	IssmDouble* lambdap = xNew<IssmDouble>(pnumnodes);
-
-	int* cs_list = xNew<int>(vnumnodes+pnumnodes);
-	if(dim==2) for(i=0;i<vnumnodes;i++) cs_list[i] = XYEnum;
-	else       for(i=0;i<vnumnodes;i++) cs_list[i] = XYZEnum;
-	for(i=0;i<pnumnodes;i++) cs_list[vnumnodes+i] = PressureEnum;
-
-	/*Get dof list: */
-	element->GetDofListVelocity(&vdoflist,GsetEnum);
-	element->GetDofListPressure(&pdoflist,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<vnumdof;i++) values[i]        =solution[vdoflist[i]];
-	for(i=0;i<pnumdof;i++) values[vnumdof+i]=solution[pdoflist[i]];
-
-	/*Transform solution in Cartesian Space*/
-	element->TransformSolutionCoord(values,cs_list);
-
-	/*fill in all arrays: */
-	for(i=0;i<vnumnodes;i++){
-		lambdax[i] = values[i*dim+0]; if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
-		lambday[i] = values[i*dim+1]; if(xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
-		if(dim==3){
-			lambdaz[i] = values[i*dim+2]; if(xIsNan<IssmDouble>(lambdaz[i])) _error_("NaN found in solution vector");
-		}
-	}
-	for(i=0;i<pnumnodes;i++){
-		lambdap[i] = values[vnumdof+i]; if(xIsNan<IssmDouble>(lambdap[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Recondition pressure and compute vel: */
-	element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum);
-	for(i=0;i<pnumnodes;i++) lambdap[i]=lambdap[i]*FSreconditioning;
-
-	/*Add vx and vy as inputs to the tria element: */
-	element->AddInput(AdjointxEnum,lambdax,element->VelocityInterpolation());
-	element->AddInput(AdjointyEnum,lambday,element->VelocityInterpolation());
-	if(domaintype!=Domain2DverticalEnum) element->AddInput(AdjointzEnum,lambdaz,element->VelocityInterpolation());
-
-	element->FindParam(&fe_FS,FlowequationFeFSEnum);
-	if(fe_FS!=LATaylorHoodEnum && fe_FS!=LACrouzeixRaviartEnum)	
-	 element->AddInput(AdjointpEnum,lambdap,element->PressureInterpolation());	
-
-	/*Free ressources:*/
-	xDelete<int>(vdoflist);
-	xDelete<int>(pdoflist);
-	xDelete<int>(cs_list);
-	xDelete<IssmDouble>(lambdap);
-	xDelete<IssmDouble>(lambdaz);
-	xDelete<IssmDouble>(lambday);
-	xDelete<IssmDouble>(lambdax);
-	xDelete<IssmDouble>(values);
-}/*}}}*/
-void AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -25,34 +25,34 @@
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
+		ElementMatrix* CreateKMatrixFS(Element* element);
+		ElementMatrix* CreateKMatrixHO(Element* element);
+		ElementMatrix* CreateKMatrixL1L2(Element* element);
 		ElementMatrix* CreateKMatrixSSA(Element* element);
-		ElementMatrix* CreateKMatrixL1L2(Element* element);
-		ElementMatrix* CreateKMatrixHO(Element* element);
-		ElementMatrix* CreateKMatrixFS(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		ElementVector* CreatePVectorSSA(Element* element);
+		ElementVector* CreatePVectorFS(Element* element);
 		ElementVector* CreatePVectorL1L2(Element* element);
 		ElementVector* CreatePVectorHO(Element* element);
-		ElementVector* CreatePVectorFS(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-		void InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element);
-		void InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);
+		ElementVector* CreatePVectorSSA(Element* element);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           GradientJBbarFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBbarHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJBSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDragGradient(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           InputUpdateFromSolutionFS(IssmDouble* solution,Element* element);
+		void           InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp	(revision 18930)
@@ -6,8 +6,21 @@
 
 /*Model processing*/
+void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+
+	int finiteelement = P1Enum;
+	IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement);
+
+}/*}}}*/
+void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+}/*}}}*/
+void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	int finiteelement = P1Enum;
+	::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement);
+}/*}}}*/
 int  Balancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void Balancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -38,18 +51,5 @@
 
 }/*}}}*/
-void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int finiteelement = P1Enum;
-	::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement);
-}/*}}}*/
-void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-
-	int finiteelement = P1Enum;
-	IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement);
-
-}/*}}}*/
-void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
+void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -62,160 +62,5 @@
 	return NULL;
 }/*}}}*/
-ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/
-_error_("Not implemented");
-}/*}}}*/
-ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	IssmDouble  Jdet,D0,omega;
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element vector and other vectors*/
-	ElementMatrix* Ke     = element->NewElementMatrix();
-	IssmDouble*    dbasis = xNew<IssmDouble>(2*numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
-	Input* D0_input    = element->GetInput(BalancethicknessD0Enum);
-	if(!D0_input){
-		this->CreateD0(element);
-		D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
-	}
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		D0_input->GetInputValue(&D0,gauss);
-		omega_input->GetInputValue(&omega,gauss);
-
-		for(int i=0;i<numnodes;i++){
-			for(int j=0;j<numnodes;j++){
-				Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]);
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(dbasis);
-	delete gauss;
-	return Ke;
-}/*}}}*/
-ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	IssmDouble  dhdt,mb,ms,Jdet;
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element vector and other vectors*/
-	ElementVector* pe    = element->NewElementVector();
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* ms_input   = element->GetInput(SurfaceforcingsMassBalanceEnum);                _assert_(ms_input);
-	Input* mb_input   = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);       _assert_(mb_input);
-	Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum);            _assert_(dhdt_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctions(basis,gauss);
-
-		ms_input->GetInputValue(&ms,gauss);
-		mb_input->GetInputValue(&mb,gauss);
-		dhdt_input->GetInputValue(&dhdt,gauss);
-
-		for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(
-					(ms-mb-dhdt)*basis[i]
-					);
-	}
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	delete gauss;
-	return pe;
-}/*}}}*/
-void Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-		element->GetSolutionFromInputsOneDof(solution,SurfaceEnum);
-}/*}}}*/
-void Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
-	_error_("Not implemented yet");
-}/*}}}*/
-void Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble  ds[2],s,b,D;
-	IssmDouble* xyz_list = NULL;
-
-	//element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
-	element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum);
-
-	/*Fetch number of vertices and allocate velocity vectors*/
-	int numvertices = element->GetNumberOfVertices();
-	IssmDouble* vel_list = xNew<IssmDouble>(numvertices);
-	IssmDouble* vx_list  = xNew<IssmDouble>(numvertices);
-	IssmDouble* vy_list  = xNew<IssmDouble>(numvertices);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* D_input   = element->GetInput(BalancethicknessDiffusionCoefficientEnum);
-	Input* H_input   = element->GetInput(ThicknessEnum);                            _assert_(H_input);
-	Input* s_input   = element->GetInput(SurfaceEnum);                              _assert_(s_input);
-	Input* b_input   = element->GetInput(BaseEnum);                                 _assert_(b_input);
-
-	/*Calculate velocities*/
-	Gauss* gauss=element->NewGauss();
-	for(int iv=0;iv<numvertices;iv++){
-		gauss->GaussVertex(iv);
-
-		if(D_input){
-			D_input->GetInputValue(&D,gauss);
-		}
-		else{
-			D = 0.;
-		}
-		b_input->GetInputValue(&b,gauss);
-		s_input->GetInputValue(&s,gauss);
-		s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
-
-		vx_list[iv] = -1./(s-b)*D*ds[0];
-		vy_list[iv] = -1./(s-b)*D*ds[1];
-		vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2));
-	}
-
-	/*Add vx and vy as inputs to the tria element: */
-	element->AddInput(VxEnum,vx_list,P1Enum);
-	element->AddInput(VyEnum,vy_list,P1Enum);
-	element->AddInput(VelEnum,vel_list,P1Enum);
-
-	/*Free ressources:*/
-	delete gauss;
-	xDelete<IssmDouble>(vy_list);
-	xDelete<IssmDouble>(vx_list);
-	xDelete<IssmDouble>(vel_list);
-	xDelete<IssmDouble>(xyz_list);
-}/*}}}*/
-void Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	/*Default, do nothing*/
-	return;
-}/*}}}*/
-
-/*Specifics*/
-void Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
+void           Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
 
 	/*Intermediaries */
@@ -281,2 +126,155 @@
 	delete gauss;
 }/*}}}*/
+ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/
+_error_("Not implemented");
+}/*}}}*/
+ElementMatrix* Balancethickness2Analysis::CreateKMatrix(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	IssmDouble  Jdet,D0,omega;
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Element vector and other vectors*/
+	ElementMatrix* Ke     = element->NewElementMatrix();
+	IssmDouble*    dbasis = xNew<IssmDouble>(2*numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* omega_input = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
+	Input* D0_input    = element->GetInput(BalancethicknessD0Enum);
+	if(!D0_input){
+		this->CreateD0(element);
+		D0_input = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
+	}
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		D0_input->GetInputValue(&D0,gauss);
+		omega_input->GetInputValue(&omega,gauss);
+
+		for(int i=0;i<numnodes;i++){
+			for(int j=0;j<numnodes;j++){
+				Ke->values[i*numnodes+j] += D0*exp(omega)*gauss->weight*Jdet*(dbasis[0*numnodes+i]*dbasis[0*numnodes+j] + dbasis[1*numnodes+i]*dbasis[1*numnodes+j]);
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(dbasis);
+	delete gauss;
+	return Ke;
+}/*}}}*/
+ElementVector* Balancethickness2Analysis::CreatePVector(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	IssmDouble  dhdt,mb,ms,Jdet;
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Element vector and other vectors*/
+	ElementVector* pe    = element->NewElementVector();
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* ms_input   = element->GetInput(SurfaceforcingsMassBalanceEnum);                _assert_(ms_input);
+	Input* mb_input   = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);       _assert_(mb_input);
+	Input* dhdt_input = element->GetInput(BalancethicknessThickeningRateEnum);            _assert_(dhdt_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctions(basis,gauss);
+
+		ms_input->GetInputValue(&ms,gauss);
+		mb_input->GetInputValue(&mb,gauss);
+		dhdt_input->GetInputValue(&dhdt,gauss);
+
+		for(int i=0;i<numnodes;i++) pe->values[i]+=Jdet*gauss->weight*(
+					(ms-mb-dhdt)*basis[i]
+					);
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	delete gauss;
+	return pe;
+}/*}}}*/
+void           Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+		element->GetSolutionFromInputsOneDof(solution,SurfaceEnum);
+}/*}}}*/
+void           Balancethickness2Analysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+	_error_("Not implemented yet");
+}/*}}}*/
+void           Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble  ds[2],s,b,D;
+	IssmDouble* xyz_list = NULL;
+
+	//element->InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
+	element->InputUpdateFromSolutionOneDof(solution,SurfaceEnum);
+
+	/*Fetch number of vertices and allocate velocity vectors*/
+	int numvertices = element->GetNumberOfVertices();
+	IssmDouble* vel_list = xNew<IssmDouble>(numvertices);
+	IssmDouble* vx_list  = xNew<IssmDouble>(numvertices);
+	IssmDouble* vy_list  = xNew<IssmDouble>(numvertices);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* D_input   = element->GetInput(BalancethicknessDiffusionCoefficientEnum);
+	Input* H_input   = element->GetInput(ThicknessEnum);                            _assert_(H_input);
+	Input* s_input   = element->GetInput(SurfaceEnum);                              _assert_(s_input);
+	Input* b_input   = element->GetInput(BaseEnum);                                 _assert_(b_input);
+
+	/*Calculate velocities*/
+	Gauss* gauss=element->NewGauss();
+	for(int iv=0;iv<numvertices;iv++){
+		gauss->GaussVertex(iv);
+
+		if(D_input){
+			D_input->GetInputValue(&D,gauss);
+		}
+		else{
+			D = 0.;
+		}
+		b_input->GetInputValue(&b,gauss);
+		s_input->GetInputValue(&s,gauss);
+		s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
+
+		vx_list[iv] = -1./(s-b)*D*ds[0];
+		vy_list[iv] = -1./(s-b)*D*ds[1];
+		vel_list[iv] = sqrt(pow(vx_list[iv],2) + pow(vy_list[iv],2));
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	element->AddInput(VxEnum,vx_list,P1Enum);
+	element->AddInput(VyEnum,vy_list,P1Enum);
+	element->AddInput(VelEnum,vel_list,P1Enum);
+
+	/*Free ressources:*/
+	delete gauss;
+	xDelete<IssmDouble>(vy_list);
+	xDelete<IssmDouble>(vx_list);
+	xDelete<IssmDouble>(vel_list);
+	xDelete<IssmDouble>(xyz_list);
+}/*}}}*/
+void           Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+	/*Default, do nothing*/
+	return;
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/Balancethickness2Analysis.h	(revision 18930)
@@ -13,24 +13,22 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
 		ElementVector* CreateDVector(Element* element);
+		void           CreateD0(Element* element);
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-
-		/*Specifics*/
-		void CreateD0(Element* element);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp	(revision 18930)
@@ -6,9 +6,69 @@
 
 /*Model processing*/
+void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*Fetch parameters: */
+	int    stabilization;	
+	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
+
+	/*Do not add constraints in DG*/
+	if(stabilization!=3){
+		IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum);
+	}
+
+}/*}}}*/
+void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*Intermediary*/
+	int element;
+	int stabilization;
+
+	/*Fetch parameters: */
+	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
+
+	/*Loads only in DG*/
+	if (stabilization==3){
+
+		/*Get faces and elements*/
+		CreateFaces(iomodel);
+		iomodel->FetchData(1,ThicknessEnum);
+
+		/*First load data:*/
+		for(int i=0;i<iomodel->numberoffaces;i++){
+
+			/*Get left and right elements*/
+			element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
+
+			/*Now, if this element is not in the partition, pass: */
+			if(!iomodel->my_elements[element]) continue;
+
+			/* Add load */
+			loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum));
+		}
+
+		/*Free data: */
+		iomodel->DeleteData(1,ThicknessEnum);
+	}
+}/*}}}*/
+void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	int  stabilization;
+	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
+
+	/*Check in 3d*/
+	if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
+
+	/*First fetch data: */
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	if(stabilization!=3){
+		::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum);
+	}
+	else{
+		::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum);
+	}
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  BalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));
 }/*}}}*/
 void BalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -50,66 +110,6 @@
 	}
 }/*}}}*/
-void BalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int  stabilization;
-	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
-
-	/*Check in 3d*/
-	if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
-
-	/*First fetch data: */
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	if(stabilization!=3){
-		::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1Enum);
-	}
-	else{
-		::CreateNodes(nodes,iomodel,BalancethicknessAnalysisEnum,P1DGEnum);
-	}
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void BalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*Fetch parameters: */
-	int    stabilization;	
-	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
-
-	/*Do not add constraints in DG*/
-	if(stabilization!=3){
-		IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancethicknessAnalysisEnum,P1Enum);
-	}
-
-}/*}}}*/
-void BalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*Intermediary*/
-	int element;
-	int stabilization;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
-
-	/*Loads only in DG*/
-	if (stabilization==3){
-
-		/*Get faces and elements*/
-		CreateFaces(iomodel);
-		iomodel->FetchData(1,ThicknessEnum);
-
-		/*First load data:*/
-		for(int i=0;i<iomodel->numberoffaces;i++){
-
-			/*Get left and right elements*/
-			element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
-
-			/*Now, if this element is not in the partition, pass: */
-			if(!iomodel->my_elements[element]) continue;
-
-			/* Add load */
-			loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,BalancethicknessAnalysisEnum));
-		}
-
-		/*Free data: */
-		iomodel->DeleteData(1,ThicknessEnum);
-	}
+void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+	parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));
 }/*}}}*/
 
@@ -421,5 +421,5 @@
 	return pe;
 }/*}}}*/
-void BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           BalancethicknessAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
 	 * For node i, Bi can be expressed in the actual coordinate system
@@ -448,5 +448,5 @@
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           BalancethicknessAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
 	 * For node i, Bi' can be expressed in the actual coordinate system
@@ -476,8 +476,8 @@
 
 }/*}}}*/
-void BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           BalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           BalancethicknessAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/* WARNING: this gradient is valid for Soft balance thickness only */
 
@@ -595,5 +595,5 @@
 
 }/*}}}*/
-void BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -609,5 +609,5 @@
 	}
 }/*}}}*/
-void BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -30,10 +30,10 @@
 		ElementVector* CreatePVectorCG(Element* element);
 		ElementVector* CreatePVectorDG(Element* element);
-		void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp	(revision 18930)
@@ -6,8 +6,23 @@
 
 /*Model processing*/
+void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*No constraints for now*/
+	//IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum);
+}/*}}}*/
+void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*No loads*/
+}/*}}}*/
+void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	/*Check in 3d*/
+	if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
+
+	/*First fetch data: */
+	::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum);
+}/*}}}*/
 int  BalancevelocityAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void BalancevelocityAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -38,20 +53,5 @@
 	}
 }/*}}}*/
-void BalancevelocityAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	/*Check in 3d*/
-	if(iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
-
-	/*First fetch data: */
-	::CreateNodes(nodes,iomodel,BalancevelocityAnalysisEnum,P1Enum);
-}/*}}}*/
-void BalancevelocityAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*No constraints for now*/
-	//IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,BalancevelocityAnalysisEnum,P1Enum);
-}/*}}}*/
-void BalancevelocityAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads*/
+void BalancevelocityAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -238,11 +238,11 @@
 	return pe;
 }/*}}}*/
-void BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           BalancevelocityAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           BalancevelocityAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           BalancevelocityAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -258,5 +258,5 @@
 	}
 }/*}}}*/
-void BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp	(revision 18930)
@@ -6,6 +6,57 @@
 
 /*Model processing*/
+void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	int finiteelement;
+	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
+
+	IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);
+
+}/*}}}*/
+void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*Nothing for now*/
+
+}/*}}}*/
+void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	int finiteelement;
+
+	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
+	::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);
+}/*}}}*/
 int  DamageEvolutionAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
+}/*}}}*/
+void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+
+	int finiteelement;
+	bool   islevelset;
+
+	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
+	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
+
+	/*Update elements: */
+	int counter=0;
+	for(int i=0;i<iomodel->numberofelements;i++){
+		if(iomodel->my_elements[i]){
+			Element* element=(Element*)elements->GetObjectByOffset(counter);
+			element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);
+			counter++;
+		}
+	}
+
+	/*What input do I need to run my damage evolution model?*/
+	iomodel->FetchDataToInput(elements,VxEnum);
+	iomodel->FetchDataToInput(elements,VyEnum);
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum);
+	iomodel->FetchDataToInput(elements,DamageDEnum);
+	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
+	iomodel->FetchDataToInput(elements,PressureEnum);
+
+	if(islevelset){
+		iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
+	}
+
 }/*}}}*/
 void DamageEvolutionAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
@@ -45,59 +96,214 @@
 
 }/*}}}*/
-void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-
-	int finiteelement;
-	bool   islevelset;
-
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
-	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
-
-	/*Update elements: */
-	int counter=0;
-	for(int i=0;i<iomodel->numberofelements;i++){
-		if(iomodel->my_elements[i]){
-			Element* element=(Element*)elements->GetObjectByOffset(counter);
-			element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);
-			counter++;
-		}
-	}
-
-	/*What input do I need to run my damage evolution model?*/
-	iomodel->FetchDataToInput(elements,VxEnum);
-	iomodel->FetchDataToInput(elements,VyEnum);
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchDataToInput(elements,VzEnum);
-	iomodel->FetchDataToInput(elements,DamageDEnum);
-	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
-	iomodel->FetchDataToInput(elements,PressureEnum);
-
-	if(islevelset){
-		iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
-	}
-
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int finiteelement;
-
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
-	::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	int finiteelement;
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
-
-	IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);
-
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*Nothing for now*/
-
-}/*}}}*/
 
 /*Finite Element Analysis*/
 void           DamageEvolutionAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
+}/*}}}*/
+void           DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	IssmDouble epsf,stress_threshold,eps0;
+	IssmDouble damage,B,n,epseff;
+	IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;
+	int domaintype,damagelaw;
+
+	/*Fetch number of vertices and allocate output*/
+	int numnodes = element->GetNumberOfNodes();
+	IssmDouble* f   = xNew<IssmDouble>(numnodes);
+
+	/*retrieve parameters:*/
+	element->FindParam(&epsf,DamageC1Enum);
+	element->FindParam(&stress_threshold,DamageStressThresholdEnum);
+	element->FindParam(&domaintype,DomainTypeEnum);
+	element->FindParam(&damagelaw,DamageLawEnum);
+
+	/*Compute stress tensor: */
+	element->ComputeStrainRate();
+
+	/*retrieve what we need: */
+	Input* eps_xx_input  = element->GetInput(StrainRatexxEnum);     _assert_(eps_xx_input);
+	Input* eps_xy_input  = element->GetInput(StrainRatexyEnum);     _assert_(eps_xy_input);
+	Input* eps_yy_input  = element->GetInput(StrainRateyyEnum);     _assert_(eps_yy_input);
+	Input*  n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
+	Input* damage_input = NULL;
+	Input* B_input = NULL;
+	if(domaintype==Domain2DhorizontalEnum){
+		damage_input = element->GetInput(DamageDbarEnum); 	_assert_(damage_input);
+		B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);
+	}
+	else{
+		damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
+		B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
+	}
+
+	/*Calculate damage evolution source term: */
+	Gauss* gauss=element->NewGauss();
+	for (int i=0;i<numnodes;i++){
+		gauss->GaussNode(element->GetElementType(),i);
+		
+		eps_xx_input->GetInputValue(&eps_xx,gauss);
+		eps_xy_input->GetInputValue(&eps_xy,gauss);
+		eps_yy_input->GetInputValue(&eps_yy,gauss);
+		B_input->GetInputValue(&B,gauss);
+		n_input->GetInputValue(&n,gauss);
+		damage_input->GetInputValue(&damage,gauss);
+	
+		/*Calculate principal effective strain rates*/
+		eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
+		eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
+		if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;}
+
+		/*Calculate effective strain rate and threshold strain rate*/
+		epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2);
+		eps0=pow(stress_threshold/B,n);
+
+		if(epseff>eps0){
+			f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage;
+		}
+		else f[i]=0;
+	}
+
+	/*Add input*/
+	element->AddInput(DamageFEnum,f,element->GetElementType());
+	
+	/*Clean up and return*/
+	xDelete<IssmDouble>(f);
+	delete gauss;
+}/*}}}*/
+void           DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	IssmDouble c1,c2,c3,healing,stress_threshold;
+	IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp;
+	IssmDouble J2s,Chi,Psi,PosPsi,NegPsi;
+	IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal;
+	int equivstress,domaintype,damagelaw,dim;
+
+	/*Fetch number of vertices and allocate output*/
+	int numnodes = element->GetNumberOfNodes();
+	IssmDouble* f   = xNew<IssmDouble>(numnodes);
+
+	/*retrieve parameters:*/
+	element->FindParam(&c1,DamageC1Enum);
+	element->FindParam(&c2,DamageC2Enum);
+	element->FindParam(&c3,DamageC3Enum);
+	element->FindParam(&healing,DamageHealingEnum);
+	element->FindParam(&stress_threshold,DamageStressThresholdEnum);
+	element->FindParam(&domaintype,DomainTypeEnum);
+	element->FindParam(&damagelaw,DamageLawEnum);
+
+	/*Get problem dimension*/
+	switch(domaintype){
+		case Domain2DhorizontalEnum: dim = 2; break;
+		case Domain3DEnum:           dim = 3; break;
+		default: _error_("not implemented");
+	}
+	/*Compute stress tensor and Stress Max Principal: */
+	element->ComputeDeviatoricStressTensor();
+	if(dim==3){
+		/*Only works in 3d because the pressure is defined*/
+		element->StressMaxPrincipalCreateInput();
+	}
+	/*retrieve what we need: */
+	Input* tau_xx_input  = element->GetInput(DeviatoricStressxxEnum);     _assert_(tau_xx_input);
+	Input* tau_xy_input  = element->GetInput(DeviatoricStressxyEnum);     _assert_(tau_xy_input);
+	Input* tau_yy_input  = element->GetInput(DeviatoricStressyyEnum);     _assert_(tau_yy_input);
+	Input* tau_xz_input  = NULL;
+	Input* tau_yz_input  = NULL;
+	Input* tau_zz_input  = NULL;
+	Input* stressMaxPrincipal_input = NULL;
+	if(dim==3){
+		tau_xz_input  = element->GetInput(DeviatoricStressxzEnum);     _assert_(tau_xz_input);
+		tau_yz_input  = element->GetInput(DeviatoricStressyzEnum);     _assert_(tau_yz_input);
+		tau_zz_input  = element->GetInput(DeviatoricStresszzEnum);     _assert_(tau_zz_input);
+		stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input);
+	}
+	Input* damage_input = NULL;
+	if(domaintype==Domain2DhorizontalEnum){
+		damage_input = element->GetInput(DamageDbarEnum); 	_assert_(damage_input);
+	}
+	else{
+		damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
+	}
+
+	/*retrieve the desired type of equivalent stress*/
+	element->FindParam(&equivstress,DamageEquivStressEnum);
+
+	/*Calculate damage evolution source term: */
+	Gauss* gauss=element->NewGauss();
+	for (int i=0;i<numnodes;i++){
+		gauss->GaussNode(element->GetElementType(),i);
+		
+		damage_input->GetInputValue(&damage,gauss);
+		tau_xx_input->GetInputValue(&tau_xx,gauss);
+		tau_xy_input->GetInputValue(&tau_xy,gauss);
+		tau_yy_input->GetInputValue(&tau_yy,gauss);
+		if(dim==3){
+			tau_xz_input->GetInputValue(&tau_xz,gauss);
+			tau_yz_input->GetInputValue(&tau_yz,gauss);
+			tau_zz_input->GetInputValue(&tau_zz,gauss);
+		}
+		/*Calculate effective stress components*/
+		s_xx=tau_xx/(1.-damage);
+		s_xy=tau_xy/(1.-damage);
+		s_yy=tau_yy/(1.-damage);
+		if(dim==3){
+			s_xz=tau_xz/(1.-damage);
+			s_yz=tau_yz/(1.-damage);
+			s_zz=tau_zz/(1.-damage);
+		}
+		/*Calculate principal effective stresses*/
+		if(dim==2){
+			s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
+			s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
+			if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;}
+
+			if(equivstress==0){ /* von Mises */
+				Chi=sqrt(s1*s1-s1*s2+s2*s2);
+			}
+			else if(equivstress==1){ /* max principal stress */
+				Chi=s1;
+			}
+			Psi=Chi-stress_threshold;
+			NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
+
+			if(damagelaw==1){
+				PosPsi=max(Psi,0.);
+				f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
+			}
+			else if(damagelaw==2){
+				PosPsi=max(Psi,1.);
+				f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
+			}
+			else _error_("damage law not supported");
+		}
+		else{
+			if(equivstress==1){/* max principal stress */
+				stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss);
+				Chi=stressMaxPrincipal/(1.-damage);
+			}
+			else if(equivstress==0){/* von Mises */
+				Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.);
+			}
+			Psi=Chi-stress_threshold;
+			NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
+			if(damagelaw==1){
+				PosPsi=max(Psi,0.);
+				f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
+			}
+			else if(damagelaw==2){
+				PosPsi=max(Psi,1.);
+				f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
+			}
+			else _error_("damage law not supported");
+		}
+	}
+	/*Add input*/
+	element->AddInput(DamageFEnum,f,element->GetElementType());
+	
+	/*Clean up and return*/
+	xDelete<IssmDouble>(f);
+	delete gauss;
 }/*}}}*/
 ElementVector* DamageEvolutionAnalysis::CreateDVector(Element* element){/*{{{*/
@@ -342,5 +548,5 @@
 	return pe;
 }/*}}}*/
-void DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           DamageEvolutionAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
 	 * For node i, Bi can be expressed in the actual coordinate system
@@ -370,5 +576,5 @@
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           DamageEvolutionAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
 	 * For node i, Bi' can be expressed in the actual coordinate system
@@ -399,11 +605,11 @@
 
 }/*}}}*/
-void DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           DamageEvolutionAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           DamageEvolutionAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           DamageEvolutionAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -445,5 +651,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	bool islevelset;
@@ -454,210 +660,2 @@
 	return;
 }/*}}}*/
-
-/*Intermediaries*/
-void DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	IssmDouble c1,c2,c3,healing,stress_threshold;
-	IssmDouble s_xx,s_xy,s_xz,s_yy,s_yz,s_zz,s1,s2,s3,stmp;
-	IssmDouble J2s,Chi,Psi,PosPsi,NegPsi;
-	IssmDouble damage,tau_xx,tau_xy,tau_xz,tau_yy,tau_yz,tau_zz,stressMaxPrincipal;
-	int equivstress,domaintype,damagelaw,dim;
-
-	/*Fetch number of vertices and allocate output*/
-	int numnodes = element->GetNumberOfNodes();
-	IssmDouble* f   = xNew<IssmDouble>(numnodes);
-
-	/*retrieve parameters:*/
-	element->FindParam(&c1,DamageC1Enum);
-	element->FindParam(&c2,DamageC2Enum);
-	element->FindParam(&c3,DamageC3Enum);
-	element->FindParam(&healing,DamageHealingEnum);
-	element->FindParam(&stress_threshold,DamageStressThresholdEnum);
-	element->FindParam(&domaintype,DomainTypeEnum);
-	element->FindParam(&damagelaw,DamageLawEnum);
-
-	/*Get problem dimension*/
-	switch(domaintype){
-		case Domain2DhorizontalEnum: dim = 2; break;
-		case Domain3DEnum:           dim = 3; break;
-		default: _error_("not implemented");
-	}
-	/*Compute stress tensor and Stress Max Principal: */
-	element->ComputeDeviatoricStressTensor();
-	if(dim==3){
-		/*Only works in 3d because the pressure is defined*/
-		element->StressMaxPrincipalCreateInput();
-	}
-	/*retrieve what we need: */
-	Input* tau_xx_input  = element->GetInput(DeviatoricStressxxEnum);     _assert_(tau_xx_input);
-	Input* tau_xy_input  = element->GetInput(DeviatoricStressxyEnum);     _assert_(tau_xy_input);
-	Input* tau_yy_input  = element->GetInput(DeviatoricStressyyEnum);     _assert_(tau_yy_input);
-	Input* tau_xz_input  = NULL;
-	Input* tau_yz_input  = NULL;
-	Input* tau_zz_input  = NULL;
-	Input* stressMaxPrincipal_input = NULL;
-	if(dim==3){
-		tau_xz_input  = element->GetInput(DeviatoricStressxzEnum);     _assert_(tau_xz_input);
-		tau_yz_input  = element->GetInput(DeviatoricStressyzEnum);     _assert_(tau_yz_input);
-		tau_zz_input  = element->GetInput(DeviatoricStresszzEnum);     _assert_(tau_zz_input);
-		stressMaxPrincipal_input = element->GetInput(StressMaxPrincipalEnum); _assert_(stressMaxPrincipal_input);
-	}
-	Input* damage_input = NULL;
-	if(domaintype==Domain2DhorizontalEnum){
-		damage_input = element->GetInput(DamageDbarEnum); 	_assert_(damage_input);
-	}
-	else{
-		damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
-	}
-
-	/*retrieve the desired type of equivalent stress*/
-	element->FindParam(&equivstress,DamageEquivStressEnum);
-
-	/*Calculate damage evolution source term: */
-	Gauss* gauss=element->NewGauss();
-	for (int i=0;i<numnodes;i++){
-		gauss->GaussNode(element->GetElementType(),i);
-		
-		damage_input->GetInputValue(&damage,gauss);
-		tau_xx_input->GetInputValue(&tau_xx,gauss);
-		tau_xy_input->GetInputValue(&tau_xy,gauss);
-		tau_yy_input->GetInputValue(&tau_yy,gauss);
-		if(dim==3){
-			tau_xz_input->GetInputValue(&tau_xz,gauss);
-			tau_yz_input->GetInputValue(&tau_yz,gauss);
-			tau_zz_input->GetInputValue(&tau_zz,gauss);
-		}
-		/*Calculate effective stress components*/
-		s_xx=tau_xx/(1.-damage);
-		s_xy=tau_xy/(1.-damage);
-		s_yy=tau_yy/(1.-damage);
-		if(dim==3){
-			s_xz=tau_xz/(1.-damage);
-			s_yz=tau_yz/(1.-damage);
-			s_zz=tau_zz/(1.-damage);
-		}
-		/*Calculate principal effective stresses*/
-		if(dim==2){
-			s1=(s_xx+s_yy)/2.+sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
-			s2=(s_xx+s_yy)/2.-sqrt(pow((s_xx-s_yy)/2.,2)+pow(s_xy,2));
-			if(fabs(s2)>fabs(s1)){stmp=s2; s2=s1; s1=stmp;}
-
-			if(equivstress==0){ /* von Mises */
-				Chi=sqrt(s1*s1-s1*s2+s2*s2);
-			}
-			else if(equivstress==1){ /* max principal stress */
-				Chi=s1;
-			}
-			Psi=Chi-stress_threshold;
-			NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
-
-			if(damagelaw==1){
-				PosPsi=max(Psi,0.);
-				f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
-			}
-			else if(damagelaw==2){
-				PosPsi=max(Psi,1.);
-				f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
-			}
-			else _error_("damage law not supported");
-		}
-		else{
-			if(equivstress==1){/* max principal stress */
-				stressMaxPrincipal_input->GetInputValue(&stressMaxPrincipal,gauss);
-				Chi=stressMaxPrincipal/(1.-damage);
-			}
-			else if(equivstress==0){/* von Mises */
-				Chi=sqrt(((s_xx-s_yy)*(s_xx-s_yy)+(s_yy-s_zz)*(s_yy-s_zz)+(s_zz-s_xx)*(s_zz-s_xx)+6.*(s_xy*s_xy+s_yz*s_yz+s_xz*s_xz))/2.);
-			}
-			Psi=Chi-stress_threshold;
-			NegPsi=max(-Chi,0.); /* healing only for compressive stresses */
-			if(damagelaw==1){
-				PosPsi=max(Psi,0.);
-				f[i]= c1*(pow(PosPsi,c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
-			}
-			else if(damagelaw==2){
-				PosPsi=max(Psi,1.);
-				f[i]= c1*(pow(log10(PosPsi),c2) - healing*pow(NegPsi,c2))*pow((1./(1.-damage)),c3);
-			}
-			else _error_("damage law not supported");
-		}
-	}
-	/*Add input*/
-	element->AddInput(DamageFEnum,f,element->GetElementType());
-	
-	/*Clean up and return*/
-	xDelete<IssmDouble>(f);
-	delete gauss;
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	IssmDouble epsf,stress_threshold,eps0;
-	IssmDouble damage,B,n,epseff;
-	IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;
-	int domaintype,damagelaw;
-
-	/*Fetch number of vertices and allocate output*/
-	int numnodes = element->GetNumberOfNodes();
-	IssmDouble* f   = xNew<IssmDouble>(numnodes);
-
-	/*retrieve parameters:*/
-	element->FindParam(&epsf,DamageC1Enum);
-	element->FindParam(&stress_threshold,DamageStressThresholdEnum);
-	element->FindParam(&domaintype,DomainTypeEnum);
-	element->FindParam(&damagelaw,DamageLawEnum);
-
-	/*Compute stress tensor: */
-	element->ComputeStrainRate();
-
-	/*retrieve what we need: */
-	Input* eps_xx_input  = element->GetInput(StrainRatexxEnum);     _assert_(eps_xx_input);
-	Input* eps_xy_input  = element->GetInput(StrainRatexyEnum);     _assert_(eps_xy_input);
-	Input* eps_yy_input  = element->GetInput(StrainRateyyEnum);     _assert_(eps_yy_input);
-	Input*  n_input=element->GetInput(MaterialsRheologyNEnum); _assert_(n_input);
-	Input* damage_input = NULL;
-	Input* B_input = NULL;
-	if(domaintype==Domain2DhorizontalEnum){
-		damage_input = element->GetInput(DamageDbarEnum); 	_assert_(damage_input);
-		B_input=element->GetInput(MaterialsRheologyBbarEnum); _assert_(B_input);
-	}
-	else{
-		damage_input = element->GetInput(DamageDEnum);   _assert_(damage_input);
-		B_input=element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
-	}
-
-	/*Calculate damage evolution source term: */
-	Gauss* gauss=element->NewGauss();
-	for (int i=0;i<numnodes;i++){
-		gauss->GaussNode(element->GetElementType(),i);
-		
-		eps_xx_input->GetInputValue(&eps_xx,gauss);
-		eps_xy_input->GetInputValue(&eps_xy,gauss);
-		eps_yy_input->GetInputValue(&eps_yy,gauss);
-		B_input->GetInputValue(&B,gauss);
-		n_input->GetInputValue(&n,gauss);
-		damage_input->GetInputValue(&damage,gauss);
-	
-		/*Calculate principal effective strain rates*/
-		eps1=(eps_xx+eps_yy)/2.+sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
-		eps2=(eps_xx+eps_yy)/2.-sqrt(pow((eps_xx-eps_yy)/2.,2)+pow(eps_xy,2));
-		if(fabs(eps2)>fabs(eps1)){epstmp=eps2; eps2=eps1; eps1=epstmp;}
-
-		/*Calculate effective strain rate and threshold strain rate*/
-		epseff=1./sqrt(2.)*sqrt(eps1*eps1-eps1*eps2+eps2*eps2);
-		eps0=pow(stress_threshold/B,n);
-
-		if(epseff>eps0){
-			f[i]=1.-pow(eps0/epseff,1./n)*exp(-(epseff-eps0)/(epsf-eps0))-damage;
-		}
-		else f[i]=0;
-	}
-
-	/*Add input*/
-	element->AddInput(DamageFEnum,f,element->GetElementType());
-	
-	/*Clean up and return*/
-	xDelete<IssmDouble>(f);
-	delete gauss;
-}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h	(revision 18930)
@@ -13,27 +13,25 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
+		void           CreateDamageFInputExp(Element* element);
+		void           CreateDamageFInputPralong(Element* element);
 		ElementVector* CreateDVector(Element* element);
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-
-		/*Intermediaries*/
-		void CreateDamageFInputPralong(Element* element);
-		void CreateDamageFInputExp(Element* element);
+		void           GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp	(revision 18930)
@@ -7,28 +7,101 @@
 
 /*Model processing*/
+void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*Intermediary*/
+	int        count;
+	int        M,N;
+	bool       spcpresent = false;
+	IssmDouble heatcapacity;
+	IssmDouble referencetemperature;
+
+	/*Output*/
+	IssmDouble *spcvector  = NULL;
+	IssmDouble* times=NULL;
+	IssmDouble* values=NULL;
+
+	/*Fetch parameters: */
+	iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
+	iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
+
+	/*return if 2d mesh*/
+	if(iomodel->domaintype==Domain2DhorizontalEnum) return;
+
+	/*Fetch data: */
+	iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum);
+
+	//FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS 
+	/*Transient or static?:*/
+	if(M==iomodel->numberofvertices){
+		/*static: just create Constraints objects*/
+		count=0;
+
+		for(int i=0;i<iomodel->numberofvertices;i++){
+			/*keep only this partition's nodes:*/
+			if((iomodel->my_vertices[i])){
+
+				if (!xIsNan<IssmDouble>(spcvector[i])){
+
+					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum));
+					count++;
+
+				}
+			}
+		}
+	}
+	else if (M==(iomodel->numberofvertices+1)){
+		/*transient: create transient SpcTransient objects. Same logic, except we need to retrieve 
+		 * various times and values to initialize an SpcTransient object: */
+		count=0;
+
+		/*figure out times: */
+		times=xNew<IssmDouble>(N);
+		for(int j=0;j<N;j++){
+			times[j]=spcvector[(M-1)*N+j];
+		}
+
+		/*Create constraints from x,y,z: */
+		for(int i=0;i<iomodel->numberofvertices;i++){
+
+			/*keep only this partition's nodes:*/
+			if((iomodel->my_vertices[i])){
+
+				/*figure out times and values: */
+				values=xNew<IssmDouble>(N);
+				spcpresent=false;
+				for(int j=0;j<N;j++){
+					values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature);
+					if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default
+				}
+
+				if(spcpresent){
+					constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum));
+					count++;
+				}
+				xDelete<IssmDouble>(values);
+			}
+		}
+	}
+	else{
+		_error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported");
+	}
+
+	/*Free ressources:*/
+	iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum);
+	xDelete<IssmDouble>(times);
+	xDelete<IssmDouble>(values);
+}/*}}}*/
+void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*No loads */
+}/*}}}*/
+void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  EnthalpyAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
-
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
-
-	iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
-	parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
-	if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
-	iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
-
-	/*Deal with friction parameters*/
-	int frictionlaw;
-	iomodel->Constant(&frictionlaw,FrictionLawEnum);
-	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
 }/*}}}*/
 void EnthalpyAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -132,102 +205,243 @@
 	iomodel->DeleteData(3,TemperatureEnum,WaterfractionEnum,PressureEnum);
 }/*}}}*/
-void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
+
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalReltolEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
+
+	iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
+	parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
+	if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
+	iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
+
+	/*Deal with friction parameters*/
+	int frictionlaw;
+	iomodel->Constant(&frictionlaw,FrictionLawEnum);
+	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
+}/*}}}*/
+
+/*Finite Element Analysis*/
+void           EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
+
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase()) || element->IsFloating()) return;
 
 	/*Intermediary*/
-	int        count;
-	int        M,N;
-	bool       spcpresent = false;
-	IssmDouble heatcapacity;
-	IssmDouble referencetemperature;
-
-	/*Output*/
-	IssmDouble *spcvector  = NULL;
-	IssmDouble* times=NULL;
-	IssmDouble* values=NULL;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
-	iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
-
-	/*return if 2d mesh*/
-	if(iomodel->domaintype==Domain2DhorizontalEnum) return;
-
-	/*Fetch data: */
-	iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum);
-
-	//FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS 
-	/*Transient or static?:*/
-	if(M==iomodel->numberofvertices){
-		/*static: just create Constraints objects*/
-		count=0;
-
-		for(int i=0;i<iomodel->numberofvertices;i++){
-			/*keep only this partition's nodes:*/
-			if((iomodel->my_vertices[i])){
-
-				if (!xIsNan<IssmDouble>(spcvector[i])){
-
-					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum));
-					count++;
-
-				}
+	bool        isdynamicbasalspc;
+	int         numindices;
+	int        *indices = NULL;
+	Node*       node = NULL;
+	IssmDouble	pressure;
+
+	/*Check wether dynamic basal boundary conditions are activated */
+	element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
+	if(!isdynamicbasalspc) return;
+
+	/*Get parameters and inputs: */
+	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
+
+	/*Fetch indices of basal & surface nodes for this finite element*/
+	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
+	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
+
+	GaussPenta* gauss=new GaussPenta();
+	for(int i=0;i<numindices;i++){
+		gauss->GaussNode(element->GetElementType(),indices[i]);
+
+		pressure_input->GetInputValue(&pressure,gauss);
+
+		/*apply or release spc*/
+		node=element->GetNode(indices[i]);
+		if(serial_spc[node->Sid()]==1.){
+			pressure_input->GetInputValue(&pressure, gauss);
+			node->ApplyConstraint(0,PureIceEnthalpy(element,pressure));
+		}
+		else			
+			node->DofInFSet(0);
+	}
+
+	/*Free ressources:*/
+	xDelete<int>(indices);
+	delete gauss;
+}/*}}}*/
+void           EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/
+	/*Compute basal melting rates: */
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		ComputeBasalMeltingrate(element);
+	}
+}/*}}}*/
+void           EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/
+	/*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/
+	/* melting rate is positive when melting, negative when refreezing*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
+
+	/* Only compute melt rates at the base of grounded ice*/
+	if(!element->IsOnBase() || element->IsFloating()) return;
+
+	/* Intermediaries */
+	bool			converged;
+	const int   dim=3;
+	int         i,is,state;
+	int			vertexdown,vertexup,numvertices,numsegments;
+	int			enthalpy_enum;
+	IssmDouble  vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim];
+	IssmDouble  basalfriction,alpha2,geothermalflux,heatflux;
+	IssmDouble  dt,yts;
+	IssmDouble  melting_overshoot,lambda;
+	IssmDouble  vx,vy,vz;
+	IssmDouble *xyz_list      = NULL;
+	IssmDouble *xyz_list_base = NULL;
+	int        *pairindices   = NULL;
+
+	/*Fetch parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GetVerticesCoordinatesBase(&xyz_list_base);
+	element->GetInputValue(&converged,ConvergedEnum);
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	element->FindParam(&yts, ConstantsYtsEnum);
+
+	if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum;
+	else enthalpy_enum=EnthalpyEnum;
+
+	IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
+	IssmDouble rho_ice    = element->GetMaterialParameter(MaterialsRhoIceEnum);
+	IssmDouble rho_water  = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
+	IssmDouble beta		 = element->GetMaterialParameter(MaterialsBetaEnum);
+	IssmDouble kappa		 = EnthalpyDiffusionParameterVolume(element,enthalpy_enum);     _assert_(kappa>=0.);
+	IssmDouble kappa_mix;
+
+	/*retrieve inputs*/
+	Input* enthalpy_input         = element->GetInput(enthalpy_enum);                    _assert_(enthalpy_input);
+	Input* pressure_input			= element->GetInput(PressureEnum);							 _assert_(pressure_input);
+	Input* geothermalflux_input   = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
+	Input* vx_input               = element->GetInput(VxEnum);                          _assert_(vx_input);
+	Input* vy_input               = element->GetInput(VyEnum);                          _assert_(vy_input);
+	Input* vz_input               = element->GetInput(VzEnum);                          _assert_(vz_input);
+
+	/*Build friction element, needed later: */
+	Friction* friction=new Friction(element,dim);
+
+	/******** MELTING RATES  ************************************//*{{{*/
+	element->NormalBase(&normal_base[0],xyz_list_base);
+	element->VerticalSegmentIndices(&pairindices,&numsegments);
+	IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments);
+	IssmDouble* heating = xNew<IssmDouble>(numsegments);	
+
+	numvertices=element->GetNumberOfVertices();
+	IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
+	IssmDouble* pressures = xNew<IssmDouble>(numvertices);
+	IssmDouble* watercolumns = xNew<IssmDouble>(numvertices);
+	IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices);
+	element->GetInputListOnVertices(enthalpies,enthalpy_enum);
+	element->GetInputListOnVertices(pressures,PressureEnum);
+	element->GetInputListOnVertices(watercolumns,WatercolumnEnum);
+	element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum);
+
+	Gauss* gauss=element->NewGauss();
+	for(is=0;is<numsegments;is++){
+		vertexdown = pairindices[is*2+0];
+		vertexup   = pairindices[is*2+1];
+		gauss->GaussVertex(vertexdown);
+
+		state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]);
+		switch (state) {
+			case 0:
+				// cold, dry base: apply basal surface forcing
+				for(i=0;i<3;i++) vec_heatflux[i]=0.;
+				break;
+			case 1: case 2: case 3: 
+				// case 1 : cold, wet base: keep at pressure melting point 
+				// case 2: temperate, thin refreezing base: release spc
+				// case 3: temperate, thin melting base: set spc
+				enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss);
+				for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i];
+				break;
+			case 4:
+				// temperate, thick melting base: set grad H*n=0
+				kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]);
+				pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss);
+				for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i];
+				break;
+			default:
+				_printf0_("	unknown thermal basal state found!");
+		}
+		if(state==0) meltingrate_enthalpy[is]=0.;
+		else{
+			/*heat flux along normal*/
+			heatflux=0.;
+			for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i];
+
+			/*basal friction*/
+			friction->GetAlpha2(&alpha2,gauss);
+			vx_input->GetInputValue(&vx,gauss);		vy_input->GetInputValue(&vy,gauss);		vz_input->GetInputValue(&vz,gauss);
+			basalfriction=alpha2*(vx*vx + vy*vy + vz*vz);
+			geothermalflux_input->GetInputValue(&geothermalflux,gauss);
+			/* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/
+			heating[is]=(heatflux+basalfriction+geothermalflux);
+			meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent
+		}
+	}/*}}}*/
+
+	/******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/
+	for(is=0;is<numsegments;is++){
+		vertexdown = pairindices[is*2+0];
+		vertexup   = pairindices[is*2+1];
+		if(dt!=0.){
+			if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){	// prevent too much freeze on			
+				lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.);
+				watercolumns[vertexdown]=0.;
+				basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn
+				enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice
 			}
-		}
-	}
-	else if (M==(iomodel->numberofvertices+1)){
-		/*transient: create transient SpcTransient objects. Same logic, except we need to retrieve 
-		 * various times and values to initialize an SpcTransient object: */
-		count=0;
-
-		/*figure out times: */
-		times=xNew<IssmDouble>(N);
-		for(int j=0;j<N;j++){
-			times[j]=spcvector[(M-1)*N+j];
-		}
-
-		/*Create constraints from x,y,z: */
-		for(int i=0;i<iomodel->numberofvertices;i++){
-
-			/*keep only this partition's nodes:*/
-			if((iomodel->my_vertices[i])){
-
-				/*figure out times and values: */
-				values=xNew<IssmDouble>(N);
-				spcpresent=false;
-				for(int j=0;j<N;j++){
-					values[j]=heatcapacity*(spcvector[i*N+j]-referencetemperature);
-					if(!xIsNan<IssmDouble>(values[j]))spcpresent=true; //NaN means no spc by default
-				}
-
-				if(spcpresent){
-					constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum));
-					count++;
-				}
-				xDelete<IssmDouble>(values);
+			else{
+				basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
+				watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is]; 
 			}
 		}
-	}
-	else{
-		_error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported");
-	}
-
-	/*Free ressources:*/
-	iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum);
-	xDelete<IssmDouble>(times);
-	xDelete<IssmDouble>(values);
-}/*}}}*/
-void EnthalpyAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads */
-}/*}}}*/
-
-/*Finite Element Analysis*/
-void EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
+		else{
+			basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
+			if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.)
+				watercolumns[vertexdown]=0.;
+			else
+				watercolumns[vertexdown]+=meltingrate_enthalpy[is];
+		}	
+		basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent
+		_assert_(watercolumns[vertexdown]>=0.);
+	}/*}}}*/
+
+	/*feed updated variables back into model*/
+	if(dt!=0.){
+		element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run
+		element->AddInput(WatercolumnEnum,watercolumns,P1Enum);
+	}
+	element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	xDelete<int>(pairindices);
+	xDelete<IssmDouble>(enthalpies);
+	xDelete<IssmDouble>(pressures);
+	xDelete<IssmDouble>(watercolumns);
+	xDelete<IssmDouble>(basalmeltingrates);
+	xDelete<IssmDouble>(meltingrate_enthalpy);
+	xDelete<IssmDouble>(heating);
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(xyz_list_base);
+}/*}}}*/
+void           EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
 	if(VerboseSolution()) _printf0_("   computing enthalpy\n");
 	femmodel->SetCurrentConfiguration(EnthalpyAnalysisEnum);
@@ -741,377 +955,5 @@
 	return pe;
 }/*}}}*/
-void EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi_conduct=[ dh/dx ]
-	 *                  [ dh/dy ]
-	 *                  [ dh/dz ]
-	 * where h is the interpolation function for node i.
-	 *
-	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = dbasis[0*numnodes+i];
-		B[numnodes*1+i] = dbasis[1*numnodes+i];
-		B[numnodes*2+i] = dbasis[2*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-}/*}}}*/
-void EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi_advec =[ h ]
-	 *                 [ h ]
-	 *                 [ h ]
-	 * where h is the interpolation function for node i.
-	 *
-	 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions*/
-	IssmDouble* basis=xNew<IssmDouble>(numnodes);
-	element->NodalFunctions(basis,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = basis[i];
-		B[numnodes*1+i] = basis[i];
-		B[numnodes*2+i] = basis[i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(basis);
-}/*}}}*/
-void EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Biprime_advec=[ dh/dx ]
-	 *                     [ dh/dy ]
-	 *                     [ dh/dz ]
-	 * where h is the interpolation function for node i.
-	 *
-	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = dbasis[0*numnodes+i];
-		B[numnodes*1+i] = dbasis[1*numnodes+i];
-		B[numnodes*2+i] = dbasis[2*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-}/*}}}*/
-void EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-	element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum);
-}/*}}}*/
-void EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
-	_error_("Not implemented yet");
-}/*}}}*/
-void EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
-
-	bool        converged;
-	int         i,rheology_law;
-	IssmDouble  B_average,s_average,T_average=0.,P_average=0.;
-	int        *doflist   = NULL;
-	IssmDouble *xyz_list  = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes    = element->GetNumberOfNodes();
-
-	/*Fetch dof list and allocate solution vector*/
-	element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	IssmDouble* values        = xNew<IssmDouble>(numnodes);
-	IssmDouble* pressure      = xNew<IssmDouble>(numnodes);
-	IssmDouble* surface       = xNew<IssmDouble>(numnodes);
-	IssmDouble* B             = xNew<IssmDouble>(numnodes);
-	IssmDouble* temperature   = xNew<IssmDouble>(numnodes);
-	IssmDouble* waterfraction = xNew<IssmDouble>(numnodes);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numnodes;i++){
-		values[i]=solution[doflist[i]];
-
-		/*Check solution*/
-		if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get all inputs and parameters*/
-	element->GetInputValue(&converged,ConvergedEnum);
-	element->GetInputListOnNodes(&pressure[0],PressureEnum);
-	if(converged){
-		for(i=0;i<numnodes;i++){
-			element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]);
-			if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector");
-			//if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector");
-		}
-		element->AddInput(EnthalpyEnum,values,element->GetElementType());
-		element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType());
-		element->AddInput(TemperatureEnum,temperature,element->GetElementType());
-
-		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
-		 * otherwise the rheology could be negative*/
-		element->FindParam(&rheology_law,MaterialsRheologyLawEnum);
-		element->GetInputListOnNodes(&surface[0],SurfaceEnum);
-		switch(rheology_law){
-			case NoneEnum:
-				/*Do nothing: B is not temperature dependent*/
-				break;
-			case CuffeyEnum:
-				for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]);
-				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
-				break;
-			case PatersonEnum:
-				for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]);
-				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
-				break;
-			case ArrheniusEnum:
-				element->GetVerticesCoordinates(&xyz_list);
-				for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum));
-				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
-				break;
-			case LliboutryDuvalEnum:
-				for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum)); 
-				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 
-				break; 
-			default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet");
-		}
-	}
-	else{
-		element->AddInput(EnthalpyPicardEnum,values,element->GetElementType());
-	}
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(values);
-	xDelete<IssmDouble>(pressure);
-	xDelete<IssmDouble>(surface);
-	xDelete<IssmDouble>(B);
-	xDelete<IssmDouble>(temperature);
-	xDelete<IssmDouble>(waterfraction);
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<int>(doflist);
-}/*}}}*/
-void EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-
-	bool islevelset;
-	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
-	if(islevelset){
-		SetActiveNodesLSMx(femmodel);
-	}
-	return;
-}/*}}}*/
-
-/*Modules*/
-void EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/
-
-	/*Intermediaries*/
-	bool computebasalmeltingrates=true;
-	bool drainicecolumn=true;
-	bool isdynamicbasalspc;
-	IssmDouble dt;
-
-	femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
-	femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-
-	//TODO: use dt to decide what to do
-	if(drainicecolumn)	DrainWaterfraction(femmodel);
-	if(computebasalmeltingrates)	ComputeBasalMeltingrate(femmodel);
-	if(isdynamicbasalspc)	UpdateBasalConstraints(femmodel);
-
-}/*}}}*/
-void EnthalpyAnalysis::ComputeBasalMeltingrate(FemModel* femmodel){/*{{{*/
-	/*Compute basal melting rates: */
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ComputeBasalMeltingrate(element);
-	}
-}/*}}}*/
-void EnthalpyAnalysis::ComputeBasalMeltingrate(Element* element){/*{{{*/
-	/*Calculate the basal melt rates of the enthalpy model after Aschwanden 2012*/
-	/* melting rate is positive when melting, negative when refreezing*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
-
-	/* Only compute melt rates at the base of grounded ice*/
-	if(!element->IsOnBase() || element->IsFloating()) return;
-
-	/* Intermediaries */
-	bool			converged;
-	const int   dim=3;
-	int         i,is,state;
-	int			vertexdown,vertexup,numvertices,numsegments;
-	int			enthalpy_enum;
-	IssmDouble  vec_heatflux[dim],normal_base[dim],d1enthalpy[dim],d1pressure[dim];
-	IssmDouble  basalfriction,alpha2,geothermalflux,heatflux;
-	IssmDouble  dt,yts;
-	IssmDouble  melting_overshoot,lambda;
-	IssmDouble  vx,vy,vz;
-	IssmDouble *xyz_list      = NULL;
-	IssmDouble *xyz_list_base = NULL;
-	int        *pairindices   = NULL;
-
-	/*Fetch parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GetVerticesCoordinatesBase(&xyz_list_base);
-	element->GetInputValue(&converged,ConvergedEnum);
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	element->FindParam(&yts, ConstantsYtsEnum);
-
-	if(dt==0. && !converged) enthalpy_enum=EnthalpyPicardEnum;
-	else enthalpy_enum=EnthalpyEnum;
-
-	IssmDouble latentheat = element->GetMaterialParameter(MaterialsLatentheatEnum);
-	IssmDouble rho_ice    = element->GetMaterialParameter(MaterialsRhoIceEnum);
-	IssmDouble rho_water  = element->GetMaterialParameter(MaterialsRhoFreshwaterEnum);
-	IssmDouble beta		 = element->GetMaterialParameter(MaterialsBetaEnum);
-	IssmDouble kappa		 = EnthalpyDiffusionParameterVolume(element,enthalpy_enum);     _assert_(kappa>=0.);
-	IssmDouble kappa_mix;
-
-	/*retrieve inputs*/
-	Input* enthalpy_input         = element->GetInput(enthalpy_enum);                    _assert_(enthalpy_input);
-	Input* pressure_input			= element->GetInput(PressureEnum);							 _assert_(pressure_input);
-	Input* geothermalflux_input   = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
-	Input* vx_input               = element->GetInput(VxEnum);                          _assert_(vx_input);
-	Input* vy_input               = element->GetInput(VyEnum);                          _assert_(vy_input);
-	Input* vz_input               = element->GetInput(VzEnum);                          _assert_(vz_input);
-
-	/*Build friction element, needed later: */
-	Friction* friction=new Friction(element,dim);
-
-	/******** MELTING RATES  ************************************//*{{{*/
-	element->NormalBase(&normal_base[0],xyz_list_base);
-	element->VerticalSegmentIndices(&pairindices,&numsegments);
-	IssmDouble* meltingrate_enthalpy = xNew<IssmDouble>(numsegments);
-	IssmDouble* heating = xNew<IssmDouble>(numsegments);	
-
-	numvertices=element->GetNumberOfVertices();
-	IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
-	IssmDouble* pressures = xNew<IssmDouble>(numvertices);
-	IssmDouble* watercolumns = xNew<IssmDouble>(numvertices);
-	IssmDouble* basalmeltingrates = xNew<IssmDouble>(numvertices);
-	element->GetInputListOnVertices(enthalpies,enthalpy_enum);
-	element->GetInputListOnVertices(pressures,PressureEnum);
-	element->GetInputListOnVertices(watercolumns,WatercolumnEnum);
-	element->GetInputListOnVertices(basalmeltingrates,BasalforcingsGroundediceMeltingRateEnum);
-
-	Gauss* gauss=element->NewGauss();
-	for(is=0;is<numsegments;is++){
-		vertexdown = pairindices[is*2+0];
-		vertexup   = pairindices[is*2+1];
-		gauss->GaussVertex(vertexdown);
-
-		state=GetThermalBasalCondition(element, enthalpies[vertexdown], enthalpies[vertexup], pressures[vertexdown], pressures[vertexup], watercolumns[vertexdown], basalmeltingrates[vertexdown]);
-		switch (state) {
-			case 0:
-				// cold, dry base: apply basal surface forcing
-				for(i=0;i<3;i++) vec_heatflux[i]=0.;
-				break;
-			case 1: case 2: case 3: 
-				// case 1 : cold, wet base: keep at pressure melting point 
-				// case 2: temperate, thin refreezing base: release spc
-				// case 3: temperate, thin melting base: set spc
-				enthalpy_input->GetInputDerivativeValue(&d1enthalpy[0],xyz_list,gauss);
-				for(i=0;i<3;i++) vec_heatflux[i]=-kappa*d1enthalpy[i];
-				break;
-			case 4:
-				// temperate, thick melting base: set grad H*n=0
-				kappa_mix=GetWetIceConductivity(element, enthalpies[vertexdown], pressures[vertexdown]);
-				pressure_input->GetInputDerivativeValue(&d1pressure[0],xyz_list,gauss);
-				for(i=0;i<3;i++) vec_heatflux[i]=kappa_mix*beta*d1pressure[i];
-				break;
-			default:
-				_printf0_("	unknown thermal basal state found!");
-		}
-		if(state==0) meltingrate_enthalpy[is]=0.;
-		else{
-			/*heat flux along normal*/
-			heatflux=0.;
-			for(i=0;i<3;i++) heatflux+=(vec_heatflux[i])*normal_base[i];
-
-			/*basal friction*/
-			friction->GetAlpha2(&alpha2,gauss);
-			vx_input->GetInputValue(&vx,gauss);		vy_input->GetInputValue(&vy,gauss);		vz_input->GetInputValue(&vz,gauss);
-			basalfriction=alpha2*(vx*vx + vy*vy + vz*vz);
-			geothermalflux_input->GetInputValue(&geothermalflux,gauss);
-			/* -Mb= Fb-(q-q_geo)/((1-w)*L*rho), and (1-w)*rho=rho_ice, cf Aschwanden 2012, eqs.1, 2, 66*/
-			heating[is]=(heatflux+basalfriction+geothermalflux);
-			meltingrate_enthalpy[is]=heating[is]/(latentheat*rho_ice); // m/s water equivalent
-		}
-	}/*}}}*/
-
-	/******** UPDATE MELTINGRATES AND WATERCOLUMN **************//*{{{*/
-	for(is=0;is<numsegments;is++){
-		vertexdown = pairindices[is*2+0];
-		vertexup   = pairindices[is*2+1];
-		if(dt!=0.){
-			if(watercolumns[vertexdown]+meltingrate_enthalpy[is]*dt<0.){	// prevent too much freeze on			
-				lambda = -watercolumns[vertexdown]/(dt*meltingrate_enthalpy[is]); _assert_(lambda>=0.); _assert_(lambda<1.);
-				watercolumns[vertexdown]=0.;
-				basalmeltingrates[vertexdown]=lambda*meltingrate_enthalpy[is]; // restrict freeze on only to size of watercolumn
-				enthalpies[vertexdown]+=(1.-lambda)*dt/yts*meltingrate_enthalpy[is]*latentheat*rho_ice; // use rest of energy to cool down base: dE=L*m, m=(1-lambda)*meltingrate*rho_ice
-			}
-			else{
-				basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
-				watercolumns[vertexdown]+=dt*meltingrate_enthalpy[is]; 
-			}
-		}
-		else{
-			basalmeltingrates[vertexdown]=meltingrate_enthalpy[is];
-			if(watercolumns[vertexdown]+meltingrate_enthalpy[is]<0.)
-				watercolumns[vertexdown]=0.;
-			else
-				watercolumns[vertexdown]+=meltingrate_enthalpy[is];
-		}	
-		basalmeltingrates[vertexdown]*=rho_water/rho_ice; // convert meltingrate from water to ice equivalent
-		_assert_(watercolumns[vertexdown]>=0.);
-	}/*}}}*/
-
-	/*feed updated variables back into model*/
-	if(dt!=0.){
-		element->AddInput(enthalpy_enum,enthalpies,P1Enum); //TODO: distinguis for steadystate and transient run
-		element->AddInput(WatercolumnEnum,watercolumns,P1Enum);
-	}
-	element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	xDelete<int>(pairindices);
-	xDelete<IssmDouble>(enthalpies);
-	xDelete<IssmDouble>(pressures);
-	xDelete<IssmDouble>(watercolumns);
-	xDelete<IssmDouble>(basalmeltingrates);
-	xDelete<IssmDouble>(meltingrate_enthalpy);
-	xDelete<IssmDouble>(heating);
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(xyz_list_base);
-}/*}}}*/
-void EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
+void           EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
 	/*Drain excess water fraction in ice column: */
 	for(int i=0;i<femmodel->elements->Size();i++){
@@ -1120,46 +962,5 @@
 	}
 }/*}}}*/
-void EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
-
-	/* Only drain waterfraction of ice column from element at base*/
-	if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements
-
-	/* Intermediaries*/
-	int is, numvertices, numsegments;
-	int *pairindices   = NULL;
-
-	numvertices=element->GetNumberOfVertices();
-	element->VerticalSegmentIndices(&pairindices,&numsegments);
-
-	IssmDouble* watercolumn = xNew<IssmDouble>(numvertices);
-	IssmDouble* drainrate_column  = xNew<IssmDouble>(numsegments);
-	IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments);
-
-	element->GetInputListOnVertices(watercolumn,WatercolumnEnum);
-
-	for(is=0;is<numsegments;is++)	drainrate_column[is]=0.;
-	Element* elementi = element;
-	for(;;){
-		for(is=0;is<numsegments;is++)	drainrate_element[is]=0.;
-		DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once
-		for(is=0;is<numsegments;is++)	drainrate_column[is]+=drainrate_element[is];
-
-		if(elementi->IsOnSurface()) break;
-		elementi=elementi->GetUpperElement();			
-	}
-	/* add drained water to water column*/
-	for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is];
-	/* Feed updated water column back into model */
-	element->AddInput(WatercolumnEnum,watercolumn,P1Enum);
-
-	xDelete<int>(pairindices);
-	xDelete<IssmDouble>(drainrate_column);
-	xDelete<IssmDouble>(drainrate_element);
-	xDelete<IssmDouble>(watercolumn);
-}/*}}}*/
-void EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
+void           EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
 
 	/* Check if ice in element */
@@ -1223,288 +1024,46 @@
 	xDelete<IssmDouble>(deltawaterfractions);
 }/*}}}*/
-void EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/
-
-	/*Update basal dirichlet BCs for enthalpy: */
-	Vector<IssmDouble>* spc           = NULL;
-	IssmDouble*         serial_spc    = NULL;
-
-	spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum));
-	/*First create a vector to figure out what elements should be constrained*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		GetBasalConstraints(spc,element);
-	}
-
-	/*Assemble and serialize*/
-	spc->Assemble();
-	serial_spc=spc->ToMPISerial();
-	delete spc;
-
-	/*Then update basal constraints nodes accordingly*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ApplyBasalConstraints(serial_spc,element);
-	}
-
-	femmodel->UpdateConstraintsx();
-
-	/*Delete*/
-	xDelete<IssmDouble>(serial_spc);
-}/*}}}*/
-void EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
+void           EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
 
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return;
 
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase()) || element->IsFloating()) return;
-
-	/*Intermediary*/
-	bool        isdynamicbasalspc;
-	int         numindices;
-	int        *indices = NULL;
-	Node*       node = NULL;
-	IssmDouble	pressure;
-
-	/*Check wether dynamic basal boundary conditions are activated */
-	element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
-	if(!isdynamicbasalspc) return;
-
-	/*Get parameters and inputs: */
-	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
-
-	/*Fetch indices of basal & surface nodes for this finite element*/
-	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
-	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
-
-	GaussPenta* gauss=new GaussPenta();
-	for(int i=0;i<numindices;i++){
-		gauss->GaussNode(element->GetElementType(),indices[i]);
-
-		pressure_input->GetInputValue(&pressure,gauss);
-
-		/*apply or release spc*/
-		node=element->GetNode(indices[i]);
-		if(serial_spc[node->Sid()]==1.){
-			pressure_input->GetInputValue(&pressure, gauss);
-			node->ApplyConstraint(0,PureIceEnthalpy(element,pressure));
-		}
-		else			
-			node->DofInFSet(0);
-	}
-
-	/*Free ressources:*/
-	xDelete<int>(indices);
-	delete gauss;
-}/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
-
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase()) || element->IsFloating()) return;
-
-	/*Intermediary*/
-	bool        isdynamicbasalspc;
-	IssmDouble	dt;
-
-	/*Check wether dynamic basal boundary conditions are activated */
-	element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
-	if(!isdynamicbasalspc) return;
-
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	if(dt==0.){
-		GetBasalConstraintsSteadystate(vec_spc,element);
-	}
-	else{
-		GetBasalConstraintsTransient(vec_spc,element);
-	}
-}/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
-
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase()) || element->IsFloating()) return;
-
-	/*Intermediary*/
-	int         numindices, numindicesup, state;
-	int        *indices = NULL, *indicesup = NULL;
-	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
-
-	/*Get parameters and inputs: */
-	Input* enthalpy_input       = element->GetInput(EnthalpyEnum);                    _assert_(enthalpy_input); //TODO: check EnthalpyPicard?
-	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
-	Input* watercolumn_input	 = element->GetInput(WatercolumnEnum);							 _assert_(watercolumn_input);
-	Input* meltingrate_input	 = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);							 _assert_(meltingrate_input);
-
-	/*Fetch indices of basal & surface nodes for this finite element*/
-	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
-	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
-	penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());	_assert_(numindices==numindicesup);
-
-	GaussPenta* gauss=new GaussPenta();
-	GaussPenta* gaussup=new GaussPenta();
-
-	for(int i=0;i<numindices;i++){
-		gauss->GaussNode(element->GetElementType(),indices[i]);
-		gaussup->GaussNode(element->GetElementType(),indicesup[i]);
-		
-		enthalpy_input->GetInputValue(&enthalpy,gauss);
-		enthalpy_input->GetInputValue(&enthalpyup,gaussup);
-		pressure_input->GetInputValue(&pressure,gauss);
-		pressure_input->GetInputValue(&pressureup,gaussup);
-		watercolumn_input->GetInputValue(&watercolumn,gauss);
-		meltingrate_input->GetInputValue(&meltingrate,gauss);
-
-		state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
-
-		switch (state) {
-			case 0:
-				// cold, dry base: apply basal surface forcing
-				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
-				break;
-			case 1:
-				// cold, wet base: keep at pressure melting point 
-				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
-				break;
-			case 2:
-				// temperate, thin refreezing base: release spc
-				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
-				break;
-			case 3:
-				// temperate, thin melting base: set spc
-				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
-				break;
-			case 4:
-				// temperate, thick melting base: set grad H*n=0
-				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
-				break;
-			default:
-				_printf0_("	unknown thermal basal state found!");
-		}
-
-	}
-
-	/*Free ressources:*/
-	xDelete<int>(indices);
-	xDelete<int>(indicesup);
-	delete gauss;
-	delete gaussup;
-}/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
-
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase()) || element->IsFloating()) return;
-
-	/*Intermediary*/
-	int         numindices, numindicesup, state;
-	int        *indices = NULL, *indicesup = NULL;
-	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
-
-	/*Get parameters and inputs: */
-	Input* enthalpy_input		 = element->GetInput(EnthalpyPicardEnum);					 _assert_(enthalpy_input);
-	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
-	Input* watercolumn_input	 = element->GetInput(WatercolumnEnum);							 _assert_(watercolumn_input);
-	Input* meltingrate_input	 = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);							 _assert_(meltingrate_input);
-
-	/*Fetch indices of basal & surface nodes for this finite element*/
-	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
-	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
-	penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());	_assert_(numindices==numindicesup);
-
-	GaussPenta* gauss=new GaussPenta();
-	GaussPenta* gaussup=new GaussPenta();
-	for(int i=0;i<numindices;i++){
-		gauss->GaussNode(element->GetElementType(),indices[i]);
-		gaussup->GaussNode(element->GetElementType(),indicesup[i]);
-
-		enthalpy_input->GetInputValue(&enthalpy,gauss);
-		enthalpy_input->GetInputValue(&enthalpyup,gaussup);
-		pressure_input->GetInputValue(&pressure,gauss);
-		pressure_input->GetInputValue(&pressureup,gaussup);
-		watercolumn_input->GetInputValue(&watercolumn,gauss);
-		meltingrate_input->GetInputValue(&meltingrate,gauss);
-
-		state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
-		switch (state) {
-			case 0:
-				// cold, dry base: apply basal surface forcing
-				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
-				break;
-			case 1:
-				// cold, wet base: keep at pressure melting point 
-				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
-				break;
-			case 2:
-				// temperate, thin refreezing base: release spc
-				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
-				break;
-			case 3:
-				// temperate, thin melting base: set spc
-				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
-				break;
-			case 4:
-				// temperate, thick melting base: s
-				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
-				break;
-			default:
-				_printf0_("	unknown thermal basal state found!");
-		}
-	}
-
-	/*Free ressources:*/
-	xDelete<int>(indices);
-	xDelete<int>(indicesup);
-	delete gauss;
-	delete gaussup;
-}/*}}}*/
-int EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return -1;
-
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase())) return -1;
-
-	/*Intermediary*/
-	int state=-1;
-	IssmDouble	dt;
-
-	/*Get parameters and inputs: */
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-
-	if(enthalpy<PureIceEnthalpy(element,pressure)){
-		if(watercolumn<=0.) state=0; // cold, dry base
-		else state=1; // cold, wet base (refreezing)
-	}
-	else{
-		if(enthalpyup<PureIceEnthalpy(element,pressureup)){
-			if((dt==0.) && (meltingrate<0.)) state=2;	// refreezing temperate base (non-physical, only for steadystate solver)
-			else	state=3; // temperate base, but no temperate layer
-		}
-		else state=4; // temperate layer with positive thickness
-	}
-
-	_assert_(state>=0);
-	return state;
-}/*}}}*/
-IssmDouble EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/
-
-	IssmDouble temperature, waterfraction;
-	IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K)
-	IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
-	element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure);
-
-	return (1.-waterfraction)*kappa_i + waterfraction*kappa_w;
-}/*}}}*/
-
-/*Intermediaries*/
-IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
+	/* Only drain waterfraction of ice column from element at base*/
+	if(!element->IsOnBase()) return; //FIXME: allow freeze on for floating elements
+
+	/* Intermediaries*/
+	int is, numvertices, numsegments;
+	int *pairindices   = NULL;
+
+	numvertices=element->GetNumberOfVertices();
+	element->VerticalSegmentIndices(&pairindices,&numsegments);
+
+	IssmDouble* watercolumn = xNew<IssmDouble>(numvertices);
+	IssmDouble* drainrate_column  = xNew<IssmDouble>(numsegments);
+	IssmDouble* drainrate_element = xNew<IssmDouble>(numsegments);
+
+	element->GetInputListOnVertices(watercolumn,WatercolumnEnum);
+
+	for(is=0;is<numsegments;is++)	drainrate_column[is]=0.;
+	Element* elementi = element;
+	for(;;){
+		for(is=0;is<numsegments;is++)	drainrate_element[is]=0.;
+		DrainWaterfraction(elementi,drainrate_element); // TODO: make sure every vertex is only drained once
+		for(is=0;is<numsegments;is++)	drainrate_column[is]+=drainrate_element[is];
+
+		if(elementi->IsOnSurface()) break;
+		elementi=elementi->GetUpperElement();			
+	}
+	/* add drained water to water column*/
+	for(is=0;is<numsegments;is++) watercolumn[is]+=drainrate_column[is];
+	/* Feed updated water column back into model */
+	element->AddInput(WatercolumnEnum,watercolumn,P1Enum);
+
+	xDelete<int>(pairindices);
+	xDelete<IssmDouble>(drainrate_column);
+	xDelete<IssmDouble>(drainrate_element);
+	xDelete<IssmDouble>(watercolumn);
+}/*}}}*/
+IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
 
 	IssmDouble heatcapacity             = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
@@ -1519,5 +1078,5 @@
 	}
 }/*}}}*/
-IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
+IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
 
 	int         iv;
@@ -1574,5 +1133,404 @@
 	return kappa;
 }/*}}}*/
-IssmDouble EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/
+void           EnthalpyAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_advec =[ h ]
+	 *                 [ h ]
+	 *                 [ h ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = basis[i];
+		B[numnodes*1+i] = basis[i];
+		B[numnodes*2+i] = basis[i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(basis);
+}/*}}}*/
+void           EnthalpyAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Biprime_advec=[ dh/dx ]
+	 *                     [ dh/dy ]
+	 *                     [ dh/dz ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = dbasis[0*numnodes+i];
+		B[numnodes*1+i] = dbasis[1*numnodes+i];
+		B[numnodes*2+i] = dbasis[2*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
+void           EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
+
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase()) || element->IsFloating()) return;
+
+	/*Intermediary*/
+	bool        isdynamicbasalspc;
+	IssmDouble	dt;
+
+	/*Check wether dynamic basal boundary conditions are activated */
+	element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
+	if(!isdynamicbasalspc) return;
+
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	if(dt==0.){
+		GetBasalConstraintsSteadystate(vec_spc,element);
+	}
+	else{
+		GetBasalConstraintsTransient(vec_spc,element);
+	}
+}/*}}}*/
+void           EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
+
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase()) || element->IsFloating()) return;
+
+	/*Intermediary*/
+	int         numindices, numindicesup, state;
+	int        *indices = NULL, *indicesup = NULL;
+	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
+
+	/*Get parameters and inputs: */
+	Input* enthalpy_input		 = element->GetInput(EnthalpyPicardEnum);					 _assert_(enthalpy_input);
+	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
+	Input* watercolumn_input	 = element->GetInput(WatercolumnEnum);							 _assert_(watercolumn_input);
+	Input* meltingrate_input	 = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);							 _assert_(meltingrate_input);
+
+	/*Fetch indices of basal & surface nodes for this finite element*/
+	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
+	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
+	penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());	_assert_(numindices==numindicesup);
+
+	GaussPenta* gauss=new GaussPenta();
+	GaussPenta* gaussup=new GaussPenta();
+	for(int i=0;i<numindices;i++){
+		gauss->GaussNode(element->GetElementType(),indices[i]);
+		gaussup->GaussNode(element->GetElementType(),indicesup[i]);
+
+		enthalpy_input->GetInputValue(&enthalpy,gauss);
+		enthalpy_input->GetInputValue(&enthalpyup,gaussup);
+		pressure_input->GetInputValue(&pressure,gauss);
+		pressure_input->GetInputValue(&pressureup,gaussup);
+		watercolumn_input->GetInputValue(&watercolumn,gauss);
+		meltingrate_input->GetInputValue(&meltingrate,gauss);
+
+		state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
+		switch (state) {
+			case 0:
+				// cold, dry base: apply basal surface forcing
+				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
+				break;
+			case 1:
+				// cold, wet base: keep at pressure melting point 
+				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
+				break;
+			case 2:
+				// temperate, thin refreezing base: release spc
+				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
+				break;
+			case 3:
+				// temperate, thin melting base: set spc
+				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
+				break;
+			case 4:
+				// temperate, thick melting base: s
+				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
+				break;
+			default:
+				_printf0_("	unknown thermal basal state found!");
+		}
+	}
+
+	/*Free ressources:*/
+	xDelete<int>(indices);
+	xDelete<int>(indicesup);
+	delete gauss;
+	delete gaussup;
+}/*}}}*/
+void           EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
+
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase()) || element->IsFloating()) return;
+
+	/*Intermediary*/
+	int         numindices, numindicesup, state;
+	int        *indices = NULL, *indicesup = NULL;
+	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
+
+	/*Get parameters and inputs: */
+	Input* enthalpy_input       = element->GetInput(EnthalpyEnum);                    _assert_(enthalpy_input); //TODO: check EnthalpyPicard?
+	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
+	Input* watercolumn_input	 = element->GetInput(WatercolumnEnum);							 _assert_(watercolumn_input);
+	Input* meltingrate_input	 = element->GetInput(BasalforcingsGroundediceMeltingRateEnum);							 _assert_(meltingrate_input);
+
+	/*Fetch indices of basal & surface nodes for this finite element*/
+	Penta *penta =  (Penta *) element; // TODO: add Basal-/SurfaceNodeIndices to element.h, and change this to Element*
+	penta->BasalNodeIndices(&numindices,&indices,element->GetElementType());
+	penta->SurfaceNodeIndices(&numindicesup,&indicesup,element->GetElementType());	_assert_(numindices==numindicesup);
+
+	GaussPenta* gauss=new GaussPenta();
+	GaussPenta* gaussup=new GaussPenta();
+
+	for(int i=0;i<numindices;i++){
+		gauss->GaussNode(element->GetElementType(),indices[i]);
+		gaussup->GaussNode(element->GetElementType(),indicesup[i]);
+		
+		enthalpy_input->GetInputValue(&enthalpy,gauss);
+		enthalpy_input->GetInputValue(&enthalpyup,gaussup);
+		pressure_input->GetInputValue(&pressure,gauss);
+		pressure_input->GetInputValue(&pressureup,gaussup);
+		watercolumn_input->GetInputValue(&watercolumn,gauss);
+		meltingrate_input->GetInputValue(&meltingrate,gauss);
+
+		state=GetThermalBasalCondition(element, enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate);
+
+		switch (state) {
+			case 0:
+				// cold, dry base: apply basal surface forcing
+				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
+				break;
+			case 1:
+				// cold, wet base: keep at pressure melting point 
+				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
+				break;
+			case 2:
+				// temperate, thin refreezing base: release spc
+				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
+				break;
+			case 3:
+				// temperate, thin melting base: set spc
+				vec_spc->SetValue(element->nodes[i]->Sid(),1.,INS_VAL);
+				break;
+			case 4:
+				// temperate, thick melting base: set grad H*n=0
+				vec_spc->SetValue(element->nodes[i]->Sid(),0.,INS_VAL);
+				break;
+			default:
+				_printf0_("	unknown thermal basal state found!");
+		}
+
+	}
+
+	/*Free ressources:*/
+	xDelete<int>(indices);
+	xDelete<int>(indicesup);
+	delete gauss;
+	delete gaussup;
+}/*}}}*/
+void           EnthalpyAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_conduct=[ dh/dx ]
+	 *                  [ dh/dy ]
+	 *                  [ dh/dz ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = dbasis[0*numnodes+i];
+		B[numnodes*1+i] = dbasis[1*numnodes+i];
+		B[numnodes*2+i] = dbasis[2*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
+void           EnthalpyAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+	element->GetSolutionFromInputsOneDof(solution,EnthalpyEnum);
+}/*}}}*/
+int            EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return -1;
+
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase())) return -1;
+
+	/*Intermediary*/
+	int state=-1;
+	IssmDouble	dt;
+
+	/*Get parameters and inputs: */
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+
+	if(enthalpy<PureIceEnthalpy(element,pressure)){
+		if(watercolumn<=0.) state=0; // cold, dry base
+		else state=1; // cold, wet base (refreezing)
+	}
+	else{
+		if(enthalpyup<PureIceEnthalpy(element,pressureup)){
+			if((dt==0.) && (meltingrate<0.)) state=2;	// refreezing temperate base (non-physical, only for steadystate solver)
+			else	state=3; // temperate base, but no temperate layer
+		}
+		else state=4; // temperate layer with positive thickness
+	}
+
+	_assert_(state>=0);
+	return state;
+}/*}}}*/
+IssmDouble     EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/
+
+	IssmDouble temperature, waterfraction;
+	IssmDouble kappa_w = 0.6; // thermal conductivity of water (in W/m/K)
+	IssmDouble kappa_i = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
+	element->EnthalpyToThermal(&temperature, &waterfraction, enthalpy, pressure);
+
+	return (1.-waterfraction)*kappa_i + waterfraction*kappa_w;
+}/*}}}*/
+void           EnthalpyAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+	_error_("Not implemented yet");
+}/*}}}*/
+void           EnthalpyAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+
+	bool        converged;
+	int         i,rheology_law;
+	IssmDouble  B_average,s_average,T_average=0.,P_average=0.;
+	int        *doflist   = NULL;
+	IssmDouble *xyz_list  = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes    = element->GetNumberOfNodes();
+
+	/*Fetch dof list and allocate solution vector*/
+	element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	IssmDouble* values        = xNew<IssmDouble>(numnodes);
+	IssmDouble* pressure      = xNew<IssmDouble>(numnodes);
+	IssmDouble* surface       = xNew<IssmDouble>(numnodes);
+	IssmDouble* B             = xNew<IssmDouble>(numnodes);
+	IssmDouble* temperature   = xNew<IssmDouble>(numnodes);
+	IssmDouble* waterfraction = xNew<IssmDouble>(numnodes);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numnodes;i++){
+		values[i]=solution[doflist[i]];
+
+		/*Check solution*/
+		if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get all inputs and parameters*/
+	element->GetInputValue(&converged,ConvergedEnum);
+	element->GetInputListOnNodes(&pressure[0],PressureEnum);
+	if(converged){
+		for(i=0;i<numnodes;i++){
+			element->EnthalpyToThermal(&temperature[i],&waterfraction[i],values[i],pressure[i]);
+			if(waterfraction[i]<0.) _error_("Negative water fraction found in solution vector");
+			//if(waterfraction[i]>1.) _error_("Water fraction >1 found in solution vector");
+		}
+		element->AddInput(EnthalpyEnum,values,element->GetElementType());
+		element->AddInput(WaterfractionEnum,waterfraction,element->GetElementType());
+		element->AddInput(TemperatureEnum,temperature,element->GetElementType());
+
+		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
+		 * otherwise the rheology could be negative*/
+		element->FindParam(&rheology_law,MaterialsRheologyLawEnum);
+		element->GetInputListOnNodes(&surface[0],SurfaceEnum);
+		switch(rheology_law){
+			case NoneEnum:
+				/*Do nothing: B is not temperature dependent*/
+				break;
+			case CuffeyEnum:
+				for(i=0;i<numnodes;i++) B[i]=Cuffey(temperature[i]);
+				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
+				break;
+			case PatersonEnum:
+				for(i=0;i<numnodes;i++) B[i]=Paterson(temperature[i]);
+				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
+				break;
+			case ArrheniusEnum:
+				element->GetVerticesCoordinates(&xyz_list);
+				for(i=0;i<numnodes;i++) B[i]=Arrhenius(temperature[i],surface[i]-xyz_list[i*3+2],element->GetMaterialParameter(MaterialsRheologyNEnum));
+				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType());
+				break;
+			case LliboutryDuvalEnum:
+				for(i=0;i<numnodes;i++) B[i]=LliboutryDuval(values[i],pressure[i],element->GetMaterialParameter(MaterialsRheologyNEnum),element->GetMaterialParameter(MaterialsBetaEnum),element->GetMaterialParameter(ConstantsReferencetemperatureEnum),element->GetMaterialParameter(MaterialsHeatcapacityEnum),element->GetMaterialParameter(MaterialsLatentheatEnum)); 
+				element->AddInput(MaterialsRheologyBEnum,&B[0],element->GetElementType()); 
+				break; 
+			default: _error_("Rheology law " << EnumToStringx(rheology_law) << " not supported yet");
+		}
+	}
+	else{
+		element->AddInput(EnthalpyPicardEnum,values,element->GetElementType());
+	}
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(values);
+	xDelete<IssmDouble>(pressure);
+	xDelete<IssmDouble>(surface);
+	xDelete<IssmDouble>(B);
+	xDelete<IssmDouble>(temperature);
+	xDelete<IssmDouble>(waterfraction);
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<int>(doflist);
+}/*}}}*/
+void           EnthalpyAnalysis::PostProcessing(FemModel* femmodel){/*{{{*/
+
+	/*Intermediaries*/
+	bool computebasalmeltingrates=true;
+	bool drainicecolumn=true;
+	bool isdynamicbasalspc;
+	IssmDouble dt;
+
+	femmodel->parameters->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
+	femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+
+	//TODO: use dt to decide what to do
+	if(drainicecolumn)	DrainWaterfraction(femmodel);
+	if(computebasalmeltingrates)	ComputeBasalMeltingrate(femmodel);
+	if(isdynamicbasalspc)	UpdateBasalConstraints(femmodel);
+
+}/*}}}*/
+IssmDouble     EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/
 
 	IssmDouble heatcapacity         = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
@@ -1581,5 +1539,5 @@
 	return heatcapacity*(TMeltingPoint(element,pressure)-referencetemperature);
 }/*}}}*/
-IssmDouble EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/
+IssmDouble     EnthalpyAnalysis::TMeltingPoint(Element* element,IssmDouble pressure){/*{{{*/
 
 	IssmDouble meltingpoint = element->GetMaterialParameter(MaterialsMeltingpointEnum);
@@ -1588,2 +1546,40 @@
 	return meltingpoint-beta*pressure;
 }/*}}}*/
+void           EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/
+
+	/*Update basal dirichlet BCs for enthalpy: */
+	Vector<IssmDouble>* spc           = NULL;
+	IssmDouble*         serial_spc    = NULL;
+
+	spc=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(EnthalpyAnalysisEnum));
+	/*First create a vector to figure out what elements should be constrained*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		GetBasalConstraints(spc,element);
+	}
+
+	/*Assemble and serialize*/
+	spc->Assemble();
+	serial_spc=spc->ToMPISerial();
+	delete spc;
+
+	/*Then update basal constraints nodes accordingly*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		ApplyBasalConstraints(serial_spc,element);
+	}
+
+	femmodel->UpdateConstraintsx();
+
+	/*Delete*/
+	xDelete<IssmDouble>(serial_spc);
+}/*}}}*/
+void           EnthalpyAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+
+	bool islevelset;
+	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
+	if(islevelset){
+		SetActiveNodesLSMx(femmodel);
+	}
+	return;
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/EnthalpyAnalysis.h	(revision 18930)
@@ -14,51 +14,46 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
-		void           Core(FemModel* femmodel);
-		ElementVector* CreateDVector(Element* element);
-		ElementMatrix* CreateJacobianMatrix(Element* element);
-		ElementMatrix* CreateKMatrix(Element* element);
-		ElementMatrix* CreateKMatrixVolume(Element* element);
-		ElementMatrix* CreateKMatrixShelf(Element* element);
-		ElementVector* CreatePVector(Element* element);
-		ElementVector* CreatePVectorVolume(Element* element);
-		ElementVector* CreatePVectorSheet(Element* element);
-		ElementVector* CreatePVectorShelf(Element* element);
-		void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-
-		/*Modules*/
-		static void PostProcessing(FemModel* femmodel);
-		static void ComputeBasalMeltingrate(FemModel* femmodel);
-		static void ComputeBasalMeltingrate(Element* element);
-		static void DrainWaterfraction(FemModel* femmodel);
-		static void DrainWaterfractionIcecolumn(Element* element);
-		static void DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element);
-		static void UpdateBasalConstraints(FemModel* femmodel);
-		static void ApplyBasalConstraints(IssmDouble* serial_spc,Element* element);
-		static void GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element);
-		static void GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element);
-		static void GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element);
-		static int GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate);
-		static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure);
-
-
-		/*Intermediaries*/
+		static void       ApplyBasalConstraints(IssmDouble* serial_spc,Element* element);
+		static void       ComputeBasalMeltingrate(FemModel* femmodel);
+		static void       ComputeBasalMeltingrate(Element* element);
+		void              Core(FemModel* femmodel);
+		ElementVector*    CreateDVector(Element* element);
+		ElementMatrix*    CreateJacobianMatrix(Element* element);
+		ElementMatrix*    CreateKMatrix(Element* element);
+		ElementMatrix*    CreateKMatrixVolume(Element* element);
+		ElementMatrix*    CreateKMatrixShelf(Element* element);
+		ElementVector*    CreatePVector(Element* element);
+		ElementVector*    CreatePVectorVolume(Element* element);
+		ElementVector*    CreatePVectorSheet(Element* element);
+		ElementVector*    CreatePVectorShelf(Element* element);
+		static void       DrainWaterfraction(FemModel* femmodel);
+		static void       DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element);
+		static void       DrainWaterfractionIcecolumn(Element* element);
 		static IssmDouble EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure);
 		static IssmDouble EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum);
+		void              GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void              GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		static void       GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element);
+		static void       GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element);
+		static void       GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element);
+		void              GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void              GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		static int        GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpy_up, IssmDouble pressure, IssmDouble pressure_up, IssmDouble watercolumn, IssmDouble meltingrate);
+		static IssmDouble GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure);
+		void              GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void              InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		static void       PostProcessing(FemModel* femmodel);
 		static IssmDouble PureIceEnthalpy(Element* element,IssmDouble pressure);
 		static IssmDouble TMeltingPoint(Element* element,IssmDouble pressure);
+		static void       UpdateBasalConstraints(FemModel* femmodel);
+		void              UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp	(revision 18930)
@@ -6,19 +6,33 @@
 
 /*Model processing*/
+void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*retrieve some parameters: */
+	int          hydrology_model;
+	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
+
+	if(hydrology_model!=HydrologyshreveEnum) return;
+
+	IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum);
+
+}/*}}}*/
+void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	/*No loads*/
+}/*}}}*/
+void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	/*Fetch parameters: */
+	int  hydrology_model;
+	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
+
+	/*Now, do we really want Shreve?*/
+	if(hydrology_model!=HydrologyshreveEnum) return;
+
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  HydrologyShreveAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	/*retrieve some parameters: */
-	int  hydrology_model;
-	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
-
-	/*Now, do we really want Shreve?*/
-	if(hydrology_model!=HydrologyshreveEnum) return;
-
-	parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
-	parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));
-
 }/*}}}*/
 void HydrologyShreveAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -55,7 +69,7 @@
 	elements->InputDuplicate(WatercolumnEnum,WaterColumnOldEnum);
 }/*}}}*/
-void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	/*Fetch parameters: */
+void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	/*retrieve some parameters: */
 	int  hydrology_model;
 	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
@@ -64,21 +78,7 @@
 	if(hydrology_model!=HydrologyshreveEnum) return;
 
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,HydrologyShreveAnalysisEnum,P1Enum);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*retrieve some parameters: */
-	int          hydrology_model;
-	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
-
-	if(hydrology_model!=HydrologyshreveEnum) return;
-
-	IoModelToConstraintsx(constraints,iomodel,HydrologyshreveSpcwatercolumnEnum,HydrologyShreveAnalysisEnum,P1Enum);
-
-}/*}}}*/
-void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	/*No loads*/
+	parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
+	parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));
+
 }/*}}}*/
 
@@ -90,4 +90,48 @@
 	/*Default, return NULL*/
 	return NULL;
+}/*}}}*/
+void           HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble dsdx,dsdy,dbdx,dbdy,w;
+
+	/*Retrieve all inputs and parameters*/
+	IssmDouble  rho_ice   = element->GetMaterialParameter(MaterialsRhoIceEnum);
+	IssmDouble  rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
+	IssmDouble  g         = element->GetMaterialParameter(ConstantsGEnum);
+	IssmDouble  mu_water  = element->GetMaterialParameter(MaterialsMuWaterEnum);
+	Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
+	Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
+	Input* bedslopex_input     = element->GetInput(BedSlopeXEnum);     _assert_(bedslopex_input);
+	Input* bedslopey_input     = element->GetInput(BedSlopeYEnum);     _assert_(bedslopey_input);
+	Input* watercolumn_input   = element->GetInput(WatercolumnEnum);   _assert_(watercolumn_input);
+
+	/*Fetch number of vertices and allocate output*/
+	int numvertices = element->GetNumberOfVertices();
+	IssmDouble* vx  = xNew<IssmDouble>(numvertices);
+	IssmDouble* vy  = xNew<IssmDouble>(numvertices);
+
+	Gauss* gauss=element->NewGauss();
+	for(int iv=0;iv<numvertices;iv++){
+		gauss->GaussVertex(iv);
+		surfaceslopex_input->GetInputValue(&dsdx,gauss);
+		surfaceslopey_input->GetInputValue(&dsdy,gauss);
+		bedslopex_input->GetInputValue(&dbdx,gauss);
+		bedslopey_input->GetInputValue(&dbdy,gauss);
+		watercolumn_input->GetInputValue(&w,gauss);
+
+		/* Water velocity x and y components */
+		vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
+		vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
+	}
+
+	/*clean-up*/
+	delete gauss;
+
+	/*Add to inputs*/
+	element->AddInput(HydrologyWaterVxEnum,vx,P1Enum);
+	element->AddInput(HydrologyWaterVyEnum,vy,P1Enum);
+	xDelete<IssmDouble>(vx);
+	xDelete<IssmDouble>(vy);
 }/*}}}*/
 ElementMatrix* HydrologyShreveAnalysis::CreateJacobianMatrix(Element* element){/*{{{*/
@@ -234,5 +278,5 @@
 	return pe;
 }/*}}}*/
-void HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           HydrologyShreveAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
 	 * For node i, Bi can be expressed in the actual coordinate system
@@ -261,5 +305,5 @@
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           HydrologyShreveAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
 	 * For node i, Bi' can be expressed in the actual coordinate system
@@ -289,11 +333,11 @@
 
 }/*}}}*/
-void HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           HydrologyShreveAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	element->GetSolutionFromInputsOneDof(solution,WatercolumnEnum);
 }/*}}}*/
-void HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           HydrologyShreveAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           HydrologyShreveAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	/*Intermediary*/
@@ -321,55 +365,8 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           HydrologyShreveAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
-
-/*Intermediaries*/
-void HydrologyShreveAnalysis::CreateHydrologyWaterVelocityInput(Element* element){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble dsdx,dsdy,dbdx,dbdy,w;
-
-	/*Retrieve all inputs and parameters*/
-	IssmDouble  rho_ice   = element->GetMaterialParameter(MaterialsRhoIceEnum);
-	IssmDouble  rho_water = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
-	IssmDouble  g         = element->GetMaterialParameter(ConstantsGEnum);
-	IssmDouble  mu_water  = element->GetMaterialParameter(MaterialsMuWaterEnum);
-	Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
-	Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
-	Input* bedslopex_input     = element->GetInput(BedSlopeXEnum);     _assert_(bedslopex_input);
-	Input* bedslopey_input     = element->GetInput(BedSlopeYEnum);     _assert_(bedslopey_input);
-	Input* watercolumn_input   = element->GetInput(WatercolumnEnum);   _assert_(watercolumn_input);
-
-	/*Fetch number of vertices and allocate output*/
-	int numvertices = element->GetNumberOfVertices();
-	IssmDouble* vx  = xNew<IssmDouble>(numvertices);
-	IssmDouble* vy  = xNew<IssmDouble>(numvertices);
-
-	Gauss* gauss=element->NewGauss();
-	for(int iv=0;iv<numvertices;iv++){
-		gauss->GaussVertex(iv);
-		surfaceslopex_input->GetInputValue(&dsdx,gauss);
-		surfaceslopey_input->GetInputValue(&dsdy,gauss);
-		bedslopex_input->GetInputValue(&dbdx,gauss);
-		bedslopey_input->GetInputValue(&dbdy,gauss);
-		watercolumn_input->GetInputValue(&w,gauss);
-
-		/* Water velocity x and y components */
-		vx[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
-		vy[iv]= - w*w/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
-	}
-
-	/*clean-up*/
-	delete gauss;
-
-	/*Add to inputs*/
-	element->AddInput(HydrologyWaterVxEnum,vx,P1Enum);
-	element->AddInput(HydrologyWaterVyEnum,vy,P1Enum);
-	xDelete<IssmDouble>(vx);
-	xDelete<IssmDouble>(vy);
-}/*}}}*/
-
 
 
Index: /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h	(revision 18930)
@@ -13,26 +13,24 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
 		ElementVector* CreateDVector(Element* element);
+		void           CreateHydrologyWaterVelocityInput(Element* element);
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-
-		/*Intermediaries*/
-		void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void CreateHydrologyWaterVelocityInput(Element* element);
+		void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp	(revision 18930)
@@ -6,8 +6,25 @@
 
 /*Model processing*/
+void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*No constraints*/
+}/*}}}*/
+void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*No loads*/
+}/*}}}*/
+void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	if(iomodel->domaintype==Domain3DEnum){
+		iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	}
+	else if(iomodel->domaintype==Domain2DverticalEnum){
+		iomodel->FetchData(1,MeshVertexonbaseEnum);
+	}
+	::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  L2ProjectionBaseAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void L2ProjectionBaseAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -31,22 +48,5 @@
 	}
 }/*}}}*/
-void L2ProjectionBaseAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	if(iomodel->domaintype==Domain3DEnum){
-		iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	}
-	else if(iomodel->domaintype==Domain2DverticalEnum){
-		iomodel->FetchData(1,MeshVertexonbaseEnum);
-	}
-	::CreateNodes(nodes,iomodel,L2ProjectionBaseAnalysisEnum,P1Enum);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*No constraints*/
-}/*}}}*/
-void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads*/
+void L2ProjectionBaseAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -196,11 +196,11 @@
 	return pe;
 }/*}}}*/
-void L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           L2ProjectionBaseAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           L2ProjectionBaseAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           L2ProjectionBaseAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int inputenum,domaintype,elementtype;
@@ -225,5 +225,5 @@
 	}
 }/*}}}*/
-void L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp	(revision 18930)
@@ -6,8 +6,34 @@
 
 /*Model processing*/
+void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*No constraints*/
+}/*}}}*/
+void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*No loads*/
+}/*}}}*/
+void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	/*Now, do we really want DC?*/
+	int  hydrology_model;
+	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
+	if(hydrology_model!=HydrologydcEnum) return;
+
+	/*Do we want an efficient layer*/
+	bool isefficientlayer;
+	iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum);
+	if(!isefficientlayer) return;
+
+	if(iomodel->domaintype==Domain3DEnum){
+		iomodel->FetchData(1,MeshVertexonbaseEnum);
+	}
+	else if(iomodel->domaintype==Domain2DverticalEnum){
+		iomodel->FetchData(1,MeshVertexonbaseEnum);
+	}
+	::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum);
+	iomodel->DeleteData(1,MeshVertexonbaseEnum);
+}/*}}}*/
 int  L2ProjectionEPLAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void L2ProjectionEPLAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -41,31 +67,5 @@
 	}
 }/*}}}*/
-void L2ProjectionEPLAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	/*Now, do we really want DC?*/
-	int  hydrology_model;
-	iomodel->Constant(&hydrology_model,HydrologyModelEnum);
-	if(hydrology_model!=HydrologydcEnum) return;
-
-	/*Do we want an efficient layer*/
-	bool isefficientlayer;
-	iomodel->Constant(&isefficientlayer,HydrologydcIsefficientlayerEnum);
-	if(!isefficientlayer) return;
-
-	if(iomodel->domaintype==Domain3DEnum){
-		iomodel->FetchData(1,MeshVertexonbaseEnum);
-	}
-	else if(iomodel->domaintype==Domain2DverticalEnum){
-		iomodel->FetchData(1,MeshVertexonbaseEnum);
-	}
-	::CreateNodes(nodes,iomodel,L2ProjectionEPLAnalysisEnum,P1Enum);
-	iomodel->DeleteData(1,MeshVertexonbaseEnum);
-}/*}}}*/
-void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*No constraints*/
-}/*}}}*/
-void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads*/
+void L2ProjectionEPLAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -226,11 +226,11 @@
 	return pe;
 }/*}}}*/
-void L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           L2ProjectionEPLAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           L2ProjectionEPLAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           L2ProjectionEPLAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	int inputenum,domaintype;
 
@@ -250,5 +250,5 @@
 	}
 }/*}}}*/
-void L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp	(revision 18930)
@@ -11,10 +11,20 @@
 #include "../solutionsequences/solutionsequences.h"
 
-int LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
+void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	return;
 }
 /*}}}*/
-void LevelsetAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	return;
+}/*}}}*/
+void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	int finiteelement=P1Enum;
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}
+/*}}}*/
+int  LevelsetAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	return 1;
 }
 /*}}}*/
@@ -60,21 +70,11 @@
 }
 /*}}}*/
-void LevelsetAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	int finiteelement=P1Enum;
-	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,LevelsetAnalysisEnum,finiteelement);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}
-/*}}}*/
-void LevelsetAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+void LevelsetAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	return;
 }
 /*}}}*/
-void LevelsetAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	return;
-}/*}}}*/
 
 /*Finite element Analysis*/
-void LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/
+void           LevelsetAnalysis::Core(FemModel* femmodel){/*{{{*/
 
 	#if !defined(_DEVELOPMENT_)
@@ -404,11 +404,90 @@
 	return pe;
 }/*}}}*/
-void LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For node i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ N ]
+	 *          [ N ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = basis[i];
+		B[numnodes*1+i] = basis[i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(basis);
+}/*}}}*/
+void           LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_prime=[ dN/dx ]
+	 *                [ dN/dy ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B': */
+	for(int i=0;i<numnodes;i++){
+		Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
+		Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+
+}/*}}}*/
+IssmDouble     LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
+	// returns distance d of point q to straight going through points s0, s1
+	// d=|a x b|/|b|
+	// with a=q-s0, b=s1-s0
+	
+	/* Intermediaries */
+	const int dim=2;
+	int i;
+	IssmDouble a[dim], b[dim];
+	IssmDouble norm_b;
+
+	for(i=0;i<dim;i++){
+		a[i]=q[i]-s0[i];
+		b[i]=s1[i]-s0[i];
+	}
+	
+	norm_b=0.;
+	for(i=0;i<dim;i++)
+		norm_b+=b[i]*b[i];
+	norm_b=sqrt(norm_b);
+	_assert_(norm_b>0.);
+
+	return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
+}/*}}}*/
+void           LevelsetAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           LevelsetAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -424,64 +503,5 @@
 	}
 }/*}}}*/
-void LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	/*Default, do nothing*/
-	return;
-}/*}}}*/
-void LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
-	 * For node i, Bi can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi=[ N ]
-	 *          [ N ]
-	 * where N is the finiteelement function for node i.
-	 *
-	 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions*/
-	IssmDouble* basis=xNew<IssmDouble>(numnodes);
-	element->NodalFunctions(basis,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = basis[i];
-		B[numnodes*1+i] = basis[i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(basis);
-}/*}}}*/
-void LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi_prime=[ dN/dx ]
-	 *                [ dN/dy ]
-	 * where N is the finiteelement function for node i.
-	 *
-	 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B': */
-	for(int i=0;i<numnodes;i++){
-		Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
-		Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-
-}/*}}}*/
-void LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
+void           LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
 
 	/* Intermediaries */
@@ -539,5 +559,5 @@
 	delete dist_zerolevelset;
 }/*}}}*/
-void LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
+void           LevelsetAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
 
 	if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
@@ -592,26 +612,6 @@
 	xDelete<IssmDouble>(xyz_list_zero);
 }/*}}}*/
-IssmDouble LevelsetAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
-	// returns distance d of point q to straight going through points s0, s1
-	// d=|a x b|/|b|
-	// with a=q-s0, b=s1-s0
-	
-	/* Intermediaries */
-	const int dim=2;
-	int i;
-	IssmDouble a[dim], b[dim];
-	IssmDouble norm_b;
-
-	for(i=0;i<dim;i++){
-		a[i]=q[i]-s0[i];
-		b[i]=s1[i]-s0[i];
-	}
-	
-	norm_b=0.;
-	for(i=0;i<dim;i++)
-		norm_b+=b[i]*b[i];
-	norm_b=sqrt(norm_b);
-	_assert_(norm_b>0.);
-
-	return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
-}/*}}}*/
+void           LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+	/*Default, do nothing*/
+	return;
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/LevelsetAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,13 +26,13 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-		void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void SetDistanceOnIntersectedElements(FemModel* femmodel);
-		void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element);
-		IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
+		void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		IssmDouble     GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           SetDistanceOnIntersectedElements(FemModel* femmodel);
+		void           SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp	(revision 18930)
@@ -10,9 +10,18 @@
 
 /*Model processing*/
+void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	/* Do nothing for now */
+}/*}}}*/
+void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	/* Do nothing for now */
+}/*}}}*/
+void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+	int finiteelement=P1Enum;
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  LsfReinitializationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	/* Do nothing for now */
 }/*}}}*/
 void LsfReinitializationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -34,19 +43,10 @@
 	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
 }/*}}}*/
-void LsfReinitializationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-	int finiteelement=P1Enum;
-	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,LsfReinitializationAnalysisEnum,finiteelement);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void LsfReinitializationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+void LsfReinitializationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	/* Do nothing for now */
 }/*}}}*/
-void LsfReinitializationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	/* Do nothing for now */
-}/*}}}*/
 
 /*Finite element Analysis*/
-void  LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/
+void           LsfReinitializationAnalysis::Core(FemModel* femmodel){/*{{{*/
 
 	/*parameters: */
@@ -249,5 +249,84 @@
 	return pe;
 	}/*}}}*/
-void LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For node i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ N ]
+	 *          [ N ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = basis[i];
+		B[numnodes*1+i] = basis[i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(basis);
+}/*}}}*/
+void           LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_prime=[ dN/dx ]
+	 *                [ dN/dy ]
+	 * where N is the finiteelement function for node i.
+	 *
+	 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
+	 */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B': */
+	for(int i=0;i<numnodes;i++){
+		Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
+		Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+
+}/*}}}*/
+IssmDouble     LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
+	// returns distance d of point q to straight going through points s0, s1
+	// d=|a x b|/|b|
+	// with a=q-s0, b=s1-s0
+	
+	/* Intermediaries */
+	const int dim=2;
+	int i;
+	IssmDouble a[dim], b[dim];
+	IssmDouble norm_b;
+
+	for(i=0;i<dim;i++){
+		a[i]=q[i]-s0[i];
+		b[i]=s1[i]-s0[i];
+	}
+	
+	norm_b=0.;
+	for(i=0;i<dim;i++)
+		norm_b+=b[i]*b[i];
+	norm_b=sqrt(norm_b);
+	_assert_(norm_b>0.);
+
+	return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
+}/*}}}*/
+void           LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 
 	IssmDouble   lsf;
@@ -284,8 +363,8 @@
 
 }/*}}}*/
-void LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           LsfReinitializationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           LsfReinitializationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
@@ -301,65 +380,142 @@
 	}
 }/*}}}*/
-void LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	/* Do nothing for now */
-}/*}}}*/
-void LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
-	 * For node i, Bi can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi=[ N ]
-	 *          [ N ]
-	 * where N is the finiteelement function for node i.
-	 *
-	 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions*/
-	IssmDouble* basis=xNew<IssmDouble>(numnodes);
-	element->NodalFunctions(basis,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = basis[i];
-		B[numnodes*1+i] = basis[i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(basis);
-}/*}}}*/
-void LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi_prime=[ dN/dx ]
-	 *                [ dN/dy ]
-	 * where N is the finiteelement function for node i.
-	 *
-	 * We assume B' has been allocated already, of size: 3x(NDOF2*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B': */
-	for(int i=0;i<numnodes;i++){
-		Bprime[numnodes*0+i] = dbasis[0*numnodes+i];
-		Bprime[numnodes*1+i] = dbasis[1*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-
-}/*}}}*/
-
-/* Other */
-void LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
+bool           LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/
+
+	/*Output*/
+	bool converged = true;
+
+	/*Intermediary*/
+	Vector<IssmDouble>* dlsfg    = NULL;
+	IssmDouble          norm_dlsf,norm_lsf;
+
+	/*compute norm(du)/norm(u)*/
+	dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0);
+	norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO);
+	if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!");
+	if((norm_dlsf/norm_lsf)<reltol){
+		if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n");
+	}
+	else{ 
+		if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n");
+		converged=false;
+	}
+
+	/*Cleanup*/
+	delete dlsfg;
+
+	return converged;
+}/*}}}*/
+void           LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
+
+	/* Intermediaries */
+	int i;
+	IssmDouble dmaxp,dmaxm,val;
+	Element* element;
+
+	/*Initialize vector with number of vertices*/
+	int numvertices=femmodel->vertices->NumberOfVertices();
+
+	Vector<IssmDouble>* vec_dist_zerolevelset = NULL;
+	GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum);
+	
+	/* set distance on elements intersected by zero levelset */
+	for(i=0;i<femmodel->elements->Size();i++){
+		element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		if(element->IsZeroLevelset(MaskIceLevelsetEnum)){
+			SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element);
+		}
+	}
+	vec_dist_zerolevelset->Assemble();
+
+	/* Get maximum distance to interface along vertices */
+	dmaxp=0.; dmaxm=0.;
+	for(i=0;i<numvertices;i++){
+		vec_dist_zerolevelset->GetValue(&val,i); 
+		if((val>0.) && (val>dmaxp))
+			 dmaxp=val;
+		else if((val<0.) && (val<dmaxm))
+			 dmaxm=val;
+	}
+	//wait until all values are computed
+
+	/* set all none intersected vertices to max/min distance */
+	for(i=0;i<numvertices;i++){
+		vec_dist_zerolevelset->GetValue(&val,i);
+		if(val==1.) //FIXME: improve check
+			vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL);
+		else if(val==-1.)
+			vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL);
+	}
+
+	/*Assemble vector and serialize */
+	vec_dist_zerolevelset->Assemble();
+	IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial();
+	InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum);
+
+	/*Clean up and return*/
+	delete vec_dist_zerolevelset;
+	delete dist_zerolevelset;
+
+}/*}}}*/
+void           LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
+
+	if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
+		return;
+
+	/* Intermediaries */
+	int dim=3;
+	int i,d;
+	IssmDouble dist,lsf_old;
+
+	int numvertices=element->GetNumberOfVertices();
+
+	IssmDouble* lsf = xNew<IssmDouble>(numvertices);
+	IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices);
+	IssmDouble* signed_dist = xNew<IssmDouble>(numvertices);
+	IssmDouble* s0 = xNew<IssmDouble>(dim);
+	IssmDouble* s1 = xNew<IssmDouble>(dim);
+	IssmDouble* v = xNew<IssmDouble>(dim);
+	IssmDouble* xyz_list = NULL;
+	IssmDouble* xyz_list_zero = NULL;
+
+	/* retrieve inputs and parameters */
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum);
+
+	/* get sign of levelset function */
+	for(i=0;i<numvertices;i++)
+		sign_lsf[i]=(lsf[i]>=0.?1.:-1.);
+
+	element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum);
+	for(i=0;i<dim;i++){
+		s0[i]=xyz_list_zero[0+i];
+		s1[i]=xyz_list_zero[3+i];
+	}
+
+	/* get signed_distance of vertices to zero levelset straight */
+	for(i=0;i<numvertices;i++){
+		for(d=0;d<dim;d++)
+			v[d]=xyz_list[dim*i+d];
+		dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]);
+		signed_dist[i]=sign_lsf[i]*dist;
+	}
+	
+	/* insert signed_distance into vec_signed_dist, if computed distance is smaller */
+	for(i=0;i<numvertices;i++){
+		vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid());
+		/* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/
+		if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old))
+			vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL);
+	}
+
+	xDelete<IssmDouble>(lsf);
+	xDelete<IssmDouble>(sign_lsf);
+	xDelete<IssmDouble>(signed_dist);
+	xDelete<IssmDouble>(s0);
+	xDelete<IssmDouble>(s1);
+	xDelete<IssmDouble>(v);
+
+}/*}}}*/
+void           LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
 
 	int i,k, numnodes;
@@ -399,163 +555,5 @@
 
 }/*}}}*/
-void LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
-
-	/* Intermediaries */
-	int i;
-	IssmDouble dmaxp,dmaxm,val;
-	Element* element;
-
-	/*Initialize vector with number of vertices*/
-	int numvertices=femmodel->vertices->NumberOfVertices();
-
-	Vector<IssmDouble>* vec_dist_zerolevelset = NULL;
-	GetVectorFromInputsx(&vec_dist_zerolevelset, femmodel, MaskIceLevelsetEnum, VertexEnum);
-	
-	/* set distance on elements intersected by zero levelset */
-	for(i=0;i<femmodel->elements->Size();i++){
-		element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		if(element->IsZeroLevelset(MaskIceLevelsetEnum)){
-			SetDistanceToZeroLevelsetElement(vec_dist_zerolevelset, element);
-		}
-	}
-	vec_dist_zerolevelset->Assemble();
-
-	/* Get maximum distance to interface along vertices */
-	dmaxp=0.; dmaxm=0.;
-	for(i=0;i<numvertices;i++){
-		vec_dist_zerolevelset->GetValue(&val,i); 
-		if((val>0.) && (val>dmaxp))
-			 dmaxp=val;
-		else if((val<0.) && (val<dmaxm))
-			 dmaxm=val;
-	}
-	//wait until all values are computed
-
-	/* set all none intersected vertices to max/min distance */
-	for(i=0;i<numvertices;i++){
-		vec_dist_zerolevelset->GetValue(&val,i);
-		if(val==1.) //FIXME: improve check
-			vec_dist_zerolevelset->SetValue(i,3.*dmaxp,INS_VAL);
-		else if(val==-1.)
-			vec_dist_zerolevelset->SetValue(i,3.*dmaxm,INS_VAL);
-	}
-
-	/*Assemble vector and serialize */
-	vec_dist_zerolevelset->Assemble();
-	IssmDouble* dist_zerolevelset=vec_dist_zerolevelset->ToMPISerial();
-	InputUpdateFromVectorx(femmodel,dist_zerolevelset,MaskIceLevelsetEnum,VertexSIdEnum);
-
-	/*Clean up and return*/
-	delete vec_dist_zerolevelset;
-	delete dist_zerolevelset;
-
-}/*}}}*/
-void LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
-
-	if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
-		return;
-
-	/* Intermediaries */
-	int dim=3;
-	int i,d;
-	IssmDouble dist,lsf_old;
-
-	int numvertices=element->GetNumberOfVertices();
-
-	IssmDouble* lsf = xNew<IssmDouble>(numvertices);
-	IssmDouble* sign_lsf = xNew<IssmDouble>(numvertices);
-	IssmDouble* signed_dist = xNew<IssmDouble>(numvertices);
-	IssmDouble* s0 = xNew<IssmDouble>(dim);
-	IssmDouble* s1 = xNew<IssmDouble>(dim);
-	IssmDouble* v = xNew<IssmDouble>(dim);
-	IssmDouble* xyz_list = NULL;
-	IssmDouble* xyz_list_zero = NULL;
-
-	/* retrieve inputs and parameters */
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GetInputListOnVertices(lsf,MaskIceLevelsetEnum);
-
-	/* get sign of levelset function */
-	for(i=0;i<numvertices;i++)
-		sign_lsf[i]=(lsf[i]>=0.?1.:-1.);
-
-	element->ZeroLevelsetCoordinates(&xyz_list_zero, xyz_list, MaskIceLevelsetEnum);
-	for(i=0;i<dim;i++){
-		s0[i]=xyz_list_zero[0+i];
-		s1[i]=xyz_list_zero[3+i];
-	}
-
-	/* get signed_distance of vertices to zero levelset straight */
-	for(i=0;i<numvertices;i++){
-		for(d=0;d<dim;d++)
-			v[d]=xyz_list[dim*i+d];
-		dist=GetDistanceToStraight(&v[0],&s0[0],&s1[0]);
-		signed_dist[i]=sign_lsf[i]*dist;
-	}
-	
-	/* insert signed_distance into vec_signed_dist, if computed distance is smaller */
-	for(i=0;i<numvertices;i++){
-		vec_signed_dist->GetValue(&lsf_old, element->vertices[i]->Sid());
-		/* initial lsf values are +-1. Update those fields or if distance to interface smaller.*/
-		if(fabs(lsf_old)==1. || fabs(signed_dist[i])<fabs(lsf_old))
-			vec_signed_dist->SetValue(element->vertices[i]->Sid(),signed_dist[i],INS_VAL);
-	}
-
-	xDelete<IssmDouble>(lsf);
-	xDelete<IssmDouble>(sign_lsf);
-	xDelete<IssmDouble>(signed_dist);
-	xDelete<IssmDouble>(s0);
-	xDelete<IssmDouble>(s1);
-	xDelete<IssmDouble>(v);
-
-}/*}}}*/
-IssmDouble LsfReinitializationAnalysis::GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1){/*{{{*/
-	// returns distance d of point q to straight going through points s0, s1
-	// d=|a x b|/|b|
-	// with a=q-s0, b=s1-s0
-	
-	/* Intermediaries */
-	const int dim=2;
-	int i;
-	IssmDouble a[dim], b[dim];
-	IssmDouble norm_b;
-
-	for(i=0;i<dim;i++){
-		a[i]=q[i]-s0[i];
-		b[i]=s1[i]-s0[i];
-	}
-	
-	norm_b=0.;
-	for(i=0;i<dim;i++)
-		norm_b+=b[i]*b[i];
-	norm_b=sqrt(norm_b);
-	_assert_(norm_b>0.);
-
-	return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
-}/*}}}*/
-bool LsfReinitializationAnalysis::ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol){/*{{{*/
-
-	/*Output*/
-	bool converged = true;
-
-	/*Intermediary*/
-	Vector<IssmDouble>* dlsfg    = NULL;
-	IssmDouble          norm_dlsf,norm_lsf;
-
-	/*compute norm(du)/norm(u)*/
-	dlsfg=lsfg_old->Duplicate(); lsfg_old->Copy(dlsfg); dlsfg->AYPX(lsfg,-1.0);
-	norm_dlsf=dlsfg->Norm(NORM_TWO); norm_lsf=lsfg_old->Norm(NORM_TWO);
-	if (xIsNan<IssmDouble>(norm_dlsf) || xIsNan<IssmDouble>(norm_lsf)) _error_("convergence criterion is NaN!");
-	if((norm_dlsf/norm_lsf)<reltol){
-		if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" < "<<reltol*100<<" %\n");
-	}
-	else{ 
-		if(VerboseConvergence()) _printf0_("\n"<<setw(50)<<left<<"   Velocity convergence: norm(du)/norm(u)"<<norm_dlsf/norm_lsf*100<<" > "<<reltol*100<<" %\n");
-		converged=false;
-	}
-
-	/*Cleanup*/
-	delete dlsfg;
-
-	return converged;
-}/*}}}*/
+void           LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+	/* Do nothing for now */
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 public:
 	/*Model processing*/
-	int  DofsPerNode(int** doflist,int domaintype,int approximation);
-	void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-	void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-	void CreateNodes(Nodes* nodes,IoModel* iomodel);
 	void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 	void CreateLoads(Loads* loads, IoModel* iomodel);
+	void CreateNodes(Nodes* nodes,IoModel* iomodel);
+	int  DofsPerNode(int** doflist,int domaintype,int approximation);
+	void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+	void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 	/*Finite element Analysis*/
@@ -26,17 +26,15 @@
 	ElementMatrix* CreateKMatrix(Element* element);
 	ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-	void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-	void UpdateConstraints(FemModel* femmodel);
-	void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-	void GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-	
-	/* Other */
-	void SetReinitSPCs(FemModel* femmodel);
-	void SetDistanceOnIntersectedElements(FemModel* femmodel);
-	void SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element);
-	IssmDouble GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
-	bool ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol);
+	void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+	void           GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+	IssmDouble     GetDistanceToStraight(IssmDouble* q, IssmDouble* s0, IssmDouble* s1);
+	void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+	void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+	void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+	bool           ReinitConvergence(Vector<IssmDouble>* lsfg,Vector<IssmDouble>* lsfg_old,IssmDouble reltol);
+	void           SetDistanceOnIntersectedElements(FemModel* femmodel);
+	void           SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_dist, Element* element);
+	void           SetReinitSPCs(FemModel* femmodel);
+	void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp	(revision 18930)
@@ -6,24 +6,113 @@
 
 /*Model processing*/
+void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*Fetch parameters: */
+	int stabilization;
+	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
+
+	/*Do not add constraints in DG,  they are weakly imposed*/
+	if(stabilization!=3){
+		IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum);
+	}
+
+	/*FCT, constraints are imposed using penalties*/
+	if(stabilization==4){
+		constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum);
+	}
+}/*}}}*/
+void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*Intermediaries*/
+	int element;
+	int penpair_ids[2];
+	int count=0;
+	int stabilization;
+	int numvertex_pairing;
+
+	/*Fetch parameters: */
+	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
+
+	/*Loads only in DG*/
+	if (stabilization==3){
+
+		/*Get faces and elements*/
+		CreateFaces(iomodel);
+		iomodel->FetchData(1,ThicknessEnum);
+
+		/*First load data:*/
+		for(int i=0;i<iomodel->numberoffaces;i++){
+
+			/*Get left and right elements*/
+			element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
+
+			/*Now, if this element is not in the partition, pass: */
+			if(!iomodel->my_elements[element]) continue;
+
+			/* Add load */
+			loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum));
+		}
+
+		/*Free data: */
+		iomodel->DeleteData(1,ThicknessEnum);
+	}
+
+	/*Create Penpair for vertex_pairing: */
+	IssmDouble *vertex_pairing=NULL;
+	IssmDouble *nodeonbase=NULL;
+	iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum);
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum);
+
+	for(int i=0;i<numvertex_pairing;i++){
+
+		if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){
+
+			/*In debugging mode, check that the second node is in the same cpu*/
+			_assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]);
+
+			/*Skip if one of the two is not on the bed*/
+			if(iomodel->domaintype!=Domain2DhorizontalEnum){
+				if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue;
+			}
+
+			/*Get node ids*/
+			penpair_ids[0]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]);
+			penpair_ids[1]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]);
+
+			/*Create Load*/
+			loads->AddObject(new Penpair(
+							iomodel->loadcounter+count+1,
+							&penpair_ids[0],
+							MasstransportAnalysisEnum));
+			count++;
+		}
+	}
+
+	/*free ressources: */
+	iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum);
+	iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum);
+
+}/*}}}*/
+void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	/*Fetch parameters: */
+	int  stabilization;
+	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
+
+	/*Check in 3d*/
+	if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
+
+	/*Create Nodes either DG or CG depending on stabilization*/
+	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	if(stabilization!=3){
+		::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum);
+	}
+	else{
+		::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum);
+	}
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  MasstransportAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
-
-	parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum));
-
-	iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum);
-	parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs));
-	if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs));
-	iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum);
-
 }/*}}}*/
 void MasstransportAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -126,109 +215,20 @@
 
 }/*}}}*/
-void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	/*Fetch parameters: */
-	int  stabilization;
-	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
-
-	/*Check in 3d*/
-	if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
-
-	/*Create Nodes either DG or CG depending on stabilization*/
-	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	if(stabilization!=3){
-		::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1Enum);
-	}
-	else{
-		::CreateNodes(nodes,iomodel,MasstransportAnalysisEnum,P1DGEnum);
-	}
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void MasstransportAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*Fetch parameters: */
-	int stabilization;
-	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
-
-	/*Do not add constraints in DG,  they are weakly imposed*/
-	if(stabilization!=3){
-		IoModelToConstraintsx(constraints,iomodel,MasstransportSpcthicknessEnum,MasstransportAnalysisEnum,P1Enum);
-	}
-
-	/*FCT, constraints are imposed using penalties*/
-	if(stabilization==4){
-		constraints->ActivatePenaltyMethod(MasstransportAnalysisEnum);
-	}
-}/*}}}*/
-void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*Intermediaries*/
-	int element;
-	int penpair_ids[2];
-	int count=0;
-	int stabilization;
-	int numvertex_pairing;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
-
-	/*Loads only in DG*/
-	if (stabilization==3){
-
-		/*Get faces and elements*/
-		CreateFaces(iomodel);
-		iomodel->FetchData(1,ThicknessEnum);
-
-		/*First load data:*/
-		for(int i=0;i<iomodel->numberoffaces;i++){
-
-			/*Get left and right elements*/
-			element=iomodel->faces[4*i+2]-1; //faces are [node1 node2 elem1 elem2]
-
-			/*Now, if this element is not in the partition, pass: */
-			if(!iomodel->my_elements[element]) continue;
-
-			/* Add load */
-			loads->AddObject(new Numericalflux(iomodel->loadcounter+i+1,i,i,iomodel,MasstransportAnalysisEnum));
-		}
-
-		/*Free data: */
-		iomodel->DeleteData(1,ThicknessEnum);
-	}
-
-	/*Create Penpair for vertex_pairing: */
-	IssmDouble *vertex_pairing=NULL;
-	IssmDouble *nodeonbase=NULL;
-	iomodel->FetchData(&vertex_pairing,&numvertex_pairing,NULL,MasstransportVertexPairingEnum);
-	if(iomodel->domaintype!=Domain2DhorizontalEnum) iomodel->FetchData(&nodeonbase,NULL,NULL,MeshVertexonbaseEnum);
-
-	for(int i=0;i<numvertex_pairing;i++){
-
-		if(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+0])-1]){
-
-			/*In debugging mode, check that the second node is in the same cpu*/
-			_assert_(iomodel->my_vertices[reCast<int>(vertex_pairing[2*i+1])-1]);
-
-			/*Skip if one of the two is not on the bed*/
-			if(iomodel->domaintype!=Domain2DhorizontalEnum){
-				if(!(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+0])-1])) || !(reCast<bool>(nodeonbase[reCast<int>(vertex_pairing[2*i+1])-1]))) continue;
-			}
-
-			/*Get node ids*/
-			penpair_ids[0]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+0]);
-			penpair_ids[1]=iomodel->nodecounter+reCast<int>(vertex_pairing[2*i+1]);
-
-			/*Create Load*/
-			loads->AddObject(new Penpair(
-							iomodel->loadcounter+count+1,
-							&penpair_ids[0],
-							MasstransportAnalysisEnum));
-			count++;
-		}
-	}
-
-	/*free ressources: */
-	iomodel->DeleteData(vertex_pairing,MasstransportVertexPairingEnum);
-	iomodel->DeleteData(nodeonbase,MeshVertexonbaseEnum);
+void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
+
+	parameters->AddObject(iomodel->CopyConstantObject(FlowequationIsFSEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(MasstransportIsfreesurfaceEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(MasstransportHydrostaticAdjustmentEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(MasstransportStabilizationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(MasstransportMinThicknessEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(MasstransportPenaltyFactorEnum));
+
+	iomodel->FetchData(&requestedoutputs,&numoutputs,MasstransportRequestedOutputsEnum);
+	parameters->AddObject(new IntParam(MasstransportNumRequestedOutputsEnum,numoutputs));
+	if(numoutputs)parameters->AddObject(new StringArrayParam(MasstransportRequestedOutputsEnum,requestedoutputs,numoutputs));
+	iomodel->DeleteData(&requestedoutputs,numoutputs,MasstransportRequestedOutputsEnum);
 
 }/*}}}*/
@@ -625,5 +625,5 @@
 	return pe;
 }/*}}}*/
-void MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           MasstransportAnalysis::GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
 	 * For node i, Bi can be expressed in the actual coordinate system
@@ -653,5 +653,5 @@
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           MasstransportAnalysis::GetBprime(IssmDouble* Bprime,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
 	 * For node i, Bi' can be expressed in the actual coordinate system
@@ -682,11 +682,11 @@
 
 }/*}}}*/
-void MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           MasstransportAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	element->GetSolutionFromInputsOneDof(solution,ThicknessEnum);
 }/*}}}*/
-void MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           MasstransportAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int        i,hydroadjustment,domaintype;
@@ -772,5 +772,5 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
@@ -783,4 +783,126 @@
 
 /*Flux Correction Transport*/
+ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Intermediaries */
+	IssmDouble Jdet;
+	IssmDouble vx,vy;
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+	int dim      = 2;
+
+	/*Initialize Element vector and other vectors*/
+	ElementMatrix* Ke     = element->NewElementMatrix();
+	IssmDouble*    B      = xNew<IssmDouble>(dim*numnodes);
+	IssmDouble*    Bprime = xNew<IssmDouble>(dim*numnodes);
+	IssmDouble*    D      = xNewZeroInit<IssmDouble>(dim*dim);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input);
+	Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		GetB(B,element,dim,xyz_list,gauss);
+		GetBprime(Bprime,element,dim,xyz_list,gauss);
+		vxaverage_input->GetInputValue(&vx,gauss);
+		vyaverage_input->GetInputValue(&vy,gauss);
+
+		D[0*dim+0] = -gauss->weight*vx*Jdet;
+		D[1*dim+1] = -gauss->weight*vy*Jdet;
+
+		TripleMultiply(B,dim,numnodes,1,
+					D,dim,dim,0,
+					Bprime,dim,numnodes,0,
+					&Ke->values[0],1);
+
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(B);
+	xDelete<IssmDouble>(Bprime);
+	xDelete<IssmDouble>(D);
+	delete gauss;
+	return Ke;
+}/*}}}*/
+ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Intermediaries*/
+	IssmDouble  D,Jdet;
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Element vector and other vectors*/
+	ElementMatrix* Me     = element->NewElementMatrix();
+	IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctions(basis,gauss);
+
+		D=gauss->weight*Jdet;
+		TripleMultiply(basis,1,numnodes,1,
+					&D,1,1,0,
+					basis,1,numnodes,0,
+					&Me->values[0],1);
+	}
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	delete gauss;
+	return Me;
+}/*}}}*/
+void           MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/
+
+	/*Output*/
+	Matrix<IssmDouble>* Kff = NULL;
+	Matrix<IssmDouble>* Kfs = NULL;
+
+	/*Initialize Jacobian Matrix*/
+	AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel);
+
+	/*Create and assemble matrix*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		ElementMatrix* Ke     = this->CreateFctKMatrix(element);
+		if(Ke) Ke->AddToGlobal(Kff,Kfs);
+		delete Ke;
+	}
+	Kff->Assemble();
+	Kfs->Assemble();
+
+	/*Assign output pointer*/
+	*pKff=Kff;
+	if(pKfs){
+		*pKfs=Kfs;
+	}
+	else{
+		delete Kfs;
+	}
+}/*}}}*/
 void           MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/
 
@@ -829,124 +951,2 @@
 	*pMff=Mff;
 }/*}}}*/
-ElementMatrix* MasstransportAnalysis::CreateMassMatrix(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	/*Intermediaries*/
-	IssmDouble  D,Jdet;
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element vector and other vectors*/
-	ElementMatrix* Me     = element->NewElementMatrix();
-	IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctions(basis,gauss);
-
-		D=gauss->weight*Jdet;
-		TripleMultiply(basis,1,numnodes,1,
-					&D,1,1,0,
-					basis,1,numnodes,0,
-					&Me->values[0],1);
-	}
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	delete gauss;
-	return Me;
-}/*}}}*/
-void           MasstransportAnalysis::FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel){/*{{{*/
-
-	/*Output*/
-	Matrix<IssmDouble>* Kff = NULL;
-	Matrix<IssmDouble>* Kfs = NULL;
-
-	/*Initialize Jacobian Matrix*/
-	AllocateSystemMatricesx(&Kff,&Kfs,NULL,NULL,femmodel);
-
-	/*Create and assemble matrix*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ElementMatrix* Ke     = this->CreateFctKMatrix(element);
-		if(Ke) Ke->AddToGlobal(Kff,Kfs);
-		delete Ke;
-	}
-	Kff->Assemble();
-	Kfs->Assemble();
-
-	/*Assign output pointer*/
-	*pKff=Kff;
-	if(pKfs){
-		*pKfs=Kfs;
-	}
-	else{
-		delete Kfs;
-	}
-}/*}}}*/
-ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	/*Intermediaries */
-	IssmDouble Jdet;
-	IssmDouble vx,vy;
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-	int dim      = 2;
-
-	/*Initialize Element vector and other vectors*/
-	ElementMatrix* Ke     = element->NewElementMatrix();
-	IssmDouble*    B      = xNew<IssmDouble>(dim*numnodes);
-	IssmDouble*    Bprime = xNew<IssmDouble>(dim*numnodes);
-	IssmDouble*    D      = xNewZeroInit<IssmDouble>(dim*dim);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* vxaverage_input=element->GetInput(VxEnum); _assert_(vxaverage_input);
-	Input* vyaverage_input=element->GetInput(VyEnum); _assert_(vyaverage_input);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		GetB(B,element,dim,xyz_list,gauss);
-		GetBprime(Bprime,element,dim,xyz_list,gauss);
-		vxaverage_input->GetInputValue(&vx,gauss);
-		vyaverage_input->GetInputValue(&vy,gauss);
-
-		D[0*dim+0] = -gauss->weight*vx*Jdet;
-		D[1*dim+1] = -gauss->weight*vy*Jdet;
-
-		TripleMultiply(B,dim,numnodes,1,
-					D,dim,dim,0,
-					Bprime,dim,numnodes,0,
-					&Ke->values[0],1);
-
-	}
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(B);
-	xDelete<IssmDouble>(Bprime);
-	xDelete<IssmDouble>(D);
-	delete gauss;
-	return Ke;
-}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MasstransportAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -30,17 +30,17 @@
 		ElementVector* CreatePVectorCG(Element* element);
 		ElementVector* CreatePVectorDG(Element* element);
-		void GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetB(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* B,Element* element,int dim,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 
 		/*FCT*/
+		ElementMatrix* CreateFctKMatrix(Element* element);
+		ElementMatrix* CreateMassMatrix(Element* element);
+		void           FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel);
 		void           LumpedMassMatrix(Vector<IssmDouble>** pMLff,FemModel* femmodel);
 		void           MassMatrix(Matrix<IssmDouble>** pMff,FemModel* femmodel);
-		void           FctKMatrix(Matrix<IssmDouble>** pKff,Matrix<IssmDouble>** pKfs,FemModel* femmodel);
-		ElementMatrix* CreateMassMatrix(Element* element);
-		ElementMatrix* CreateFctKMatrix(Element* element);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.cpp	(revision 18930)
@@ -6,8 +6,34 @@
 
 /*Model processing*/
+void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	/*No Constraints*/
+}/*}}}*/
+void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*if 2d: Error*/
+	if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
+
+	//create penalties for nodes: no node can have a temperature over the melting point
+	iomodel->FetchData(1,MeshVertexonbaseEnum);
+	CreateSingleNodeToElementConnectivity(iomodel);
+
+	for(int i=0;i<iomodel->numberofvertices;i++){
+		if(iomodel->my_vertices[i]){
+			if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){
+				loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum));
+			}
+		}
+	}
+	iomodel->DeleteData(1,MeshVertexonbaseEnum);
+
+}/*}}}*/
+void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  MeltingAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void MeltingAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -39,31 +65,5 @@
 	iomodel->FetchDataToInput(elements,PressureEnum);
 }/*}}}*/
-void MeltingAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,MeltingAnalysisEnum,P1Enum);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void MeltingAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	/*No Constraints*/
-}/*}}}*/
-void MeltingAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*if 2d: Error*/
-	if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
-
-	//create penalties for nodes: no node can have a temperature over the melting point
-	iomodel->FetchData(1,MeshVertexonbaseEnum);
-	CreateSingleNodeToElementConnectivity(iomodel);
-
-	for(int i=0;i<iomodel->numberofvertices;i++){
-		if(iomodel->my_vertices[i]){
-			if (reCast<int>(iomodel->Data(MeshVertexonbaseEnum)[i])){
-				loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,MeltingAnalysisEnum));
-			}
-		}
-	}
-	iomodel->DeleteData(1,MeshVertexonbaseEnum);
-
+void MeltingAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -126,14 +126,14 @@
 	return NULL;
 }/*}}}*/
-void MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           MeltingAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           MeltingAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           MeltingAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	element->InputUpdateFromSolutionOneDof(solution,BasalforcingsGroundediceMeltingRateEnum);
 }/*}}}*/
-void MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           MeltingAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MeltingAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp	(revision 18930)
@@ -6,11 +6,8 @@
 
 /*Model processing*/
-int  MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	_error_("not implemented");
-}/*}}}*/
-void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+void MeshdeformationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
@@ -18,8 +15,11 @@
 	   _error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+int  MeshdeformationAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	_error_("not implemented");
+}/*}}}*/
+void MeshdeformationAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void MeshdeformationAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
@@ -42,14 +42,14 @@
 _error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           MeshdeformationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           MeshdeformationAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           MeshdeformationAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           MeshdeformationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp	(revision 18930)
@@ -6,11 +6,20 @@
 
 /*Model processing*/
+void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	const int finiteelement = P1Enum;
+	IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0);
+	IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1);
+}/*}}}*/
+void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	return;
+}/*}}}*/
+void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum);
+
+}/*}}}*/
 int  SeaiceAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 2;
-}/*}}}*/
-void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum));
 }/*}}}*/
 void SeaiceAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -49,17 +58,8 @@
 	iomodel->FetchDataToInput(elements,MeshYEnum);
 }/*}}}*/
-void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum);
-
-}/*}}}*/
-void SeaiceAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	const int finiteelement = P1Enum;
-	IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvxEnum,SeaiceAnalysisEnum,finiteelement,0);
-	IoModelToConstraintsx(constraints,iomodel,SeaiceSpcvyEnum,SeaiceAnalysisEnum,finiteelement,1);
-}/*}}}*/
-void SeaiceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	return;
+void SeaiceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinConcentrationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMinThicknessEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(SeaiceMaxThicknessEnum));
 }/*}}}*/
 
@@ -312,11 +312,107 @@
 	return pe;
 }/*}}}*/
-void SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble D[3][3];
+	IssmDouble damage,concentration;
+
+	/*Get Material parameters*/
+	IssmDouble poisson          = element->GetMaterialParameter(MaterialsPoissonEnum);
+	IssmDouble young_modulus    = element->GetMaterialParameter(MaterialsYoungModulusEnum);
+	IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum);
+
+	/*Get damage input at this location*/
+	Input* damage_input        = element->GetInput(DamageEnum);              _assert_(damage_input);
+	Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
+	damage_input->GetInputValue(&damage,gauss);
+	concentration_input->GetInputValue(&concentration,gauss);
+
+	/*Build D tensor once for all*/
+	D[0][0] = 1.;      D[0][1] = poisson; D[0][2] = 0.;
+	D[1][0] = poisson; D[1][1] = 1.;      D[1][2] = 0.;
+	D[2][0] = 0.;      D[2][1] = 0;       D[2][2] = (1.-poisson)/2.;
+	for(int i=0;i<3;i++){
+		for(int j=0;j<3;j++){
+			D[i][j] = D[i][j]/(1-poisson*poisson);
+		}
+	}
+
+	/*Get f(A), E*/
+	IssmDouble f = exp(ridging_exponent*(1.-concentration));
+	IssmDouble E = young_modulus*(1.-damage)*f;
+
+	/*Let's build C = E*D */
+	for(int i=0;i<3;i++){
+		for(int j=0;j<3;j++){
+			C[i*3+j] = E*D[i][j];
+		}
+	}
+}/*}}}*/
+void           SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For node i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ dN/dx           0    ] 
+	 *          [   0           dN/dy  ]      
+	 *          [ 1/2*dN/dy  1/2*dN/dx ]     
+	 * where N is the basis function for node i.
+	 *
+	 * We assume B has been allocated already           */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
+		B[2*numnodes*0+2*i+1] = 0.;
+		B[2*numnodes*1+2*i+0] = 0.;
+		B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
+		//B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i];
+		//B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i];
+		B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i];
+		B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
+void           SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute M  matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2. 
+	 * For node i, Mi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Mi=[ N  N ] 
+	 * where N is the basis function for node i.
+	 *
+	 * We assume M has been allocated already           */
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Get nodal functions derivatives*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
+
+	/*Build M: */
+	for(int i=0;i<numnodes;i++){
+		M[2*i+0] = basis[i];
+		M[2*i+1] = basis[i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(basis);
+}/*}}}*/
+void           SeaiceAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           SeaiceAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	/*Intermediaries*/
@@ -360,5 +456,153 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
+
+	/*Intermediaties*/
+	IssmDouble *xyz_list = NULL;
+	IssmDouble *xyz_list_old = NULL;
+	IssmDouble *xyz_list_new = NULL;
+	IssmDouble  dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new;
+	IssmDouble  time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness;
+	IssmDouble  sigma_dot_xx,sigma_dot_yy,sigma_dot_xy;
+	IssmDouble  sigma_pred_xx,sigma_pred_yy,sigma_pred_xy;
+	IssmDouble  sigma_xx,sigma_yy,sigma_xy;
+	IssmDouble  min_c,min_h,max_h;
+	IssmDouble  epsilon[3]; /*eps_xx,eps_yy,eps_xy*/
+	IssmDouble  C[3][3];
+
+	/*Fetch the parameters once for all*/
+	femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum);
+	femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum);
+	femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum);
+
+	/*Loop over the elements of this partition and update accordingly*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+
+		/*Get some inputs needed for the update*/
+		element->GetVerticesCoordinates(&xyz_list);
+		time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum);
+		time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum);
+		Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input);
+		Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input);
+		Input* vx_input    = element->GetInput(VxEnum);    _assert_(vx_input);
+		Input* vy_input    = element->GetInput(VyEnum);    _assert_(vy_input);
+
+		/*Preallocate future inputs*/
+		int numvertices=element->GetNumberOfVertices();
+		IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices);
+		IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices);
+		xyz_list_old = xNew<IssmDouble>(numvertices*3);
+		xyz_list_new = xNew<IssmDouble>(numvertices*3);
+
+		/*1. update vertex positions (using a Gauss object for convenience)*/
+		Gauss* gauss=element->NewGauss();
+		for (int iv=0;iv<numvertices;iv++){
+			gauss->GaussVertex(iv);
+
+			meshx_input->GetInputValue(&meshx,gauss);
+			meshy_input->GetInputValue(&meshy,gauss);
+			vx_input->GetInputValue(&vx,gauss);
+			vy_input->GetInputValue(&vy,gauss);
+
+			meshx_new_list[iv] = meshx + vx*dt;
+			meshy_new_list[iv] = meshy + vy*dt;
+
+			xyz_list_old[iv*3+0] = meshx;
+			xyz_list_old[iv*3+1] = meshy;
+			xyz_list_old[iv*3+2] = 0.;
+
+			xyz_list_new[iv*3+0] = meshx_new_list[iv];
+			xyz_list_new[iv*3+1] = meshy_new_list[iv];
+			xyz_list_new[iv*3+2] = 0.;
+		}
+		element->AddInput(MeshXEnum,meshx_new_list,P1Enum);
+		element->AddInput(MeshYEnum,meshy_new_list,P1Enum);
+
+		/*Now we are going to use a point in the center of the element, because we are P0 for the stress*/
+		gauss->GaussNode(P0Enum,0);
+
+		/*Calculate sigma_dot*/
+		sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.;
+		this->CreateCTensor(&C[0][0],element,gauss);
+		element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
+		for(int j=0;j<3;j++){
+			sigma_dot_xx += C[0][j]*epsilon[0];
+			sigma_dot_yy += C[1][j]*epsilon[1];
+			sigma_dot_xy += C[2][j]*epsilon[2];
+		}
+
+		/*Get predicted stress state*/
+		Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input);
+		Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input);
+		Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input);
+		sigma_xx_input->GetInputAverage(&sigma_xx);
+		sigma_yy_input->GetInputAverage(&sigma_yy);
+		sigma_xy_input->GetInputAverage(&sigma_xy);
+
+		/*Calculate new stress and push to element*/
+		sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress);
+		sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress);
+		sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress);
+		element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
+		element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
+		element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
+
+		/*Update Damage According*/
+		Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input);
+		damage_input->GetInputAverage(&damage);
+		damage = damage*(1.-dt/time_relaxation_damage);
+		element->AddInput(DamageEnum,&damage,P0Enum);
+
+		/*Prepare new predictor*/
+		this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/
+		for(int j=0;j<3;j++){
+			sigma_pred_xx += C[0][j]*epsilon[0];
+			sigma_pred_yy += C[1][j]*epsilon[1];
+			sigma_pred_xy += C[2][j]*epsilon[2];
+		}
+		element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum);
+		element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum);
+		element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum);
+
+		/*Calculate Old and new area (FIXME: for now we assume trianlges...)*/
+		element->JacobianDeterminant(&area_old,xyz_list_old,gauss);
+		element->JacobianDeterminant(&area_new,xyz_list_new,gauss);
+		area_old = area_old/SQRT3;
+		area_new = area_new/SQRT3;
+
+		/*Update ice thickness and concentration using element distortion*/
+		Input* thickness_input     = element->GetInput(SeaiceThicknessEnum);     _assert_(thickness_input);
+		Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
+		thickness_input->GetInputAverage(&thickness);
+		concentration_input->GetInputAverage(&concentration);
+		IssmDouble ice_area   = concentration*area_old;
+		IssmDouble ice_volume = thickness*area_old;
+		if(concentration>min_c){
+			concentration = ice_area  /area_new;
+			thickness     = ice_volume/area_new;
+
+			/* lower bounds */
+			concentration = ((concentration>min_c)?(concentration):(min_c));
+			thickness     = ((thickness    >min_h)?(thickness    ):(min_h));
+
+			/* upper bounds (only for the concentration) */
+			concentration    = ((concentration<1.   )?(concentration):(1));
+			thickness        = ((thickness    <max_h)?(thickness    ):(max_h));
+		}
+		element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum);
+		element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum);
+
+		/*Clean up*/
+		xDelete<IssmDouble>(meshx_new_list);
+		xDelete<IssmDouble>(meshy_new_list);
+		xDelete<IssmDouble>(xyz_list);
+		xDelete<IssmDouble>(xyz_list_old);
+		xDelete<IssmDouble>(xyz_list_new);
+	}
+
+}/*}}}*/
+void           SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	/*Intermediaries*/
@@ -409,103 +653,5 @@
 	if(VerboseSolution()) _printf0_("   Number of active nodes: "<< sum_counter <<"\n");
 }/*}}}*/
-
-/*Intermediary functions*/
-void SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble D[3][3];
-	IssmDouble damage,concentration;
-
-	/*Get Material parameters*/
-	IssmDouble poisson          = element->GetMaterialParameter(MaterialsPoissonEnum);
-	IssmDouble young_modulus    = element->GetMaterialParameter(MaterialsYoungModulusEnum);
-	IssmDouble ridging_exponent = element->GetMaterialParameter(MaterialsRidgingExponentEnum);
-
-	/*Get damage input at this location*/
-	Input* damage_input        = element->GetInput(DamageEnum);              _assert_(damage_input);
-	Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
-	damage_input->GetInputValue(&damage,gauss);
-	concentration_input->GetInputValue(&concentration,gauss);
-
-	/*Build D tensor once for all*/
-	D[0][0] = 1.;      D[0][1] = poisson; D[0][2] = 0.;
-	D[1][0] = poisson; D[1][1] = 1.;      D[1][2] = 0.;
-	D[2][0] = 0.;      D[2][1] = 0;       D[2][2] = (1.-poisson)/2.;
-	for(int i=0;i<3;i++){
-		for(int j=0;j<3;j++){
-			D[i][j] = D[i][j]/(1-poisson*poisson);
-		}
-	}
-
-	/*Get f(A), E*/
-	IssmDouble f = exp(ridging_exponent*(1.-concentration));
-	IssmDouble E = young_modulus*(1.-damage)*f;
-
-	/*Let's build C = E*D */
-	for(int i=0;i<3;i++){
-		for(int j=0;j<3;j++){
-			C[i*3+j] = E*D[i][j];
-		}
-	}
-}/*}}}*/
-void SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
-	 * For node i, Bi can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi=[ dN/dx           0    ] 
-	 *          [   0           dN/dy  ]      
-	 *          [ 1/2*dN/dy  1/2*dN/dx ]     
-	 * where N is the basis function for node i.
-	 *
-	 * We assume B has been allocated already           */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(2*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[2*numnodes*0+2*i+0] = dbasis[0*numnodes+i];
-		B[2*numnodes*0+2*i+1] = 0.;
-		B[2*numnodes*1+2*i+0] = 0.;
-		B[2*numnodes*1+2*i+1] = dbasis[1*numnodes+i];
-		//B[2*numnodes*2+2*i+0] = .5*dbasis[1*numnodes+i];
-		//B[2*numnodes*2+2*i+1] = .5*dbasis[0*numnodes+i];
-		B[2*numnodes*2+2*i+0] = dbasis[1*numnodes+i];
-		B[2*numnodes*2+2*i+1] = dbasis[0*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-}/*}}}*/
-void SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute M  matrix. M=[M1 M2 M3] where Mi is of size 3*NDOF2. 
-	 * For node i, Mi can be expressed in the actual coordinate system
-	 * by: 
-	 *       Mi=[ N  N ] 
-	 * where N is the basis function for node i.
-	 *
-	 * We assume M has been allocated already           */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* basis=xNew<IssmDouble>(numnodes);
-	element->NodalFunctions(basis,gauss);
-
-	/*Build M: */
-	for(int i=0;i<numnodes;i++){
-		M[2*i+0] = basis[i];
-		M[2*i+1] = basis[i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(basis);
-}/*}}}*/
-void SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/
+void           SeaiceAnalysis::UpdateDamageAndStress(FemModel* femmodel){/*{{{*/
 	/* The damage variable is updated as a function of the actual elastic deformation
 	 * In both cases, a Coulombic enveloppe is used, define by the cohesion C, tan(phi) and tract_coef.
@@ -622,150 +768,2 @@
 	}
 }/*}}}*/
-void SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
-
-	/*Intermediaties*/
-	IssmDouble *xyz_list = NULL;
-	IssmDouble *xyz_list_old = NULL;
-	IssmDouble *xyz_list_new = NULL;
-	IssmDouble  dt,meshx,meshy,vx,vy,eps_xx,eps_yy,eps_zz,area_old,area_new;
-	IssmDouble  time_relaxation_stress,time_relaxation_damage,damage,concentration,thickness;
-	IssmDouble  sigma_dot_xx,sigma_dot_yy,sigma_dot_xy;
-	IssmDouble  sigma_pred_xx,sigma_pred_yy,sigma_pred_xy;
-	IssmDouble  sigma_xx,sigma_yy,sigma_xy;
-	IssmDouble  min_c,min_h,max_h;
-	IssmDouble  epsilon[3]; /*eps_xx,eps_yy,eps_xy*/
-	IssmDouble  C[3][3];
-
-	/*Fetch the parameters once for all*/
-	femmodel->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	femmodel->parameters->FindParam(&min_c,SeaiceMinConcentrationEnum);
-	femmodel->parameters->FindParam(&min_h,SeaiceMinThicknessEnum);
-	femmodel->parameters->FindParam(&max_h,SeaiceMaxThicknessEnum);
-
-	/*Loop over the elements of this partition and update accordingly*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-
-		/*Get some inputs needed for the update*/
-		element->GetVerticesCoordinates(&xyz_list);
-		time_relaxation_stress = element->GetMaterialParameter(MaterialsTimeRelaxationStressEnum);
-		time_relaxation_damage = element->GetMaterialParameter(MaterialsTimeRelaxationDamageEnum);
-		Input* meshx_input = element->GetInput(MeshXEnum); _assert_(meshx_input);
-		Input* meshy_input = element->GetInput(MeshYEnum); _assert_(meshy_input);
-		Input* vx_input    = element->GetInput(VxEnum);    _assert_(vx_input);
-		Input* vy_input    = element->GetInput(VyEnum);    _assert_(vy_input);
-
-		/*Preallocate future inputs*/
-		int numvertices=element->GetNumberOfVertices();
-		IssmDouble* meshx_new_list = xNew<IssmDouble>(numvertices);
-		IssmDouble* meshy_new_list = xNew<IssmDouble>(numvertices);
-		xyz_list_old = xNew<IssmDouble>(numvertices*3);
-		xyz_list_new = xNew<IssmDouble>(numvertices*3);
-
-		/*1. update vertex positions (using a Gauss object for convenience)*/
-		Gauss* gauss=element->NewGauss();
-		for (int iv=0;iv<numvertices;iv++){
-			gauss->GaussVertex(iv);
-
-			meshx_input->GetInputValue(&meshx,gauss);
-			meshy_input->GetInputValue(&meshy,gauss);
-			vx_input->GetInputValue(&vx,gauss);
-			vy_input->GetInputValue(&vy,gauss);
-
-			meshx_new_list[iv] = meshx + vx*dt;
-			meshy_new_list[iv] = meshy + vy*dt;
-
-			xyz_list_old[iv*3+0] = meshx;
-			xyz_list_old[iv*3+1] = meshy;
-			xyz_list_old[iv*3+2] = 0.;
-
-			xyz_list_new[iv*3+0] = meshx_new_list[iv];
-			xyz_list_new[iv*3+1] = meshy_new_list[iv];
-			xyz_list_new[iv*3+2] = 0.;
-		}
-		element->AddInput(MeshXEnum,meshx_new_list,P1Enum);
-		element->AddInput(MeshYEnum,meshy_new_list,P1Enum);
-
-		/*Now we are going to use a point in the center of the element, because we are P0 for the stress*/
-		gauss->GaussNode(P0Enum,0);
-
-		/*Calculate sigma_dot*/
-		sigma_dot_xx=sigma_dot_yy=sigma_dot_xy=0.;
-		this->CreateCTensor(&C[0][0],element,gauss);
-		element->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
-		for(int j=0;j<3;j++){
-			sigma_dot_xx += C[0][j]*epsilon[0];
-			sigma_dot_yy += C[1][j]*epsilon[1];
-			sigma_dot_xy += C[2][j]*epsilon[2];
-		}
-
-		/*Get predicted stress state*/
-		Input* sigma_xx_input = element->GetInput(StressTensorPredictorxxEnum); _assert_(sigma_xx_input);
-		Input* sigma_yy_input = element->GetInput(StressTensorPredictoryyEnum); _assert_(sigma_yy_input);
-		Input* sigma_xy_input = element->GetInput(StressTensorPredictorxyEnum); _assert_(sigma_xy_input);
-		sigma_xx_input->GetInputAverage(&sigma_xx);
-		sigma_yy_input->GetInputAverage(&sigma_yy);
-		sigma_xy_input->GetInputAverage(&sigma_xy);
-
-		/*Calculate new stress and push to element*/
-		sigma_xx = sigma_xx + dt*(sigma_dot_xx - sigma_xx/time_relaxation_stress);
-		sigma_yy = sigma_yy + dt*(sigma_dot_yy - sigma_yy/time_relaxation_stress);
-		sigma_xy = sigma_xy + dt*(sigma_dot_xy - sigma_xy/time_relaxation_stress);
-		element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
-		element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
-		element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
-
-		/*Update Damage According*/
-		Input* damage_input = element->GetInput(DamageEnum); _assert_(damage_input);
-		damage_input->GetInputAverage(&damage);
-		damage = damage*(1.-dt/time_relaxation_damage);
-		element->AddInput(DamageEnum,&damage,P0Enum);
-
-		/*Prepare new predictor*/
-		this->CreateCTensor(&C[0][0],element,gauss); /*C is updated now that there is a new damage in inputs*/
-		for(int j=0;j<3;j++){
-			sigma_pred_xx += C[0][j]*epsilon[0];
-			sigma_pred_yy += C[1][j]*epsilon[1];
-			sigma_pred_xy += C[2][j]*epsilon[2];
-		}
-		element->AddInput(StressTensorPredictorxxEnum,&sigma_pred_xx,P0Enum);
-		element->AddInput(StressTensorPredictoryyEnum,&sigma_pred_yy,P0Enum);
-		element->AddInput(StressTensorPredictorxyEnum,&sigma_pred_xy,P0Enum);
-
-		/*Calculate Old and new area (FIXME: for now we assume trianlges...)*/
-		element->JacobianDeterminant(&area_old,xyz_list_old,gauss);
-		element->JacobianDeterminant(&area_new,xyz_list_new,gauss);
-		area_old = area_old/SQRT3;
-		area_new = area_new/SQRT3;
-
-		/*Update ice thickness and concentration using element distortion*/
-		Input* thickness_input     = element->GetInput(SeaiceThicknessEnum);     _assert_(thickness_input);
-		Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
-		thickness_input->GetInputAverage(&thickness);
-		concentration_input->GetInputAverage(&concentration);
-		IssmDouble ice_area   = concentration*area_old;
-		IssmDouble ice_volume = thickness*area_old;
-		if(concentration>min_c){
-			concentration = ice_area  /area_new;
-			thickness     = ice_volume/area_new;
-
-			/* lower bounds */
-			concentration = ((concentration>min_c)?(concentration):(min_c));
-			thickness     = ((thickness    >min_h)?(thickness    ):(min_h));
-
-			/* upper bounds (only for the concentration) */
-			concentration    = ((concentration<1.   )?(concentration):(1));
-			thickness        = ((thickness    <max_h)?(thickness    ):(max_h));
-		}
-		element->AddInput(SeaiceConcentrationEnum,&concentration,P0Enum);
-		element->AddInput(SeaiceThicknessEnum,&thickness,P0Enum);
-
-		/*Clean up*/
-		xDelete<IssmDouble>(meshx_new_list);
-		xDelete<IssmDouble>(meshy_new_list);
-		xDelete<IssmDouble>(xyz_list);
-		xDelete<IssmDouble>(xyz_list_old);
-		xDelete<IssmDouble>(xyz_list_new);
-	}
-
-}/*}}}*/
Index: /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/SeaiceAnalysis.h	(revision 18930)
@@ -13,28 +13,26 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
+		void           CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss);
 		ElementVector* CreateDVector(Element* element);
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
-
-		/*Sea ice specifics*/
-		void UpdateDamageAndStress(FemModel* femmodel);
-		void CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss);
-		void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void PostProcess(FemModel* femmodel);
+		void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           PostProcess(FemModel* femmodel);
+		void           UpdateConstraints(FemModel* femmodel);
+		void           UpdateDamageAndStress(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.cpp	(revision 18930)
@@ -6,8 +6,15 @@
 
 /*Model processing*/
+void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+}/*}}}*/
+void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+}/*}}}*/
+void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum);
+
+}/*}}}*/
 int  SmoothAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 void SmoothAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -23,12 +30,5 @@
 	}
 }/*}}}*/
-void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum);
-
-}/*}}}*/
-void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-}/*}}}*/
-void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
 
@@ -205,11 +205,11 @@
 	return pe;
 }/*}}}*/
-void SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           SmoothAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           SmoothAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           SmoothAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 	int inputenum,domaintype,elementtype;
 
@@ -223,5 +223,5 @@
 	}
 }/*}}}*/
-void SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/SmoothAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,8 +26,8 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp	(revision 18930)
@@ -7,86 +7,4 @@
 
 /*Model processing*/
-int  StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 2;
-}/*}}}*/
-void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	/*No specific parameters*/
-
-}/*}}}*/
-void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-
-	/*Fetch data needed: */
-	bool   isSIA;
-	bool   islevelset;
-	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
-	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
-
-	/*Now, is the flag SIA on? otherwise, do nothing: */
-	if (!isSIA)return;
-
-	iomodel->FetchData(1,FlowequationElementEquationEnum);
-
-	/*Update elements: */
-	int counter=0;
-	for(int i=0;i<iomodel->numberofelements;i++){
-		if(iomodel->my_elements[i]){
-			Element* element=(Element*)elements->GetObjectByOffset(counter);
-			element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
-			counter++;
-		}
-	}
-
-	iomodel->FetchDataToInput(elements,ThicknessEnum);
-	iomodel->FetchDataToInput(elements,FrictionCoefficientEnum);
-	iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);
-	if(islevelset){
-		iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
-		if(iomodel->domaintype!=Domain2DhorizontalEnum)
-			iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes
-	}
-
-	/*Free data: */
-	iomodel->DeleteData(1,FlowequationElementEquationEnum);
-}/*}}}*/
-void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	/*Intermediaries*/
-	bool  isSIA;
-	Node* node = NULL;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
-
-	/*Now, is the flag isSIA on? otherwise, do nothing: */
-	if(!isSIA) return;
-
-	/*First create nodes*/
-	int    lid=0;
-	iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
-	if(iomodel->domaintype!=Domain2DhorizontalEnum){
-		iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	}
-
-	for(int i=0;i<iomodel->numberofvertices;i++){
-		if(iomodel->my_vertices[i]){
-
-			/*Create new node if is in this processor's partition*/
-			node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i]));
-
-			/*Deactivate node if not SIA*/
-			if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
-				node->Deactivate();
-			}
-
-			/*Add to Nodes dataset*/
-			nodes->AddObject(node);
-		}
-	}
-
-	iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,
-				FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
-
-}/*}}}*/
 void StressbalanceSIAAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
@@ -142,4 +60,86 @@
 
 	/*No loads*/
+
+}/*}}}*/
+void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	/*Intermediaries*/
+	bool  isSIA;
+	Node* node = NULL;
+
+	/*Fetch parameters: */
+	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
+
+	/*Now, is the flag isSIA on? otherwise, do nothing: */
+	if(!isSIA) return;
+
+	/*First create nodes*/
+	int    lid=0;
+	iomodel->FetchData(4,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
+	if(iomodel->domaintype!=Domain2DhorizontalEnum){
+		iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	}
+
+	for(int i=0;i<iomodel->numberofvertices;i++){
+		if(iomodel->my_vertices[i]){
+
+			/*Create new node if is in this processor's partition*/
+			node = new Node(iomodel->nodecounter+i+1,i,lid++,i,iomodel,StressbalanceSIAAnalysisEnum,reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i]));
+
+			/*Deactivate node if not SIA*/
+			if(reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
+				node->Deactivate();
+			}
+
+			/*Add to Nodes dataset*/
+			nodes->AddObject(node);
+		}
+	}
+
+	iomodel->DeleteData(6,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationBorderSSAEnum,FlowequationBorderFSEnum,
+				FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
+
+}/*}}}*/
+int  StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	return 2;
+}/*}}}*/
+void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+
+	/*Fetch data needed: */
+	bool   isSIA;
+	bool   islevelset;
+	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
+	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
+
+	/*Now, is the flag SIA on? otherwise, do nothing: */
+	if (!isSIA)return;
+
+	iomodel->FetchData(1,FlowequationElementEquationEnum);
+
+	/*Update elements: */
+	int counter=0;
+	for(int i=0;i<iomodel->numberofelements;i++){
+		if(iomodel->my_elements[i]){
+			Element* element=(Element*)elements->GetObjectByOffset(counter);
+			element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
+			counter++;
+		}
+	}
+
+	iomodel->FetchDataToInput(elements,ThicknessEnum);
+	iomodel->FetchDataToInput(elements,FrictionCoefficientEnum);
+	iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);
+	if(islevelset){
+		iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
+		if(iomodel->domaintype!=Domain2DhorizontalEnum)
+			iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum); // required for updating active nodes
+	}
+
+	/*Free data: */
+	iomodel->DeleteData(1,FlowequationElementEquationEnum);
+}/*}}}*/
+void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	/*No specific parameters*/
 
 }/*}}}*/
@@ -461,5 +461,5 @@
 
 }/*}}}*/
-void StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 
 	IssmDouble vx,vy;
@@ -494,8 +494,8 @@
 	xDelete<IssmDouble>(values);
 }/*}}}*/
-void StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           StressbalanceSIAAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           StressbalanceSIAAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int         i,domaintype;
@@ -581,5 +581,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
Index: /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -30,8 +30,8 @@
 		ElementVector* CreatePVector2D(Element* element);
 		ElementVector* CreatePVector3D(Element* element);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 18930)
@@ -7,49 +7,4 @@
 
 /*Model processing*/
-int  StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
-}/*}}}*/
-void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	/*No specific parameters*/
-
-}/*}}}*/
-void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-
-	/*return if not 3d mesh*/
-	if(iomodel->domaintype!=Domain3DEnum) return;
-
-	/*Update elements: */
-	int counter=0;
-	for(int i=0;i<iomodel->numberofelements;i++){
-		if(iomodel->my_elements[i]){
-			Element* element=(Element*)elements->GetObjectByOffset(counter);
-			element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
-			counter++;
-		}
-	}
-
-	iomodel->FetchDataToInput(elements,ThicknessEnum);
-	iomodel->FetchDataToInput(elements,SurfaceEnum);
-	iomodel->FetchDataToInput(elements,BaseEnum);
-	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
-	if(iomodel->domaintype!=Domain2DhorizontalEnum){
-		iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
-		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
-	}
-	iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
-	iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum);
-	iomodel->FetchDataToInput(elements,VxEnum,0.);
-	iomodel->FetchDataToInput(elements,VyEnum,0.);
-}/*}}}*/
-void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	/*return if not 3d mesh*/
-	if(iomodel->domaintype!=Domain3DEnum) return;
-
-	iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
-	::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum);
-	iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
-}/*}}}*/
 void StressbalanceVerticalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
@@ -98,4 +53,49 @@
 
 }/*}}}*/
+void StressbalanceVerticalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	/*return if not 3d mesh*/
+	if(iomodel->domaintype!=Domain3DEnum) return;
+
+	iomodel->FetchData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
+	::CreateNodes(nodes,iomodel,StressbalanceVerticalAnalysisEnum,P1Enum);
+	iomodel->DeleteData(3,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum,FlowequationVertexEquationEnum);
+}/*}}}*/
+int  StressbalanceVerticalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	return 1;
+}/*}}}*/
+void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+
+	/*return if not 3d mesh*/
+	if(iomodel->domaintype!=Domain3DEnum) return;
+
+	/*Update elements: */
+	int counter=0;
+	for(int i=0;i<iomodel->numberofelements;i++){
+		if(iomodel->my_elements[i]){
+			Element* element=(Element*)elements->GetObjectByOffset(counter);
+			element->Update(i,iomodel,analysis_counter,analysis_type,P1Enum);
+			counter++;
+		}
+	}
+
+	iomodel->FetchDataToInput(elements,ThicknessEnum);
+	iomodel->FetchDataToInput(elements,SurfaceEnum);
+	iomodel->FetchDataToInput(elements,BaseEnum);
+	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
+	if(iomodel->domaintype!=Domain2DhorizontalEnum){
+		iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
+		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
+	}
+	iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
+	iomodel->FetchDataToInput(elements,BasalforcingsFloatingiceMeltingRateEnum);
+	iomodel->FetchDataToInput(elements,VxEnum,0.);
+	iomodel->FetchDataToInput(elements,VyEnum,0.);
+}/*}}}*/
+void StressbalanceVerticalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	/*No specific parameters*/
+
+}/*}}}*/
 
 /*Finite Element Analysis*/
@@ -125,4 +125,45 @@
 	return Ke;
 
+}/*}}}*/
+ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/
+
+
+	if(!element->IsOnSurface()) return NULL;
+
+	/*Intermediaries*/
+	IssmDouble  D,Jdet,normal[3];
+	IssmDouble *xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Element matrix and vectors*/
+	ElementMatrix* Ke    = element->NewElementMatrix(NoneApproximationEnum);
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinatesTop(&xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss = element->NewGaussTop(2);
+	element->NormalTop(&normal[0],xyz_list);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminantTop(&Jdet,xyz_list,gauss);
+		element->NodalFunctions(basis,gauss);
+		D = -gauss->weight*Jdet*normal[2];
+
+		TripleMultiply( basis,1,numnodes,1,
+					&D,1,1,0,
+					basis,1,numnodes,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(basis);
+	return Ke;
 }/*}}}*/
 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/
@@ -167,45 +208,4 @@
 
 }/*}}}*/
-ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/
-
-
-	if(!element->IsOnSurface()) return NULL;
-
-	/*Intermediaries*/
-	IssmDouble  D,Jdet,normal[3];
-	IssmDouble *xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element matrix and vectors*/
-	ElementMatrix* Ke    = element->NewElementMatrix(NoneApproximationEnum);
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinatesTop(&xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss = element->NewGaussTop(2);
-	element->NormalTop(&normal[0],xyz_list);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminantTop(&Jdet,xyz_list,gauss);
-		element->NodalFunctions(basis,gauss);
-		D = -gauss->weight*Jdet*normal[2];
-
-		TripleMultiply( basis,1,numnodes,1,
-					&D,1,1,0,
-					basis,1,numnodes,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(basis);
-	return Ke;
-}/*}}}*/
 ElementVector* StressbalanceVerticalAnalysis::CreatePVector(Element* element){/*{{{*/
 
@@ -218,56 +218,4 @@
 	delete pe1;
 	delete pe2;
-	return pe;
-}/*}}}*/
-ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
-
-	/*Intermediaries*/
-	int         approximation;
-	IssmDouble  Jdet,dudx,dvdy,dwdz;
-	IssmDouble  du[3],dv[3],dw[3];
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element vector and basis functions*/
-	ElementVector* pe    = element->NewElementVector();
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GetInputValue(&approximation,ApproximationEnum);
-	Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);
-	Input* vzFS_input=NULL;
-	if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
-		vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input);
-	}
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctions(basis,gauss);
-
-		vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss);
-		vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss);
-		if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
-			vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss);
-			dwdz=dw[2];
-		}
-		else dwdz=0;
-		dudx=du[0];
-		dvdy=dv[1];
-
-		for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(xyz_list);
 	return pe;
 }/*}}}*/
@@ -338,5 +286,57 @@
 	return pe;
 }/*}}}*/
-void StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+ElementVector* StressbalanceVerticalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
+
+	/*Intermediaries*/
+	int         approximation;
+	IssmDouble  Jdet,dudx,dvdy,dwdz;
+	IssmDouble  du[3],dv[3],dw[3];
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize Element vector and basis functions*/
+	ElementVector* pe    = element->NewElementVector();
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	element->GetInputValue(&approximation,ApproximationEnum);
+	Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input);
+	Input* vzFS_input=NULL;
+	if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
+		vzFS_input=element->GetInput(VzFSEnum); _assert_(vzFS_input);
+	}
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctions(basis,gauss);
+
+		vx_input->GetInputDerivativeValue(&du[0],xyz_list,gauss);
+		vy_input->GetInputDerivativeValue(&dv[0],xyz_list,gauss);
+		if(approximation==HOFSApproximationEnum || approximation==SSAFSApproximationEnum){
+			vzFS_input->GetInputDerivativeValue(&dw[0],xyz_list,gauss);
+			dwdz=dw[2];
+		}
+		else dwdz=0;
+		dudx=du[0];
+		dvdy=dv[1];
+
+		for(int i=0;i<numnodes;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(xyz_list);
+	return pe;
+}/*}}}*/
+void           StressbalanceVerticalAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*	Compute B  matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz];
 		where hi is the interpolation function for node i.*/
@@ -357,16 +357,16 @@
 	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
-void StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+void           StressbalanceVerticalAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 
 	element->NodalFunctions(Bprime,gauss);
 
 }/*}}}*/
-void StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           StressbalanceVerticalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	element->GetSolutionFromInputsOneDof(solution,VzEnum);
 }/*}}}*/
-void StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           StressbalanceVerticalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           StressbalanceVerticalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int          numnodes = element->GetNumberOfNodes();
@@ -481,5 +481,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -25,15 +25,15 @@
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
+		ElementMatrix* CreateKMatrixSurface(Element* element);
 		ElementMatrix* CreateKMatrixVolume(Element* element);
-		ElementMatrix* CreateKMatrixSurface(Element* element);
 		ElementVector* CreatePVector(Element* element);
+		ElementVector* CreatePVectorBase(Element* element);
 		ElementVector* CreatePVectorVolume(Element* element);
-		ElementVector* CreatePVectorBase(Element* element);
-		void GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.cpp	(revision 18930)
@@ -6,30 +6,42 @@
 
 /*Model processing*/
+void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+
+	/*Only 3d mesh supported*/
+	int finiteelement = P1Enum;
+	if(iomodel->domaintype==Domain3DEnum){
+		IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement);
+	}
+
+}/*}}}*/
+void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
+
+	/*create penalties for nodes: no node can have a temperature over the melting point*/
+	iomodel->FetchData(1,ThermalSpctemperatureEnum);
+	CreateSingleNodeToElementConnectivity(iomodel);
+
+	for(int i=0;i<iomodel->numberofvertices;i++){
+
+		/*keep only this partition's nodes:*/
+		if(iomodel->my_vertices[i]){
+			if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes!
+				loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum));
+			}
+		}
+	}
+	iomodel->DeleteData(1,ThermalSpctemperatureEnum);
+
+}/*}}}*/
+void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	int finiteelement = P1Enum;
+	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement);
+	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+}/*}}}*/
 int  ThermalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
-
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
-
-	iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
-	parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
-	if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
-	iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
-
-	/*Deal with friction parameters*/
-	int frictionlaw;
-	iomodel->Constant(&frictionlaw,FrictionLawEnum);
-	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
 }/*}}}*/
 void ThermalAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -122,39 +134,27 @@
 	}
 }/*}}}*/
-void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int finiteelement = P1Enum;
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,ThermalAnalysisEnum,finiteelement);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-}/*}}}*/
-void ThermalAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-
-	/*Only 3d mesh supported*/
-	int finiteelement = P1Enum;
-	if(iomodel->domaintype==Domain3DEnum){
-		IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement);
-	}
-
-}/*}}}*/
-void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
-
-	/*create penalties for nodes: no node can have a temperature over the melting point*/
-	iomodel->FetchData(1,ThermalSpctemperatureEnum);
-	CreateSingleNodeToElementConnectivity(iomodel);
-
-	for(int i=0;i<iomodel->numberofvertices;i++){
-
-		/*keep only this partition's nodes:*/
-		if(iomodel->my_vertices[i]){
-			if (xIsNan<IssmDouble>(iomodel->Data(ThermalSpctemperatureEnum)[i])){ //No penalty applied on spc nodes!
-				loads->AddObject(new Pengrid(iomodel->loadcounter+i+1,i,iomodel,ThermalAnalysisEnum));
-			}
-		}
-	}
-	iomodel->DeleteData(1,ThermalSpctemperatureEnum);
-
+void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
+
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalMaxiterEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalStabilizationEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyFactorEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyThresholdEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalPenaltyLockEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsenthalpyEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(ThermalIsdynamicbasalspcEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(FrictionLawEnum));
+
+	iomodel->FetchData(&requestedoutputs,&numoutputs,ThermalRequestedOutputsEnum);
+	parameters->AddObject(new IntParam(ThermalNumRequestedOutputsEnum,numoutputs));
+	if(numoutputs)parameters->AddObject(new StringArrayParam(ThermalRequestedOutputsEnum,requestedoutputs,numoutputs));
+	iomodel->DeleteData(&requestedoutputs,numoutputs,ThermalRequestedOutputsEnum);
+
+	/*Deal with friction parameters*/
+	int frictionlaw;
+	iomodel->Constant(&frictionlaw,FrictionLawEnum);
+	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
 }/*}}}*/
 
@@ -183,4 +183,58 @@
 	delete Ke1;
 	delete Ke2;
+	return Ke;
+}/*}}}*/
+ElementMatrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
+
+	IssmDouble  dt,Jdet,D;
+	IssmDouble *xyz_list_base = NULL;
+
+	/*Get basal element*/
+	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize vectors*/
+	ElementMatrix* Ke    = element->NewElementMatrix();
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinatesBase(&xyz_list_base);
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
+	IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
+	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
+	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
+	IssmDouble  mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum);
+	IssmDouble  thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGaussBase(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
+		element->NodalFunctions(basis,gauss);
+
+		D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice);
+		if(reCast<bool,IssmDouble>(dt)) D=dt*D;
+		TripleMultiply(basis,numnodes,1,0,
+					&D,1,1,0,
+					basis,1,numnodes,0,
+					&Ke->values[0],1);
+
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(xyz_list_base);
 	return Ke;
 }/*}}}*/
@@ -318,23 +372,38 @@
 	return Ke;
 }/*}}}*/
-ElementMatrix* ThermalAnalysis::CreateKMatrixShelf(Element* element){/*{{{*/
-
+ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/
+	
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return NULL;
 
-	/*Initialize Element matrix and return if necessary*/
-	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
-
-	IssmDouble  dt,Jdet,D;
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorVolume(element);
+	ElementVector* pe2=CreatePVectorSheet(element);
+	ElementVector* pe3=CreatePVectorShelf(element);
+	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	delete pe3;
+	return pe;
+}/*}}}*/
+ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/* Geothermal flux on ice sheet base and basal friction */
+	if(!element->IsOnBase() || element->IsFloating()) return NULL;
+
+	IssmDouble  dt,Jdet,geothermalflux,vx,vy,vz;
+	IssmDouble  alpha2,scalar,basalfriction,heatflux;
 	IssmDouble *xyz_list_base = NULL;
 
-	/*Get basal element*/
-	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
-
 	/*Fetch number of nodes for this finite element*/
 	int numnodes = element->GetNumberOfNodes();
 
 	/*Initialize vectors*/
-	ElementMatrix* Ke    = element->NewElementMatrix();
+	ElementVector* pe    = element->NewElementVector();
 	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
 
@@ -342,4 +411,66 @@
 	element->GetVerticesCoordinatesBase(&xyz_list_base);
 	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* vx_input             = element->GetInput(VxEnum);                          _assert_(vx_input);
+	Input* vy_input             = element->GetInput(VyEnum);                          _assert_(vy_input);
+	Input* vz_input             = element->GetInput(VzEnum);                          _assert_(vz_input);
+	Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
+	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
+	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
+
+	/*Build friction element, needed later: */
+	Friction* friction=new Friction(element,3);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss   = element->NewGaussBase(2);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
+		element->NodalFunctions(basis,gauss);
+
+		geothermalflux_input->GetInputValue(&geothermalflux,gauss);
+		friction->GetAlpha2(&alpha2,gauss);
+		vx_input->GetInputValue(&vx,gauss);
+		vy_input->GetInputValue(&vy,gauss);
+		vz_input->GetInputValue(&vz,gauss);
+		vz = 0.;//FIXME
+		basalfriction = alpha2*(vx*vx + vy*vy + vz*vz);
+		heatflux      = (basalfriction+geothermalflux)/(rho_ice*heatcapacity);
+
+		scalar = gauss->weight*Jdet*heatflux;
+		if(dt!=0.) scalar=dt*scalar;
+
+		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	xDelete<IssmDouble>(basis);
+	xDelete<IssmDouble>(xyz_list_base);
+	return pe;
+}/*}}}*/
+ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/
+
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	IssmDouble  t_pmp,dt,Jdet,scalar_ocean,pressure;
+	IssmDouble *xyz_list_base = NULL;
+
+	/*Get basal element*/
+	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
+
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+
+	/*Initialize vectors*/
+	ElementVector* pe    = element->NewElementVector();
+	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinatesBase(&xyz_list_base);
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input*      pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input);
 	IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
 	IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
@@ -357,11 +488,11 @@
 		element->NodalFunctions(basis,gauss);
 
-		D=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel/(heatcapacity*rho_ice);
-		if(reCast<bool,IssmDouble>(dt)) D=dt*D;
-		TripleMultiply(basis,numnodes,1,0,
-					&D,1,1,0,
-					basis,1,numnodes,0,
-					&Ke->values[0],1);
-
+		pressure_input->GetInputValue(&pressure,gauss);
+		t_pmp=element->TMeltingPoint(pressure);
+
+		scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice);
+		if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean;
+
+		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i];
 	}
 
@@ -370,21 +501,4 @@
 	xDelete<IssmDouble>(basis);
 	xDelete<IssmDouble>(xyz_list_base);
-	return Ke;
-}/*}}}*/
-ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/
-	
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorVolume(element);
-	ElementVector* pe2=CreatePVectorSheet(element);
-	ElementVector* pe3=CreatePVectorShelf(element);
-	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	delete pe3;
 	return pe;
 }/*}}}*/
@@ -471,122 +585,63 @@
 
 }/*}}}*/
-ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	/* Geothermal flux on ice sheet base and basal friction */
-	if(!element->IsOnBase() || element->IsFloating()) return NULL;
-
-	IssmDouble  dt,Jdet,geothermalflux,vx,vy,vz;
-	IssmDouble  alpha2,scalar,basalfriction,heatflux;
-	IssmDouble *xyz_list_base = NULL;
+void           ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_advec =[ h ]
+	 *                 [ h ]
+	 *                 [ h ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
+	 */
 
 	/*Fetch number of nodes for this finite element*/
 	int numnodes = element->GetNumberOfNodes();
 
-	/*Initialize vectors*/
-	ElementVector* pe    = element->NewElementVector();
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinatesBase(&xyz_list_base);
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* vx_input             = element->GetInput(VxEnum);                          _assert_(vx_input);
-	Input* vy_input             = element->GetInput(VyEnum);                          _assert_(vy_input);
-	Input* vz_input             = element->GetInput(VzEnum);                          _assert_(vz_input);
-	Input* geothermalflux_input = element->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
-	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
-	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
-
-	/*Build friction element, needed later: */
-	Friction* friction=new Friction(element,3);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss   = element->NewGaussBase(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
-		element->NodalFunctions(basis,gauss);
-
-		geothermalflux_input->GetInputValue(&geothermalflux,gauss);
-		friction->GetAlpha2(&alpha2,gauss);
-		vx_input->GetInputValue(&vx,gauss);
-		vy_input->GetInputValue(&vy,gauss);
-		vz_input->GetInputValue(&vz,gauss);
-		vz = 0.;//FIXME
-		basalfriction = alpha2*(vx*vx + vy*vy + vz*vz);
-		heatflux      = (basalfriction+geothermalflux)/(rho_ice*heatcapacity);
-
-		scalar = gauss->weight*Jdet*heatflux;
-		if(dt!=0.) scalar=dt*scalar;
-
-		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
+	/*Get nodal functions*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = basis[i];
+		B[numnodes*1+i] = basis[i];
+		B[numnodes*2+i] = basis[i];
+	}
+
+	/*Clean-up*/
 	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(xyz_list_base);
-	return pe;
-}/*}}}*/
-ElementVector* ThermalAnalysis::CreatePVectorShelf(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	IssmDouble  t_pmp,dt,Jdet,scalar_ocean,pressure;
-	IssmDouble *xyz_list_base = NULL;
-
-	/*Get basal element*/
-	if(!element->IsOnBase() || !element->IsFloating()) return NULL;
+}/*}}}*/
+void           ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
+	 * For node i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Biprime_advec=[ dh/dx ]
+	 *                     [ dh/dy ]
+	 *                     [ dh/dz ]
+	 * where h is the interpolation function for node i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
+	 */
 
 	/*Fetch number of nodes for this finite element*/
 	int numnodes = element->GetNumberOfNodes();
 
-	/*Initialize vectors*/
-	ElementVector* pe    = element->NewElementVector();
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinatesBase(&xyz_list_base);
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input*      pressure_input=element->GetInput(PressureEnum); _assert_(pressure_input);
-	IssmDouble  gravity             = element->GetMaterialParameter(ConstantsGEnum);
-	IssmDouble  rho_water           = element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
-	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
-	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
-	IssmDouble  mixed_layer_capacity= element->GetMaterialParameter(MaterialsMixedLayerCapacityEnum);
-	IssmDouble  thermal_exchange_vel= element->GetMaterialParameter(MaterialsThermalExchangeVelocityEnum);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGaussBase(2);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
-		element->NodalFunctions(basis,gauss);
-
-		pressure_input->GetInputValue(&pressure,gauss);
-		t_pmp=element->TMeltingPoint(pressure);
-
-		scalar_ocean=gauss->weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_vel*(t_pmp)/(heatcapacity*rho_ice);
-		if(reCast<bool,IssmDouble>(dt)) scalar_ocean=dt*scalar_ocean;
-
-		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_ocean*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(xyz_list_base);
-	return pe;
-}/*}}}*/
-void ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-	element->GetSolutionFromInputsOneDof(solution,TemperatureEnum);
-}/*}}}*/
-void ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+	/*Build B: */
+	for(int i=0;i<numnodes;i++){
+		B[numnodes*0+i] = dbasis[0*numnodes+i];
+		B[numnodes*1+i] = dbasis[1*numnodes+i];
+		B[numnodes*2+i] = dbasis[2*numnodes+i];
+	}
+
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
+}/*}}}*/
+void           ThermalAnalysis::GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
 	 * For node i, Bi' can be expressed in the actual coordinate system
@@ -617,66 +672,11 @@
 	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
-void ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Bi_advec =[ h ]
-	 *                 [ h ]
-	 *                 [ h ]
-	 * where h is the interpolation function for node i.
-	 *
-	 * We assume B has been allocated already, of size: 3x(NDOF1*NUMNODESP1)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions*/
-	IssmDouble* basis=xNew<IssmDouble>(numnodes);
-	element->NodalFunctions(basis,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = basis[i];
-		B[numnodes*1+i] = basis[i];
-		B[numnodes*2+i] = basis[i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(basis);
-}/*}}}*/
-void ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
-	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF1. 
-	 * For node i, Bi' can be expressed in the actual coordinate system
-	 * by: 
-	 *       Biprime_advec=[ dh/dx ]
-	 *                     [ dh/dy ]
-	 *                     [ dh/dz ]
-	 * where h is the interpolation function for node i.
-	 *
-	 * We assume B has been allocated already, of size: 3x(NDOF1*numnodes)
-	 */
-
-	/*Fetch number of nodes for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-	/*Build B: */
-	for(int i=0;i<numnodes;i++){
-		B[numnodes*0+i] = dbasis[0*numnodes+i];
-		B[numnodes*1+i] = dbasis[1*numnodes+i];
-		B[numnodes*2+i] = dbasis[2*numnodes+i];
-	}
-
-	/*Clean-up*/
-	xDelete<IssmDouble>(dbasis);
-}/*}}}*/
-void ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           ThermalAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+	element->GetSolutionFromInputsOneDof(solution,TemperatureEnum);
+}/*}}}*/
+void           ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           ThermalAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	bool        converged;
@@ -758,5 +758,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
Index: /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/ThermalAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -25,17 +25,17 @@
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		ElementMatrix* CreateKMatrix(Element* element);
+		ElementMatrix* CreateKMatrixShelf(Element* element);
 		ElementMatrix* CreateKMatrixVolume(Element* element);
-		ElementMatrix* CreateKMatrixShelf(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		ElementVector* CreatePVectorVolume(Element* element);
 		ElementVector* CreatePVectorSheet(Element* element);
 		ElementVector* CreatePVectorShelf(Element* element);
-		void GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		ElementVector* CreatePVectorVolume(Element* element);
+		void           GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetBConduct(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
Index: /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp
===================================================================
--- /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp	(revision 18930)
@@ -6,11 +6,24 @@
 
 /*Model processing*/
+void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	return;
+}/*}}}*/
+void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	return;
+}/*}}}*/
+void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+
+	int finiteelement;
+	int fe_FS;
+
+	iomodel->Constant(&fe_FS,FlowequationFeFSEnum);
+	if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum;
+	else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum;
+	else _error_("solution not supported yet");
+
+	::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement);
+}/*}}}*/
 int  UzawaPressureAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
 	return 1;
-}/*}}}*/
-void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
-
-	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));
-	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));
 }/*}}}*/
 void UzawaPressureAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
@@ -40,21 +53,8 @@
 	InputUpdateFromConstantx(elements,0.,SigmaNNEnum);
 }/*}}}*/
-void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int finiteelement;
-	int fe_FS;
-
-	iomodel->Constant(&fe_FS,FlowequationFeFSEnum);
-	if(fe_FS==LATaylorHoodEnum) finiteelement = P1Enum;
-	else if(fe_FS==LACrouzeixRaviartEnum) finiteelement = P1DGEnum;
-	else _error_("solution not supported yet");
-
-	::CreateNodes(nodes,iomodel,UzawaPressureAnalysisEnum,finiteelement);
-}/*}}}*/
-void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	return;
-}/*}}}*/
-void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	return;
+void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+
+	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));
 }/*}}}*/
 
@@ -164,5 +164,5 @@
 	return pe;
 }/*}}}*/
-void UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/
+void           UzawaPressureAnalysis::GetM(IssmDouble* M,Element* element,Gauss* gauss){/*{{{*/
 	/*Compute B  matrix. M=[M1 M2 M3] */
 
@@ -182,11 +182,11 @@
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           UzawaPressureAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+void           UzawaPressureAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	_error_("Not implemented yet");
 }/*}}}*/
-void UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           UzawaPressureAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int        dim;
@@ -297,5 +297,5 @@
 	xDelete<int>(doflist);
 }/*}}}*/
-void UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
Index: /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h
===================================================================
--- /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h	(revision 18929)
+++ /issm/trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h	(revision 18930)
@@ -13,10 +13,10 @@
 	public:
 		/*Model processing*/
-		int  DofsPerNode(int** doflist,int domaintype,int approximation);
-		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
-		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
-		void CreateNodes(Nodes* nodes,IoModel* iomodel);
 		void CreateConstraints(Constraints* constraints,IoModel* iomodel);
 		void CreateLoads(Loads* loads, IoModel* iomodel);
+		void CreateNodes(Nodes* nodes,IoModel* iomodel);
+		int  DofsPerNode(int** doflist,int domaintype,int approximation);
+		void UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type);
+		void UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum);
 
 		/*Finite element Analysis*/
@@ -26,9 +26,9 @@
 		ElementMatrix* CreateKMatrix(Element* element);
 		ElementVector* CreatePVector(Element* element);
-		void GetM(IssmDouble* M,Element* element,Gauss* gauss);
-		void GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
-		void GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
-		void InputUpdateFromSolution(IssmDouble* solution,Element* element);
-		void UpdateConstraints(FemModel* femmodel);
+		void           GetM(IssmDouble* M,Element* element,Gauss* gauss);
+		void           GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element);
+		void           GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index);
+		void           InputUpdateFromSolution(IssmDouble* solution,Element* element);
+		void           UpdateConstraints(FemModel* femmodel);
 };
 #endif
