Index: ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -29,9 +29,9 @@
 		ElementVector* CreatePVector(Element* element);
 		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: ../trunk-jpl/src/c/analyses/SeaiceAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/SeaiceAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/SeaiceAnalysis.h	(revision 18930)
@@ -12,29 +12,27 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*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: ../trunk-jpl/src/c/analyses/ThermalAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/ThermalAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/ThermalAnalysis.h	(revision 18930)
@@ -12,30 +12,30 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
 		ElementVector* CreateDVector(Element* element);
 		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: ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.cpp	(revision 18930)
@@ -5,68 +5,6 @@
 #include "../modules/modules.h"
 
 /*Model processing*/
-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){/*{{{*/
-
-	int    stabilization,finiteelement;
-
-	/*Fetch data needed: */
-	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
-
-	/*Finite element type*/
-	finiteelement = P1Enum;
-	if(stabilization==3){
-		finiteelement = P1DGEnum;
-	}
-
-	/*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++;
-		}
-	}
-
-	iomodel->FetchDataToInput(elements,ThicknessEnum);
-	iomodel->FetchDataToInput(elements,SurfaceEnum);
-	iomodel->FetchDataToInput(elements,BaseEnum);
-	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
-	iomodel->FetchDataToInput(elements,VxEnum);
-	iomodel->FetchDataToInput(elements,VyEnum);
-	iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
-	iomodel->FetchDataToInput(elements,SurfaceforcingsMassBalanceEnum);
-	iomodel->FetchDataToInput(elements,BalancethicknessThickeningRateEnum);
-
-	if(iomodel->domaintype!=Domain2DhorizontalEnum){
-		iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
-		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
-	}
-}/*}}}*/
-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: */
@@ -112,7 +50,69 @@
 		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::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+
+	int    stabilization,finiteelement;
+
+	/*Fetch data needed: */
+	iomodel->Constant(&stabilization,BalancethicknessStabilizationEnum);
+
+	/*Finite element type*/
+	finiteelement = P1Enum;
+	if(stabilization==3){
+		finiteelement = P1DGEnum;
+	}
+
+	/*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++;
+		}
+	}
+
+	iomodel->FetchDataToInput(elements,ThicknessEnum);
+	iomodel->FetchDataToInput(elements,SurfaceEnum);
+	iomodel->FetchDataToInput(elements,BaseEnum);
+	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
+	iomodel->FetchDataToInput(elements,VxEnum);
+	iomodel->FetchDataToInput(elements,VyEnum);
+	iomodel->FetchDataToInput(elements,BasalforcingsGroundediceMeltingRateEnum);
+	iomodel->FetchDataToInput(elements,SurfaceforcingsMassBalanceEnum);
+	iomodel->FetchDataToInput(elements,BalancethicknessThickeningRateEnum);
+
+	if(iomodel->domaintype!=Domain2DhorizontalEnum){
+		iomodel->FetchDataToInput(elements,MeshVertexonbaseEnum);
+		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
+	}
+}/*}}}*/
+void BalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+	parameters->AddObject(iomodel->CopyConstantObject(BalancethicknessStabilizationEnum));
+}/*}}}*/
+
 /*Finite Element Analysis*/
 void           BalancethicknessAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -420,7 +420,7 @@
 	delete gauss;
 	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
 	 * by: 
@@ -447,7 +447,7 @@
 	/*Clean-up*/
 	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
 	 * by: 
@@ -475,10 +475,10 @@
 	xDelete<IssmDouble>(dbasis);
 
 }/*}}}*/
-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 */
 
 	/*If on water, grad = 0: */
@@ -594,7 +594,7 @@
 
 
 }/*}}}*/
-void BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           BalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	int domaintype;
 	element->FindParam(&domaintype,DomainTypeEnum);
@@ -608,7 +608,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           BalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.cpp	(revision 18930)
@@ -5,22 +5,22 @@
 #include "../modules/modules.h"
 
 /*Model processing*/
-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){/*{{{*/
+void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void AdjointHorizAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+void AdjointHorizAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
 void AdjointHorizAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 	   _error_("not implemented yet");
 }/*}}}*/
-void AdjointHorizAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+int  AdjointHorizAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	_error_("not implemented");
+}/*}}}*/
+void AdjointHorizAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 	   _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");
 }/*}}}*/
 
@@ -53,110 +53,95 @@
 			_error_("Approximation "<<EnumToStringx(approximation)<<" not supported");
 	}
 }/*}}}*/
-ElementMatrix* AdjointHorizAnalysis::CreateKMatrixSSA(Element* element){/*{{{*/
+ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
 
-	/*Intermediaries*/
-	int      domaintype;
-	Element* basalelement;
-
-	/*Get basal element*/
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			basalelement = element;
-			break;
-		case Domain3DEnum:
-			if(!element->IsOnBase()) return NULL;
-			basalelement = element->SpawnBasalElement();
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-
 	/*Intermediaries */
 	bool        incomplete_adjoint;
-	IssmDouble  Jdet,thickness,mu_prime;
-	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
-	IssmDouble  eps1[2],eps2[2],epsilon[3];
+	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 numnodes = basalelement->GetNumberOfNodes();
+	int vnumnodes = element->NumberofNodesVelocity();
+	int pnumnodes = element->NumberofNodesPressure();
+	int numdof    = vnumnodes*dim + pnumnodes;
 
-	/*Initialize Jacobian with regular SSA (first part of the Gateau derivative)*/
-	basalelement->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
+	/*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){
-		if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
-		return Ke;
-	}
+	if(incomplete_adjoint) return Ke;
 
 	/*Retrieve all inputs and parameters*/
-	basalelement->GetVerticesCoordinates(&xyz_list);
-	Input* vx_input        = basalelement->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input        = basalelement->GetInput(VyEnum);       _assert_(vy_input);
-	Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input);
+	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>(2*numnodes);
+	IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
 
 	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=basalelement->NewGauss(2);
+	Gauss* gauss=element->NewGauss(5);
 	for(int ig=gauss->begin();ig<gauss->end();ig++){
 		gauss->GaussPoint(ig);
 
-		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		basalelement->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
 
-		thickness_input->GetInputValue(&thickness, gauss);
-		basalelement->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
-		basalelement->ViscositySSADerivativeEpsSquare(&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];
+		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<numnodes;i++){
-			for(int j=0;j<numnodes;j++){
-				eps1dotdphii=eps1[0]*dbasis[0*numnodes+i]+eps1[1]*dbasis[1*numnodes+i];
-				eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j];
-				eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i];
-				eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+j];
+		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[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*thickness*eps1dotdphij*eps1dotdphii;
-				Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*thickness*eps2dotdphij*eps1dotdphii;
-				Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*thickness*eps1dotdphij*eps2dotdphii;
-				Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*thickness*eps2dotdphij*eps2dotdphii;
+				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*/
-	basalelement->TransformStiffnessMatrixCoord(Ke,XYEnum);
+	element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
 
 	/*Clean up and return*/
 	delete gauss;
 	xDelete<IssmDouble>(dbasis);
 	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 */
@@ -222,93 +207,108 @@
 	xDelete<IssmDouble>(xyz_list);
 	return Ke;
 }/*}}}*/
-ElementMatrix* AdjointHorizAnalysis::CreateKMatrixFS(Element* element){/*{{{*/
+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){/*{{{*/
+
+	/*Intermediaries*/
+	int      domaintype;
+	Element* basalelement;
+
+	/*Get basal element*/
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			basalelement = element;
+			break;
+		case Domain3DEnum:
+			if(!element->IsOnBase()) return NULL;
+			basalelement = element->SpawnBasalElement();
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+
 	/*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  Jdet,thickness,mu_prime;
+	IssmDouble  eps1dotdphii,eps1dotdphij,eps2dotdphii,eps2dotdphij;
+	IssmDouble  eps1[2],eps2[2],epsilon[3];
 	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;
+	int numnodes = basalelement->GetNumberOfNodes();
 
-	/*Initialize Jacobian with regular FS (first part of the Gateau derivative)*/
-	element->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
+	/*Initialize Jacobian with regular SSA (first part of the Gateau derivative)*/
+	basalelement->FindParam(&incomplete_adjoint,InversionIncompleteAdjointEnum);
 	StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
 	ElementMatrix* Ke=analysis->CreateKMatrix(element);
 	delete analysis;
-	if(incomplete_adjoint) return Ke;
+	if(incomplete_adjoint){
+		if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+		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");
-	}
+	basalelement->GetVerticesCoordinates(&xyz_list);
+	Input* vx_input        = basalelement->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input        = basalelement->GetInput(VyEnum);       _assert_(vy_input);
+	Input* thickness_input = basalelement->GetInput(ThicknessEnum); _assert_(thickness_input);
 
 	/*Allocate dbasis*/
-	IssmDouble* dbasis = xNew<IssmDouble>(dim*vnumnodes);
+	IssmDouble* dbasis = xNew<IssmDouble>(2*numnodes);
 
 	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(5);
+	Gauss* gauss=basalelement->NewGauss(2);
 	for(int ig=gauss->begin();ig<gauss->end();ig++){
 		gauss->GaussPoint(ig);
 
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->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];
+		thickness_input->GetInputValue(&thickness, gauss);
+		basalelement->StrainRateSSA(&epsilon[0],xyz_list,gauss,vx_input,vy_input);
+		basalelement->ViscositySSADerivativeEpsSquare(&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];
 
-		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];
+		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];
+				eps1dotdphij=eps1[0]*dbasis[0*numnodes+j]+eps1[1]*dbasis[1*numnodes+j];
+				eps2dotdphii=eps2[0]*dbasis[0*numnodes+i]+eps2[1]*dbasis[1*numnodes+i];
+				eps2dotdphij=eps2[0]*dbasis[0*numnodes+j]+eps2[1]*dbasis[1*numnodes+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;
+				Ke->values[2*numnodes*(2*i+0)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*thickness*eps1dotdphij*eps1dotdphii;
+				Ke->values[2*numnodes*(2*i+0)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*thickness*eps2dotdphij*eps1dotdphii;
+				Ke->values[2*numnodes*(2*i+1)+2*j+0]+=gauss->weight*Jdet*2*mu_prime*thickness*eps1dotdphij*eps2dotdphii;
+				Ke->values[2*numnodes*(2*i+1)+2*j+1]+=gauss->weight*Jdet*2*mu_prime*thickness*eps2dotdphij*eps2dotdphii;
 			}
 		}
 	}
 
 	/*Transform Coordinate System*/
-	element->TransformStiffnessMatrixCoord(Ke,XYZEnum);
+	basalelement->TransformStiffnessMatrixCoord(Ke,XYEnum);
 
 	/*Clean up and return*/
 	delete gauss;
 	xDelete<IssmDouble>(dbasis);
 	xDelete<IssmDouble>(xyz_list);
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 	return Ke;
 }/*}}}*/
 ElementVector* AdjointHorizAnalysis::CreatePVector(Element* element){/*{{{*/
@@ -566,6 +566,11 @@
 	delete gauss;
 	return pe;
 }/*}}}*/
+ElementVector* AdjointHorizAnalysis::CreatePVectorL1L2(Element* element){/*{{{*/
+
+	/*Same as SSA*/
+	return this->CreatePVectorSSA(element);
+}/*}}}*/
 ElementVector* AdjointHorizAnalysis::CreatePVectorHO(Element* element){/*{{{*/
 
 	/*Nothing to be done if not on surface*/
@@ -1041,15 +1046,10 @@
 	delete gauss;
 	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.
 	 *
 	 * dJ    \partial J   \partial lambda^T(KU-F)
@@ -1137,13 +1137,14 @@
 	xDelete<int>(responses);
                          
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragGradient(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){/*{{{*/
 
-	/*return if floating (gradient is 0)*/
-	if(element->IsFloating()) return;
-
 	/*Intermediaries*/
-	int      domaintype,dim;
+	int      domaintype;
 	Element* basalelement;
 
 	/*Get basal element*/
@@ -1151,17 +1152,14 @@
 	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");
 	}
@@ -1182,8 +1180,8 @@
 	/*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);
+	Input* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum);              _assert_(rheologyb_input);
+	Input* weights_input   = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_input);
 
 	/* Start  looping on the number of gaussian points: */
 	Gauss* gauss=basalelement->NewGauss(2);
@@ -1192,14 +1190,14 @@
 
 		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
-		weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
+		weights_input->GetInputValue(&weight,gauss,RheologyBbarAbsGradientEnum);
 
 		/*Build alpha_complement_list: */
-		dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
+		rheologyb_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
 
-		/*Build gradient vector (actually -dJ/ddrag): */
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
 		for(int i=0;i<numvertices;i++){
-			if(dim==2){
+			if(domaintype!=Domain2DverticalEnum){
 				ge[i]+=-weight*Jdet*gauss->weight*(dbasis[0*numvertices+i]*dk[0]+dbasis[1*numvertices+i]*dk[1]);
 			}
 			else{
@@ -1217,12 +1215,21 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 	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::GradientJBbarGradient(Element* element,Vector<IssmDouble>* gradient,int 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;
+	int      domaintype,dim;
 	Element* basalelement;
 
 	/*Get basal element*/
@@ -1230,57 +1237,66 @@
 	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 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* dbasis        = xNew<IssmDouble>(2*numvertices);
+	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* rheologyb_input = basalelement->GetInput(MaterialsRheologyBbarEnum);              _assert_(rheologyb_input);
-	Input* weights_input   = basalelement->GetInput(InversionCostFunctionsCoefficientsEnum); _assert_(weights_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(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
 
 	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=basalelement->NewGauss(2);
+	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->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
-		weights_input->GetInputValue(&weight,gauss,RheologyBbarAbsGradientEnum);
+		basalelement->NodalFunctionsP1(basis,gauss);
 
-		/*Build alpha_complement_list: */
-		rheologyb_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
-
-		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		/*Build gradient vector (actually -dJ/dB): */
 		for(int i=0;i<numvertices;i++){
-			if(domaintype!=Domain2DverticalEnum){
-				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];
-			}
+			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]));
 		}
 	}
@@ -1288,13 +1304,17 @@
 
 	/*Clean up and return*/
 	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(dbasis);
+	xDelete<IssmDouble>(basis);
 	xDelete<IssmDouble>(ge);
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBGradient(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+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*/
 	int      domaintype;
@@ -1360,12 +1380,85 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+	/*Intermediaries*/
+	int      domaintype,dim;
 
-	/*return if floating (gradient is 0)*/
-	if(element->IsFloating()) return;
+	/*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*/
 	int      domaintype,dim;
 	Element* basalelement;
 
@@ -1391,8 +1484,8 @@
 
 	/*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;
 
 	/*Fetch number of vertices for this finite element*/
@@ -1403,37 +1496,37 @@
 	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);
+	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);
 
-		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);
+		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);
 
-		friction->GetAlphaComplement(&dalpha2dk,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]));
 		}
 	}
@@ -1445,89 +1538,91 @@
 	xDelete<IssmDouble>(ge);
 	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){/*{{{*/
+void           AdjointHorizAnalysis::GradientJDragGradient(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)*/
+	/*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;
+	IssmDouble dk[3]; 
+	IssmDouble *xyz_list= NULL;
 
-	int      domaintype,dim;
-	element->FindParam(&domaintype,DomainTypeEnum);
 	/*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: */
+	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);
 
-	/*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);
+	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);
+		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		basalelement->NodalFunctionsP1Derivatives(dbasis,xyz_list,gauss);
+		weights_input->GetInputValue(&weight,gauss,DragCoefficientAbsGradientEnum);
 
-		friction->GetAlphaComplement(&dalpha2dk,gauss);
+		/*Build alpha_complement_list: */
+		dragcoefficient_input->GetInputDerivativeValue(&dk[0],xyz_list,gauss);
 
-		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
-		element->NodalFunctionsP1(basis,gauss);
-
-		/*Build gradient vector (actually -dJ/dD): */
+		/*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]));
 		}
 	}
 	gradient->SetValues(numvertices,vertexpidlist,ge,ADD_VAL);
 
 	/*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;
+	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJDragFS(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*return if floating or not on bed (gradient is 0)*/
 	if(element->IsFloating()) return;
@@ -1623,106 +1718,90 @@
 	delete gauss;
 	delete friction;
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJDragL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
-	/*Intermediaries*/
-	int      domaintype,dim;
-	Element* basalelement;
+	/*Same as SSA*/
+	return this->GradientJDragSSA(element,gradient,control_index);
+}/*}}}*/
+void           AdjointHorizAnalysis::GradientJDragHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
-	/*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");
-	}
+	/*return if floating or not on bed (gradient is 0)*/
+	if(element->IsFloating()) return;
+	if(!element->IsOnBase()) return;
 
 	/*Intermediaries*/
 	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudB;
-	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
-	IssmDouble *xyz_list= NULL;
+	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 = basalelement->GetNumberOfVertices();
+	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: */
-	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);
-
+	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=basalelement->NewGauss(4);
+	Gauss* gauss=element->NewGaussBase(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);
+		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);
 
-		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
+		friction->GetAlphaComplement(&dalpha2dk,gauss);
 
-		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		basalelement->NodalFunctionsP1(basis,gauss);
+		element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss);
+		element->NodalFunctionsP1(basis,gauss);
 
-		/*Build gradient vector (actually -dJ/dB): */
+		/*Build gradient vector (actually -dJ/dD): */
 		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];
+			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);
+	xDelete<IssmDouble>(xyz_list_base);
 	xDelete<IssmDouble>(basis);
 	xDelete<IssmDouble>(ge);
 	xDelete<int>(vertexpidlist);
 	delete gauss;
-	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
+	delete friction;
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBbarL1L2(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointHorizAnalysis::GradientJDragSSA(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){/*{{{*/
+	/*return if floating (gradient is 0)*/
+	if(element->IsFloating()) return;
 
-	/*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;
@@ -1749,8 +1828,8 @@
 
 	/*Intermediaries*/
 	IssmDouble Jdet,weight;
-	IssmDouble thickness,dmudB;
-	IssmDouble dvx[3],dvy[3],dadjx[3],dadjy[3]; 
+	IssmDouble drag,dalpha2dk;
+	IssmDouble vx,vy,lambda,mu;
 	IssmDouble *xyz_list= NULL;
 
 	/*Fetch number of vertices for this finite element*/
@@ -1761,37 +1840,37 @@
 	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* 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);
+	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);
 
-		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);
+		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);
 
-		basalelement->dViscositydBSSA(&dmudB,dim,xyz_list,gauss,vx_input,vy_input);
+		friction->GetAlphaComplement(&dalpha2dk,gauss);
 
 		basalelement->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		basalelement->NodalFunctionsP1(basis,gauss);
 
-		/*Build gradient vector (actually -dJ/dB): */
+		/*Build gradient vector (actually -dJ/dD): */
 		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];
+			ge[i]+=-2.*drag*dalpha2dk*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i];
 			_assert_(!xIsNan<IssmDouble>(ge[i]));
 		}
 	}
@@ -1803,91 +1882,12 @@
 	xDelete<IssmDouble>(ge);
 	xDelete<int>(vertexpidlist);
 	delete gauss;
+	delete friction;
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void AdjointHorizAnalysis::GradientJBHO(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
-	/*Intermediaries*/
-	int      domaintype,dim;
+void           AdjointHorizAnalysis::GradientJDSSA(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
-	/*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;
 
@@ -1968,7 +1968,7 @@
 	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);
 	if(approximation==FSApproximationEnum || approximation==NoneApproximationEnum){
@@ -1978,53 +1978,7 @@
 		InputUpdateFromSolutionHoriz(solution,element);
 	}
 }/*}}}*/
-void AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
-	int  i;
-	int* doflist=NULL;
-
-	int    domaintype;
-	element->FindParam(&domaintype,DomainTypeEnum);
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-	int numdof;
-	if(domaintype!=Domain2DverticalEnum)  numdof   = numnodes*2;
-	else			                          numdof   = numnodes*1;
-	/*Fetch dof list and allocate solution vectors*/
-	element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	IssmDouble* values  = xNew<IssmDouble>(numdof);
-	IssmDouble* lambdax = xNew<IssmDouble>(numnodes);
-	IssmDouble* lambday = xNew<IssmDouble>(numnodes);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
-
-	/*Transform solution in Cartesian Space*/
-	if(domaintype!=Domain2DverticalEnum)	element->TransformSolutionCoord(&values[0],XYEnum);
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(i=0;i<numnodes;i++){
-		if(domaintype!=Domain2DverticalEnum){
-			lambdax[i]=values[i*NDOF2+0];
-			lambday[i]=values[i*NDOF2+1];
-		}
-		else {lambdax[i]=values[i];lambday[i]=0;}
-		/*Check solution*/
-		if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
-		if(domaintype!=Domain2DverticalEnum && xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Add vx and vy as inputs to the tria element: */
-	element->AddInput(AdjointxEnum,lambdax,element->GetElementType());
-	element->AddInput(AdjointyEnum,lambday,element->GetElementType());
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(values);
-	xDelete<IssmDouble>(lambdax);
-	xDelete<IssmDouble>(lambday);
-	xDelete<int>(doflist);
-}/*}}}*/
-void AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
+void           AdjointHorizAnalysis::InputUpdateFromSolutionFS(IssmDouble* solution,Element* element){/*{{{*/
 	int          i,fe_FS;
 	int*         vdoflist=NULL;
 	int*         pdoflist=NULL;
@@ -2110,7 +2064,53 @@
 	xDelete<IssmDouble>(lambdax);
 	xDelete<IssmDouble>(values);
 }/*}}}*/
-void AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           AdjointHorizAnalysis::InputUpdateFromSolutionHoriz(IssmDouble* solution,Element* element){/*{{{*/
+	int  i;
+	int* doflist=NULL;
+
+	int    domaintype;
+	element->FindParam(&domaintype,DomainTypeEnum);
+
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+	int numdof;
+	if(domaintype!=Domain2DverticalEnum)  numdof   = numnodes*2;
+	else			                          numdof   = numnodes*1;
+	/*Fetch dof list and allocate solution vectors*/
+	element->GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	IssmDouble* values  = xNew<IssmDouble>(numdof);
+	IssmDouble* lambdax = xNew<IssmDouble>(numnodes);
+	IssmDouble* lambday = xNew<IssmDouble>(numnodes);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
+
+	/*Transform solution in Cartesian Space*/
+	if(domaintype!=Domain2DverticalEnum)	element->TransformSolutionCoord(&values[0],XYEnum);
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<numnodes;i++){
+		if(domaintype!=Domain2DverticalEnum){
+			lambdax[i]=values[i*NDOF2+0];
+			lambday[i]=values[i*NDOF2+1];
+		}
+		else {lambdax[i]=values[i];lambday[i]=0;}
+		/*Check solution*/
+		if(xIsNan<IssmDouble>(lambdax[i])) _error_("NaN found in solution vector");
+		if(domaintype!=Domain2DverticalEnum && xIsNan<IssmDouble>(lambday[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	element->AddInput(AdjointxEnum,lambdax,element->GetElementType());
+	element->AddInput(AdjointyEnum,lambday,element->GetElementType());
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(values);
+	xDelete<IssmDouble>(lambdax);
+	xDelete<IssmDouble>(lambday);
+	xDelete<int>(doflist);
+}/*}}}*/
+void           AdjointHorizAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/MeltingAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/MeltingAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MeltingAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/SmoothAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/SmoothAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/SmoothAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/LevelsetAnalysis.cpp	(revision 18930)
@@ -10,14 +10,24 @@
 #include "../modules/modules.h"
 #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;
+}
+/*}}}*/
 void LevelsetAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
 	/*Finite element type*/
@@ -59,23 +69,13 @@
 	}
 }
 /*}}}*/
-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_)
 	_error_("Not implemented yet");
@@ -403,31 +403,7 @@
 
 	return pe;
 }/*}}}*/
-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){/*{{{*/
-	_error_("Not implemented yet");
-}/*}}}*/
-void LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
-
-	int domaintype;
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			element->InputUpdateFromSolutionOneDof(solution,MaskIceLevelsetEnum);
-			break;
-		case Domain3DEnum:
-			element->InputUpdateFromSolutionOneDofCollapsed(solution,MaskIceLevelsetEnum);
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-}/*}}}*/
-void LevelsetAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	/*Default, do nothing*/
-	return;
-}/*}}}*/
-void LevelsetAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -454,7 +430,7 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void LevelsetAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -482,8 +458,52 @@
 	xDelete<IssmDouble>(dbasis);
 
 }/*}}}*/
-void LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
+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){/*{{{*/
+	_error_("Not implemented yet");
+}/*}}}*/
+void           LevelsetAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+
+	int domaintype;
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			element->InputUpdateFromSolutionOneDof(solution,MaskIceLevelsetEnum);
+			break;
+		case Domain3DEnum:
+			element->InputUpdateFromSolutionOneDofCollapsed(solution,MaskIceLevelsetEnum);
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
+	}
+}/*}}}*/
+void           LevelsetAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
+
 	/* Intermediaries */
 	int i,k;
 	IssmDouble dmaxp=0.,dmaxm=0,val=0.;
@@ -538,7 +558,7 @@
 	delete vec_dist_zerolevelset;
 	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))
 		return;
@@ -591,27 +611,7 @@
 	xDelete<IssmDouble>(xyz_list);
 	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: ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.cpp	(revision 18930)
@@ -6,51 +6,6 @@
 #include "../solutionsequences/solutionsequences.h"
 
 /*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){/*{{{*/
 
 	/*Intermediary*/
@@ -97,7 +52,52 @@
 	/*No loads*/
 
 }/*}}}*/
+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*/
 void           StressbalanceVerticalAnalysis::Core(FemModel* femmodel){/*{{{*/
 
@@ -125,47 +125,6 @@
 	return Ke;
 
 }/*}}}*/
-ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble  D,Jdet;
-	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*    B      = xNew<IssmDouble>(numnodes);
-	IssmDouble*    Bprime = 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);
-		this->GetB(B,element,xyz_list,gauss);
-		this->GetBprime(Bprime,element,xyz_list,gauss);
-		D=gauss->weight*Jdet;
-
-		TripleMultiply(B,1,numnodes,1,
-					&D,1,1,0,
-					Bprime,1,numnodes,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(Bprime);
-	xDelete<IssmDouble>(B);
-	return Ke;
-
-}/*}}}*/
 ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixSurface(Element* element){/*{{{*/
 
 
@@ -207,68 +166,57 @@
 	xDelete<IssmDouble>(basis);
 	return Ke;
 }/*}}}*/
-ElementVector* StressbalanceVerticalAnalysis::CreatePVector(Element* element){/*{{{*/
+ElementMatrix* StressbalanceVerticalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/
 
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorVolume(element);
-	ElementVector* pe2=CreatePVectorBase(element);
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	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;
+	IssmDouble  D,Jdet;
+	IssmDouble *xyz_list = NULL;
 
-	/*Fetch number of nodes for this finite element*/
+	/*Fetch number of nodes and dof for this finite element*/
 	int numnodes = element->GetNumberOfNodes();
 
-	/*Initialize Element vector and basis functions*/
-	ElementVector* pe    = element->NewElementVector();
-	IssmDouble*    basis = xNew<IssmDouble>(numnodes);
+	/*Initialize Element matrix and vectors*/
+	ElementMatrix* Ke     = element->NewElementMatrix(NoneApproximationEnum);
+	IssmDouble*    B      = xNew<IssmDouble>(numnodes);
+	IssmDouble*    Bprime = 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);
+	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);
+		this->GetB(B,element,xyz_list,gauss);
+		this->GetBprime(Bprime,element,xyz_list,gauss);
+		D=gauss->weight*Jdet;
 
-		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];
+		TripleMultiply(B,1,numnodes,1,
+					&D,1,1,0,
+					Bprime,1,numnodes,0,
+					&Ke->values[0],1);
 	}
 
 	/*Clean up and return*/
 	delete gauss;
-	xDelete<IssmDouble>(basis);
 	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(Bprime);
+	xDelete<IssmDouble>(B);
+	return Ke;
+
+}/*}}}*/
+ElementVector* StressbalanceVerticalAnalysis::CreatePVector(Element* element){/*{{{*/
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorVolume(element);
+	ElementVector* pe2=CreatePVectorBase(element);
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
 	return pe;
 }/*}}}*/
 ElementVector* StressbalanceVerticalAnalysis::CreatePVectorBase(Element* element){/*{{{*/
@@ -337,7 +285,59 @@
 	xDelete<IssmDouble>(xyz_list_base);
 	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.*/
 
@@ -356,18 +356,18 @@
 	/*Clean-up*/
 	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();
 	int          numdof=numnodes*1;
@@ -480,7 +480,7 @@
 	xDelete<IssmDouble>(xyz_list);
 	xDelete<int>(doflist);
 }/*}}}*/
-void StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           StressbalanceVerticalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,10 +25,10 @@
 		ElementMatrix* CreateJacobianMatrix(Element* element);
 		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
Index: ../trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/SeaiceAnalysis.cpp	(revision 18930)
@@ -5,14 +5,23 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Make sure we are in 2D horizontal*/
@@ -48,21 +57,12 @@
 	iomodel->FetchDataToInput(elements,MeshXEnum);
 	iomodel->FetchDataToInput(elements,MeshYEnum);
 }/*}}}*/
-void SeaiceAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	::CreateNodes(nodes,iomodel,SeaiceAnalysisEnum,P1Enum);
-
+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::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;
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           SeaiceAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -311,108 +311,9 @@
 	delete gauss;
 	return pe;
 }/*}}}*/
-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){/*{{{*/
-	_error_("Not implemented yet");
-}/*}}}*/
-void SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
+void           SeaiceAnalysis::CreateCTensor(IssmDouble* C,Element* element,Gauss* gauss){/*{{{*/
 
 	/*Intermediaries*/
-	int* doflist=NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-	int numdof   = numnodes*2;
-
-	/*Fetch dof list and allocate solution vectors*/
-	element->GetDofList(&doflist,SSAApproximationEnum,GsetEnum);
-	IssmDouble* values    = xNew<IssmDouble>(numdof);
-	IssmDouble* vx        = xNew<IssmDouble>(numnodes);
-	IssmDouble* vy        = xNew<IssmDouble>(numnodes);
-	IssmDouble* vel       = xNew<IssmDouble>(numnodes);
-
-	/*Use the dof list to index into the solution vector: */
-	for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]];
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(int i=0;i<numnodes;i++){
-		vx[i]=values[i*2+0];
-		vy[i]=values[i*2+1];
-		if(xIsNan<IssmDouble>(vx[i])) _error_("NaN found in solution vector");
-		if(xIsNan<IssmDouble>(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Compute vel*/
-	for(int i=0;i<numnodes;i++) vel[i]=sqrt(vx[i]*vx[i] + vy[i]*vy[i]);
-
-	/*Add vx and vy as inputs to the tria element: */
-	element->AddInput(VxEnum,vx,element->GetElementType());
-	element->AddInput(VyEnum,vy,element->GetElementType());
-	element->AddInput(VelEnum,vel,element->GetElementType());
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(vel);
-	xDelete<IssmDouble>(vy);
-	xDelete<IssmDouble>(vx);
-	xDelete<IssmDouble>(values);
-	xDelete<int>(doflist);
-}/*}}}*/
-void SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-
-	/*Intermediaries*/
-	IssmDouble          c_min;
-	Vector<IssmDouble>* mask        = NULL;
-	IssmDouble*         serial_mask = NULL;
-
-	/*Get minimum concentration allowed*/
-	femmodel->parameters->FindParam(&c_min,SeaiceMinConcentrationEnum);
-
-	/*Step 1: update mask of active nodes*/
-	mask=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(SeaiceAnalysisEnum));
-	for (int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-
-		/*Get current concentration of element and decide whether it is an active element*/
-		int    numnodes            = element->GetNumberOfNodes();
-		Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
-		if(concentration_input->Max()>c_min){
-			for(int in=0;in<numnodes;in++) mask->SetValue(element->nodes[in]->Sid(),1.,INS_VAL);
-		}
-	}
-
-	/*Assemble and serialize*/
-	mask->Assemble();
-	serial_mask=mask->ToMPISerial();
-	delete mask;
-
-	/*Update node activation accordingly*/
-	int counter =0;
-	for(int i=0;i<femmodel->nodes->Size();i++){
-		Node* node=xDynamicCast<Node*>(femmodel->nodes->GetObjectByOffset(i));
-		if(node->InAnalysis(SeaiceAnalysisEnum)){
-			if(serial_mask[node->Sid()]==1.){
-				node->Activate();
-				counter++;
-			}
-			else{
-				node->Deactivate();
-			}
-		}
-	}
-	xDelete<IssmDouble>(serial_mask);
-
-	/*Display number of active nodes*/
-	int sum_counter;
-	ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() );
-	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;
 
@@ -448,7 +349,7 @@
 		}
 	}
 }/*}}}*/
-void SeaiceAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -481,7 +382,7 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
-void SeaiceAnalysis::GetM(IssmDouble* M,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -506,122 +407,55 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-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.
-	 * In both cases, a maximal compressive strength is fixed at compr_max
-	 * The enveloppe is defined in N/m^2.
-	 * The coeficients of the internal stress are then multiplied by the ice thickness to be used in the vertical integrated momentiom equation.
-	 */
+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){/*{{{*/
+	_error_("Not implemented yet");
+}/*}}}*/
+void           SeaiceAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
-	/* Mohr-Coulomb criterion calculation
-	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	 *                                                                   
-	 *                            sigma_s                                
-	 *        Mohr.Coulomb branch     |                                  
-	 *                     \          |                                  
-	 *                      * |       |                                  
-	 *                        *       |   cohesion (C=cfix+calea)        
-	 *                        | *     |  /                               
-	 *                        |   *   | /    tract                       
-	 *                        |     * |/    /                            
-	 *             -comp_max  |       *    /                             
-	 *                      \ |       | * /                              
-	 *                       \|      0| | *                              
-	 *             -------------------------*------------ sigma_n        
-	 *                        |       | | *                              
-	 *                        |       | *                                
-	 *                        |       *                                  
-	 *                        |     * |                                  
-	 *                        |   *   |                                  
-	 *                        | *     |                                  
-	 *                        *       |                                  
-	 *                      * |       |                                  
-	 *                    *           |                                  
-	 *                                |                                  
-	 *                                |                                  
-	 *                                                                   
-	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-	 */
+	/*Intermediaries*/
+	int* doflist=NULL;
 
-	/*Intermediaties*/
-	IssmDouble sigma_xx,sigma_yy,sigma_xy,sigma_s,sigma_n,sigma_target;
-	IssmDouble compression_coef,traction_coef,cohesion,tan_phi;
-	IssmDouble traction,compression_max;
-	IssmDouble damage_test,damage_new,damage,tmp;
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+	int numdof   = numnodes*2;
 
-	/*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));
+	/*Fetch dof list and allocate solution vectors*/
+	element->GetDofList(&doflist,SSAApproximationEnum,GsetEnum);
+	IssmDouble* values    = xNew<IssmDouble>(numdof);
+	IssmDouble* vx        = xNew<IssmDouble>(numnodes);
+	IssmDouble* vy        = xNew<IssmDouble>(numnodes);
+	IssmDouble* vel       = xNew<IssmDouble>(numnodes);
 
-		/*Get Mohr-Coulomb parameters*/
-		compression_coef = element->GetMaterialParameter(MaterialsCompressionCoefEnum);
-		traction_coef    = element->GetMaterialParameter(MaterialsTractionCoefEnum);
-		cohesion         = element->GetMaterialParameter(MaterialsCohesionEnum); //C
-		tan_phi          = element->GetMaterialParameter(MaterialsInternalFrictionCoefEnum); //mu = tan(phi)
+	/*Use the dof list to index into the solution vector: */
+	for(int i=0;i<numdof;i++) values[i]=solution[doflist[i]];
 
-		/*Get current 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);
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(int i=0;i<numnodes;i++){
+		vx[i]=values[i*2+0];
+		vy[i]=values[i*2+1];
+		if(xIsNan<IssmDouble>(vx[i])) _error_("NaN found in solution vector");
+		if(xIsNan<IssmDouble>(vy[i])) _error_("NaN found in solution vector");
+	}
 
-		/* Compute the invariants of the elastic deformation and instantaneous deformation rate */
-		sigma_s=sqrt(pow((sigma_xx-sigma_yy)/2.,2)+pow(sigma_xy,2));
-		sigma_n=(sigma_xx+sigma_yy)/2.;
+	/*Compute vel*/
+	for(int i=0;i<numnodes;i++) vel[i]=sqrt(vx[i]*vx[i] + vy[i]*vy[i]);
 
-		/* same maximal tensile strength */
-		traction=traction_coef*cohesion/tan_phi;
-		compression_max=compression_coef*cohesion;
+	/*Add vx and vy as inputs to the tria element: */
+	element->AddInput(VxEnum,vx,element->GetElementType());
+	element->AddInput(VyEnum,vy,element->GetElementType());
+	element->AddInput(VelEnum,vel,element->GetElementType());
 
-		/* estimate the internal constraints using the current elastic deformation */
-		Input* damage_input    = element->GetInput(DamageEnum); _assert_(damage_input);
-		damage_input->GetInputAverage(&damage);
-		damage_test = damage;
-		damage_new  = damage;
-		if(sigma_n>traction || sigma_n<-compression_max){
-			if(sigma_n>traction){
-				sigma_target=traction;
-			}
-			else{
-				sigma_target=-compression_max;
-			}
-
-			tmp=1.-sigma_target/sigma_n*(1.-damage);
-			if(tmp<1. && tmp>damage_new){
-				damage_test=((damage_test>tmp)?(damage_test):(tmp)); /* max(damage_test,tmp); */
-			}
-		}
-		if(sigma_s>cohesion-sigma_n*tan_phi){
-			tmp=1.0-cohesion/(sigma_s+sigma_n*tan_phi)*(1-damage);
-			if(tmp<1. && tmp>damage_new){
-				damage_test=((damage_test>tmp)?(damage_test):(tmp)); /*max(damage_test,tmp); */
-			}
-		}
-
-		/* The damage variable is changed */
-		damage_new=damage_test;
-		element->AddInput(DamageEnum,&damage_new,P0Enum);
-
-		/* Recompute the internal stress*/
-		if(damage<1.){
-			sigma_xx = (1.-damage_new)/(1.-damage)*sigma_xx;
-			sigma_yy = (1.-damage_new)/(1.-damage)*sigma_yy;
-			sigma_xy = (1.-damage_new)/(1.-damage)*sigma_xy;
-		}
-		else{
-			sigma_xx = 0.;
-			sigma_yy = 0.;
-			sigma_xy = 0.;
-		}
-		element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
-		element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
-		element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
-	}
+	/*Free ressources:*/
+	xDelete<IssmDouble>(vel);
+	xDelete<IssmDouble>(vy);
+	xDelete<IssmDouble>(vx);
+	xDelete<IssmDouble>(values);
+	xDelete<int>(doflist);
 }/*}}}*/
-void SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
+void           SeaiceAnalysis::PostProcess(FemModel* femmodel){/*{{{*/
 
 	/*Intermediaties*/
 	IssmDouble *xyz_list = NULL;
@@ -769,3 +603,167 @@
 	}
 
 }/*}}}*/
+void           SeaiceAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+
+	/*Intermediaries*/
+	IssmDouble          c_min;
+	Vector<IssmDouble>* mask        = NULL;
+	IssmDouble*         serial_mask = NULL;
+
+	/*Get minimum concentration allowed*/
+	femmodel->parameters->FindParam(&c_min,SeaiceMinConcentrationEnum);
+
+	/*Step 1: update mask of active nodes*/
+	mask=new Vector<IssmDouble>(femmodel->nodes->NumberOfNodes(SeaiceAnalysisEnum));
+	for (int i=0;i<femmodel->elements->Size();i++){
+		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+
+		/*Get current concentration of element and decide whether it is an active element*/
+		int    numnodes            = element->GetNumberOfNodes();
+		Input* concentration_input = element->GetInput(SeaiceConcentrationEnum); _assert_(concentration_input);
+		if(concentration_input->Max()>c_min){
+			for(int in=0;in<numnodes;in++) mask->SetValue(element->nodes[in]->Sid(),1.,INS_VAL);
+		}
+	}
+
+	/*Assemble and serialize*/
+	mask->Assemble();
+	serial_mask=mask->ToMPISerial();
+	delete mask;
+
+	/*Update node activation accordingly*/
+	int counter =0;
+	for(int i=0;i<femmodel->nodes->Size();i++){
+		Node* node=xDynamicCast<Node*>(femmodel->nodes->GetObjectByOffset(i));
+		if(node->InAnalysis(SeaiceAnalysisEnum)){
+			if(serial_mask[node->Sid()]==1.){
+				node->Activate();
+				counter++;
+			}
+			else{
+				node->Deactivate();
+			}
+		}
+	}
+	xDelete<IssmDouble>(serial_mask);
+
+	/*Display number of active nodes*/
+	int sum_counter;
+	ISSM_MPI_Reduce(&counter,&sum_counter,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() );
+	if(VerboseSolution()) _printf0_("   Number of active nodes: "<< sum_counter <<"\n");
+}/*}}}*/
+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.
+	 * In both cases, a maximal compressive strength is fixed at compr_max
+	 * The enveloppe is defined in N/m^2.
+	 * The coeficients of the internal stress are then multiplied by the ice thickness to be used in the vertical integrated momentiom equation.
+	 */
+
+	/* Mohr-Coulomb criterion calculation
+	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+	 *                                                                   
+	 *                            sigma_s                                
+	 *        Mohr.Coulomb branch     |                                  
+	 *                     \          |                                  
+	 *                      * |       |                                  
+	 *                        *       |   cohesion (C=cfix+calea)        
+	 *                        | *     |  /                               
+	 *                        |   *   | /    tract                       
+	 *                        |     * |/    /                            
+	 *             -comp_max  |       *    /                             
+	 *                      \ |       | * /                              
+	 *                       \|      0| | *                              
+	 *             -------------------------*------------ sigma_n        
+	 *                        |       | | *                              
+	 *                        |       | *                                
+	 *                        |       *                                  
+	 *                        |     * |                                  
+	 *                        |   *   |                                  
+	 *                        | *     |                                  
+	 *                        *       |                                  
+	 *                      * |       |                                  
+	 *                    *           |                                  
+	 *                                |                                  
+	 *                                |                                  
+	 *                                                                   
+	 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+	 */
+
+	/*Intermediaties*/
+	IssmDouble sigma_xx,sigma_yy,sigma_xy,sigma_s,sigma_n,sigma_target;
+	IssmDouble compression_coef,traction_coef,cohesion,tan_phi;
+	IssmDouble traction,compression_max;
+	IssmDouble damage_test,damage_new,damage,tmp;
+
+	/*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 Mohr-Coulomb parameters*/
+		compression_coef = element->GetMaterialParameter(MaterialsCompressionCoefEnum);
+		traction_coef    = element->GetMaterialParameter(MaterialsTractionCoefEnum);
+		cohesion         = element->GetMaterialParameter(MaterialsCohesionEnum); //C
+		tan_phi          = element->GetMaterialParameter(MaterialsInternalFrictionCoefEnum); //mu = tan(phi)
+
+		/*Get current 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);
+
+		/* Compute the invariants of the elastic deformation and instantaneous deformation rate */
+		sigma_s=sqrt(pow((sigma_xx-sigma_yy)/2.,2)+pow(sigma_xy,2));
+		sigma_n=(sigma_xx+sigma_yy)/2.;
+
+		/* same maximal tensile strength */
+		traction=traction_coef*cohesion/tan_phi;
+		compression_max=compression_coef*cohesion;
+
+		/* estimate the internal constraints using the current elastic deformation */
+		Input* damage_input    = element->GetInput(DamageEnum); _assert_(damage_input);
+		damage_input->GetInputAverage(&damage);
+		damage_test = damage;
+		damage_new  = damage;
+		if(sigma_n>traction || sigma_n<-compression_max){
+			if(sigma_n>traction){
+				sigma_target=traction;
+			}
+			else{
+				sigma_target=-compression_max;
+			}
+
+			tmp=1.-sigma_target/sigma_n*(1.-damage);
+			if(tmp<1. && tmp>damage_new){
+				damage_test=((damage_test>tmp)?(damage_test):(tmp)); /* max(damage_test,tmp); */
+			}
+		}
+		if(sigma_s>cohesion-sigma_n*tan_phi){
+			tmp=1.0-cohesion/(sigma_s+sigma_n*tan_phi)*(1-damage);
+			if(tmp<1. && tmp>damage_new){
+				damage_test=((damage_test>tmp)?(damage_test):(tmp)); /*max(damage_test,tmp); */
+			}
+		}
+
+		/* The damage variable is changed */
+		damage_new=damage_test;
+		element->AddInput(DamageEnum,&damage_new,P0Enum);
+
+		/* Recompute the internal stress*/
+		if(damage<1.){
+			sigma_xx = (1.-damage_new)/(1.-damage)*sigma_xx;
+			sigma_yy = (1.-damage_new)/(1.-damage)*sigma_yy;
+			sigma_xy = (1.-damage_new)/(1.-damage)*sigma_xy;
+		}
+		else{
+			sigma_xx = 0.;
+			sigma_yy = 0.;
+			sigma_xy = 0.;
+		}
+		element->AddInput(StressTensorxxEnum,&sigma_xx,P0Enum);
+		element->AddInput(StressTensoryyEnum,&sigma_yy,P0Enum);
+		element->AddInput(StressTensorxyEnum,&sigma_xy,P0Enum);
+	}
+}/*}}}*/
Index: ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.h	(revision 18930)
@@ -13,52 +13,47 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*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: ../trunk-jpl/src/c/analyses/MeltingAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/MeltingAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MeltingAnalysis.cpp	(revision 18930)
@@ -5,11 +5,37 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	int frictionlaw;
@@ -38,35 +64,9 @@
 	}
 	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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-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);
-
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           MeltingAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -125,16 +125,16 @@
 ElementVector* MeltingAnalysis::CreatePVector(Element* element){/*{{{*/
 	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: ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.h	(revision 18930)
@@ -12,27 +12,25 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*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: ../trunk-jpl/src/c/analyses/SmoothAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/SmoothAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/SmoothAnalysis.cpp	(revision 18930)
@@ -5,11 +5,18 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Update elements: */
@@ -22,15 +29,8 @@
 		}
 	}
 }/*}}}*/
-void SmoothAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	::CreateNodes(nodes,iomodel,SmoothAnalysisEnum,P1Enum);
-
+void SmoothAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-void SmoothAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-}/*}}}*/
-void SmoothAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-}/*}}}*/
 
 /*Finite Element Analysis*/
 void           SmoothAnalysis::Core(FemModel* femmodel){/*{{{*/
@@ -204,13 +204,13 @@
 	delete gauss;
 	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;
 
 	element->FindParam(&inputenum,InputToSmoothEnum);
@@ -222,7 +222,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           SmoothAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointHorizAnalysis.h	(revision 18930)
@@ -12,47 +12,47 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
 		ElementVector* CreateDVector(Element* element);
 		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: ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.cpp	(revision 18930)
@@ -5,22 +5,22 @@
 #include "../modules/modules.h"
 
 /*Model processor*/
-int  AdjointBalancethicknessAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+void AdjointBalancethicknessAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
 void AdjointBalancethicknessAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+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::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void AdjointBalancethicknessAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
 
@@ -146,10 +146,10 @@
 	delete gauss;
 	return pe;
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+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::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/*The gradient of the cost function is calculated in 2 parts.
 	 *
 	 * dJ    \partial J   \partial lambda^T(KU-F)
@@ -195,8 +195,32 @@
 	xDelete<int>(responses);
 
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJVx(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*/
+	int numvertices = element->GetNumberOfVertices();
+
+	/*Initialize some vectors*/
+	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
+	IssmDouble* lambda        = xNew<IssmDouble>(numvertices);
+	int*        vertexpidlist = xNew<int>(numvertices);
+
+	/*Retrieve all inputs we will be needing: */
+	element->GradientIndexing(&vertexpidlist[0],control_index);
+	element->GetInputListOnVertices(lambda,AdjointEnum);
+	for(int i=0;i<numvertices;i++){
+		ge[i]=-lambda[i];
+		_assert_(!xIsNan<IssmDouble>(ge[i]));
+	}
+	gradient->SetValues(numvertices,vertexpidlist,ge,INS_VAL);
+
+	/*Clean up and return*/
+	xDelete<IssmDouble>(ge);
+	xDelete<IssmDouble>(lambda);
+	xDelete<int>(vertexpidlist);
+}/*}}}*/
+void           AdjointBalancethicknessAnalysis::GradientJVx(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+
 	/*Intermediaries*/
 	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
 	IssmDouble *xyz_list= NULL;
@@ -242,7 +266,7 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethicknessAnalysis::GradientJVy(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
 	IssmDouble thickness,Jdet,Dlambda[3],dp[3];
@@ -289,32 +313,8 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::GradientJDhDt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
-	/*Fetch number of vertices for this finite element*/
-	int numvertices = element->GetNumberOfVertices();
-
-	/*Initialize some vectors*/
-	IssmDouble* ge            = xNewZeroInit<IssmDouble>(numvertices);
-	IssmDouble* lambda        = xNew<IssmDouble>(numvertices);
-	int*        vertexpidlist = xNew<int>(numvertices);
-
-	/*Retrieve all inputs we will be needing: */
-	element->GradientIndexing(&vertexpidlist[0],control_index);
-	element->GetInputListOnVertices(lambda,AdjointEnum);
-	for(int i=0;i<numvertices;i++){
-		ge[i]=-lambda[i];
-		_assert_(!xIsNan<IssmDouble>(ge[i]));
-	}
-	gradient->SetValues(numvertices,vertexpidlist,ge,INS_VAL);
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(ge);
-	xDelete<IssmDouble>(lambda);
-	xDelete<int>(vertexpidlist);
-}/*}}}*/
-void AdjointBalancethicknessAnalysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
-
 	int domaintype;
 	element->FindParam(&domaintype,DomainTypeEnum);
 	switch(domaintype){
@@ -327,7 +327,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           AdjointBalancethicknessAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/L2ProjectionEPLAnalysis.cpp	(revision 18930)
@@ -5,11 +5,37 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	bool   isefficientlayer;
@@ -40,35 +66,9 @@
 		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
 	}
 }/*}}}*/
-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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-void L2ProjectionEPLAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-	/*No constraints*/
-}/*}}}*/
-void L2ProjectionEPLAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads*/
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           L2ProjectionEPLAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -225,13 +225,13 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 	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;
 
 	element->FindParam(&inputenum,InputToL2ProjectEnum);
@@ -249,7 +249,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           L2ProjectionEPLAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MasstransportAnalysis.cpp	(revision 18930)
@@ -5,27 +5,116 @@
 #include "../modules/modules.h"
 
 /*Model processing*/
-int  MasstransportAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
+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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void MasstransportAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
+	/*Intermediaries*/
+	int element;
+	int penpair_ids[2];
+	int count=0;
+	int stabilization;
+	int numvertex_pairing;
 
-	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));
+	/*Fetch parameters: */
+	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
 
-	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);
+	/*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::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
 	int    stabilization,finiteelement,smb_model;
@@ -125,114 +214,25 @@
 	}
 
 }/*}}}*/
-void MasstransportAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void MasstransportAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	/*Fetch parameters: */
-	int  stabilization;
-	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
 
-	/*Check in 3d*/
-	if(stabilization==3 && iomodel->domaintype==Domain3DEnum) _error_("DG 3d not implemented yet");
+	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));
 
-	/*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){/*{{{*/
+	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);
 
-	/*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);
-
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           MasstransportAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -624,7 +624,7 @@
 	delete gauss;
 	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
 	 * by: 
@@ -652,7 +652,7 @@
 	/*Clean-up*/
 	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
 	 * by: 
@@ -681,13 +681,13 @@
 	xDelete<IssmDouble>(dbasis);
 
 }/*}}}*/
-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;
 	int*       doflist=NULL;
@@ -771,7 +771,7 @@
 	xDelete<int>(doflist);
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 }/*}}}*/
-void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
 	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
@@ -782,51 +782,59 @@
 }/*}}}*/
 
 /*Flux Correction Transport*/
-void           MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/
+ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
 
-	/*Intermediaries*/
-	int  configuration_type;
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
 
-	/*Initialize Lumped mass matrix (actually we just save its diagonal)*/
-	femmodel->parameters->FindParam(&configuration_type,ConfigurationTypeEnum);
-	int fsize      = femmodel->nodes->NumberOfDofs(configuration_type,FsetEnum);
-	int flocalsize = femmodel->nodes->NumberOfDofsLocal(configuration_type,FsetEnum);
-	Vector<IssmDouble>* Mlff = new Vector<IssmDouble>(flocalsize,fsize);
+	/*Intermediaries */
+	IssmDouble Jdet;
+	IssmDouble vx,vy;
+	IssmDouble* xyz_list = NULL;
 
-	/*Create and assemble matrix*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ElementMatrix* MLe     = this->CreateMassMatrix(element);
-		if(MLe){
-			MLe->Lump();
-			MLe->AddDiagonalToGlobal(Mlff);
-		}
-		delete MLe;
-	}
-	Mlff->Assemble();
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
+	int dim      = 2;
 
-	/*Assign output pointer*/
-	*pMlff=Mlff;
-}/*}}}*/
-void           MasstransportAnalysis::MassMatrix(Matrix<IssmDouble>** pMff,FemModel* femmodel){/*{{{*/
+	/*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);
 
-	/*Initialize Mass matrix*/
-	Matrix<IssmDouble> *Mff = NULL;
-	AllocateSystemMatricesx(&Mff,NULL,NULL,NULL,femmodel);
+	/*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);
 
-	/*Create and assemble matrix*/
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ElementMatrix* MLe     = this->CreateMassMatrix(element);
-		if(MLe){
-			MLe->AddToGlobal(Mff);
-		}
-		delete MLe;
+	/* 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);
+
 	}
-	Mff->Assemble();
 
-	/*Assign output pointer*/
-	*pMff=Mff;
+	/*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){/*{{{*/
 
@@ -896,57 +904,49 @@
 		delete Kfs;
 	}
 }/*}}}*/
-ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/
+void           MasstransportAnalysis::LumpedMassMatrix(Vector<IssmDouble>** pMlff,FemModel* femmodel){/*{{{*/
 
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
+	/*Intermediaries*/
+	int  configuration_type;
 
-	/*Intermediaries */
-	IssmDouble Jdet;
-	IssmDouble vx,vy;
-	IssmDouble* xyz_list = NULL;
+	/*Initialize Lumped mass matrix (actually we just save its diagonal)*/
+	femmodel->parameters->FindParam(&configuration_type,ConfigurationTypeEnum);
+	int fsize      = femmodel->nodes->NumberOfDofs(configuration_type,FsetEnum);
+	int flocalsize = femmodel->nodes->NumberOfDofsLocal(configuration_type,FsetEnum);
+	Vector<IssmDouble>* Mlff = new Vector<IssmDouble>(flocalsize,fsize);
 
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-	int dim      = 2;
+	/*Create and assemble matrix*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		ElementMatrix* MLe     = this->CreateMassMatrix(element);
+		if(MLe){
+			MLe->Lump();
+			MLe->AddDiagonalToGlobal(Mlff);
+		}
+		delete MLe;
+	}
+	Mlff->Assemble();
 
-	/*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);
+	/*Assign output pointer*/
+	*pMlff=Mlff;
+}/*}}}*/
+void           MasstransportAnalysis::MassMatrix(Matrix<IssmDouble>** pMff,FemModel* femmodel){/*{{{*/
 
-	/*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);
+	/*Initialize Mass matrix*/
+	Matrix<IssmDouble> *Mff = NULL;
+	AllocateSystemMatricesx(&Mff,NULL,NULL,NULL,femmodel);
 
-	/* 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);
-
+	/*Create and assemble matrix*/
+	for(int i=0;i<femmodel->elements->Size();i++){
+		Element*       element = xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		ElementMatrix* MLe     = this->CreateMassMatrix(element);
+		if(MLe){
+			MLe->AddToGlobal(Mff);
+		}
+		delete MLe;
 	}
+	Mff->Assemble();
 
-	/*Clean up and return*/
-	xDelete<IssmDouble>(xyz_list);
-	xDelete<IssmDouble>(B);
-	xDelete<IssmDouble>(Bprime);
-	xDelete<IssmDouble>(D);
-	delete gauss;
-	return Ke;
+	/*Assign output pointer*/
+	*pMff=Mff;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 	
 public:
 	/*Model processing*/
+	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);
-	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);
 
 	/*Finite element Analysis*/
 	void           Core(FemModel* femmodel);
@@ -25,18 +25,16 @@
 	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);
-	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: ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.cpp	(revision 18930)
@@ -5,22 +5,22 @@
 #include "../modules/modules.h"
 
 /*Model processor*/
-int  AdjointBalancethickness2Analysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
-}/*}}}*/
-void AdjointBalancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void AdjointBalancethickness2Analysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
+void AdjointBalancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
 void AdjointBalancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
-void AdjointBalancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+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::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void AdjointBalancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 	_error_("not implemented yet");
 }/*}}}*/
 
@@ -105,10 +105,10 @@
 	return pe;
 
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+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::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
 	/*The gradient of the cost function is calculated in 2 parts.
 	 *
 	 * dJ    \partial J   \partial lambda^T(KU-F)
@@ -145,10 +145,10 @@
 	xDelete<int>(responses);
 
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
-	IssmDouble dlambda[2],ds[2],D0,omega,Jdet; 
+	IssmDouble lambda,Jdet; 
 	IssmDouble *xyz_list= NULL;
 
 	/*Fetch number of vertices for this finite element*/
@@ -163,9 +163,6 @@
 	element->GetVerticesCoordinates(&xyz_list);
 	element->GradientIndexing(&vertexpidlist[0],control_index);
 	Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
-	Input* s_input       = element->GetInput(SurfaceEnum);            _assert_(s_input);
-	Input* D0_input      = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
-	Input* omega_input   = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
 
 	Gauss* gauss=element->NewGauss(2);
 	for(int ig=gauss->begin();ig<gauss->end();ig++){
@@ -174,14 +171,11 @@
 		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		element->NodalFunctionsP1(basis,gauss);
 
-		D0_input->GetInputValue(&D0,gauss);
-		omega_input->GetInputValue(&omega,gauss);
-		adjoint_input->GetInputDerivativeValue(&dlambda[0],xyz_list,gauss);
-		s_input->GetInputDerivativeValue(&ds[0],xyz_list,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]*exp(omega)*D0*(ds[0]*dlambda[0] + ds[1]*dlambda[1]);
+			ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
 			_assert_(!xIsNan<IssmDouble>(ge[i]));
 		}
 	}
@@ -194,10 +188,10 @@
 	xDelete<int>(vertexpidlist);
 	delete gauss;
 }/*}}}*/
-void AdjointBalancethickness2Analysis::GradientJdHdt(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
+void           AdjointBalancethickness2Analysis::GradientJOmega(Element* element,Vector<IssmDouble>* gradient,int control_index){/*{{{*/
 
 	/*Intermediaries*/
-	IssmDouble lambda,Jdet; 
+	IssmDouble dlambda[2],ds[2],D0,omega,Jdet; 
 	IssmDouble *xyz_list= NULL;
 
 	/*Fetch number of vertices for this finite element*/
@@ -212,6 +206,9 @@
 	element->GetVerticesCoordinates(&xyz_list);
 	element->GradientIndexing(&vertexpidlist[0],control_index);
 	Input* adjoint_input = element->GetInput(AdjointEnum);            _assert_(adjoint_input);
+	Input* s_input       = element->GetInput(SurfaceEnum);            _assert_(s_input);
+	Input* D0_input      = element->GetInput(BalancethicknessD0Enum); _assert_(D0_input);
+	Input* omega_input   = element->GetInput(BalancethicknessOmegaEnum); _assert_(omega_input);
 
 	Gauss* gauss=element->NewGauss(2);
 	for(int ig=gauss->begin();ig<gauss->end();ig++){
@@ -220,11 +217,14 @@
 		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
 		element->NodalFunctionsP1(basis,gauss);
 
-		adjoint_input->GetInputValue(&lambda,gauss);
+		D0_input->GetInputValue(&D0,gauss);
+		omega_input->GetInputValue(&omega,gauss);
+		adjoint_input->GetInputDerivativeValue(&dlambda[0],xyz_list,gauss);
+		s_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
 
 		/*Build gradient vector (actually -dJ/da): */
 		for(int i=0;i<numvertices;i++){
-			ge[i]+= -Jdet*gauss->weight*basis[i]*lambda;
+			ge[i]+= -Jdet*gauss->weight*basis[i]*exp(omega)*D0*(ds[0]*dlambda[0] + ds[1]*dlambda[1]);
 			_assert_(!xIsNan<IssmDouble>(ge[i]));
 		}
 	}
@@ -237,10 +237,10 @@
 	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: ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/HydrologyShreveAnalysis.cpp	(revision 18930)
@@ -5,22 +5,36 @@
 #include "../modules/modules.h"
 
 /*Model processing*/
-int  HydrologyShreveAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
+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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void HydrologyShreveAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	/*No loads*/
+}/*}}}*/
+void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 
-	/*retrieve some parameters: */
+	/*Fetch 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));
-
+	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::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
 	/*Fetch data needed: */
@@ -54,33 +68,19 @@
 
 	elements->InputDuplicate(WatercolumnEnum,WaterColumnOldEnum);
 }/*}}}*/
-void HydrologyShreveAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void HydrologyShreveAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	/*Fetch parameters: */
+	/*retrieve some 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);
-}/*}}}*/
-void HydrologyShreveAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	parameters->AddObject(new IntParam(HydrologyModelEnum,hydrology_model));
+	parameters->AddObject(iomodel->CopyConstantObject(HydrologyshreveStabilizationEnum));
 
-	/*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*/
-}/*}}}*/
 
 /*Finite Element Analysis*/
 void           HydrologyShreveAnalysis::Core(FemModel* femmodel){/*{{{*/
@@ -90,6 +90,50 @@
 	/*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){/*{{{*/
 _error_("Not implemented");
 }/*}}}*/
@@ -233,7 +277,7 @@
 	delete gauss;
 	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
 	 * by: 
@@ -260,7 +304,7 @@
 	/*Clean-up*/
 	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
 	 * by: 
@@ -288,13 +332,13 @@
 	xDelete<IssmDouble>(dbasis);
 
 }/*}}}*/
-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*/
 	int* doflist = NULL;
@@ -320,59 +364,12 @@
 	xDelete<IssmDouble>(values);
 	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);
-}/*}}}*/
-
-
-
 /*Needed changes to switch to the Johnson formulation*//*{{{*/
 /*All the changes are to be done in the velocity computation.
 	The new velocity needs some new parameter that should be introduce in the hydrologyshreve class:
Index: ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.cpp	(revision 18930)
@@ -5,11 +5,26 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Update elements: */
@@ -37,24 +52,9 @@
 		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
 	}
 }/*}}}*/
-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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-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*/
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           BalancevelocityAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -237,13 +237,13 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 	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;
 	element->FindParam(&domaintype,DomainTypeEnum);
@@ -257,7 +257,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           BalancevelocityAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/L2ProjectionBaseAnalysis.cpp	(revision 18930)
@@ -5,11 +5,28 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Update elements: */
@@ -30,26 +47,9 @@
 		iomodel->FetchDataToInput(elements,MeshVertexonsurfaceEnum);
 	}
 }/*}}}*/
-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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-void L2ProjectionBaseAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-	/*No constraints*/
-}/*}}}*/
-void L2ProjectionBaseAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads*/
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           L2ProjectionBaseAnalysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented");
@@ -195,13 +195,13 @@
 	if(domaintype!=Domain2DhorizontalEnum){basalelement->DeleteMaterials(); delete basalelement;};
 	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;
 
@@ -224,7 +224,7 @@
 		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
 }/*}}}*/
-void L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           L2ProjectionBaseAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointBalancethicknessAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,12 +25,12 @@
 		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 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: ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/LsfReinitializationAnalysis.cpp	(revision 18930)
@@ -9,12 +9,21 @@
 #include "../modules/GetVectorFromInputsx/GetVectorFromInputsx.h"
 
 /*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){/*{{{*/
 	int    finiteelement;
 
@@ -33,21 +42,12 @@
 
 	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: */
 	bool save_results;
@@ -248,62 +248,7 @@
 	xDelete<IssmDouble>(normal);
 	return pe;
 	}/*}}}*/
-void LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
-
-	IssmDouble   lsf;
-	int          dim;
-	int*         doflist = NULL;
-
-	/*Get some parameters*/
-	element->FindParam(&dim,DomainDimensionEnum);
-
-	/*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);
-
-	/*Get inputs*/
-	Input* lsf_input=element->GetInput(MaskIceLevelsetEnum); _assert_(lsf_input);
-
-	Gauss* gauss=element->NewGauss();
-	for(int i=0;i<numnodes;i++){
-		gauss->GaussNode(element->FiniteElement(),i);
-
-		lsf_input->GetInputValue(&lsf,gauss);
-		values[i]=lsf;
-	}
-
-	solution->SetValues(numnodes,doflist,values,INS_VAL);
-
-	/*Free ressources:*/
-	delete gauss;
-	xDelete<IssmDouble>(values);
-	xDelete<int>(doflist);
-
-}/*}}}*/
-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){/*{{{*/
-
-	int domaintype;
-	element->FindParam(&domaintype,DomainTypeEnum);
-	switch(domaintype){
-		case Domain2DhorizontalEnum:
-			element->InputUpdateFromSolutionOneDof(solution,MaskIceLevelsetEnum);
-			break;
-		case Domain3DEnum:
-			element->InputUpdateFromSolutionOneDofCollapsed(solution,MaskIceLevelsetEnum);
-			break;
-		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
-	}
-}/*}}}*/
-void LsfReinitializationAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
-	/* Do nothing for now */
-}/*}}}*/
-void LsfReinitializationAnalysis::GetB(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -330,7 +275,7 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void LsfReinitializationAnalysis::GetBprime(IssmDouble* Bprime,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -358,47 +303,109 @@
 	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;
 
-/* Other */
-void LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
+	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.);
 
-	int i,k, numnodes;
-	Element* element;
-	Node* node;
+	return fabs(a[0]*b[1]-a[1]*b[0])/norm_b;
+}/*}}}*/
+void           LsfReinitializationAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 
-	/* deactivate all spcs */
-	for(i=0;i<femmodel->elements->Size();i++){
-		element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		for(k=0;k<element->GetNumberOfNodes();k++){
-			node=element->GetNode(k);
-			if(node->IsActive()){
-				node->DofInFSet(0); 
-			}
-		}
+	IssmDouble   lsf;
+	int          dim;
+	int*         doflist = NULL;
+
+	/*Get some parameters*/
+	element->FindParam(&dim,DomainDimensionEnum);
+
+	/*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);
+
+	/*Get inputs*/
+	Input* lsf_input=element->GetInput(MaskIceLevelsetEnum); _assert_(lsf_input);
+
+	Gauss* gauss=element->NewGauss();
+	for(int i=0;i<numnodes;i++){
+		gauss->GaussNode(element->FiniteElement(),i);
+
+		lsf_input->GetInputValue(&lsf,gauss);
+		values[i]=lsf;
 	}
 
-	SetDistanceOnIntersectedElements(femmodel);
+	solution->SetValues(numnodes,doflist,values,INS_VAL);
 
-	/* reactivate spcs 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)){
-			/*iterate over nodes and set spc */
-			numnodes=element->GetNumberOfNodes();
-			IssmDouble* lsf = xNew<IssmDouble>(numnodes);
-			element->GetInputListOnNodes(&lsf[0],MaskIceLevelsetEnum);
-			for(k=0;k<numnodes;k++){
-				node=element->GetNode(k);
-				if(node->IsActive()){
-					node->ApplyConstraint(0,lsf[k]);
-				}
-			}
-			xDelete<IssmDouble>(lsf);
-		}
+	/*Free ressources:*/
+	delete gauss;
+	xDelete<IssmDouble>(values);
+	xDelete<int>(doflist);
+
+}/*}}}*/
+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){/*{{{*/
+
+	int domaintype;
+	element->FindParam(&domaintype,DomainTypeEnum);
+	switch(domaintype){
+		case Domain2DhorizontalEnum:
+			element->InputUpdateFromSolutionOneDof(solution,MaskIceLevelsetEnum);
+			break;
+		case Domain3DEnum:
+			element->InputUpdateFromSolutionOneDofCollapsed(solution,MaskIceLevelsetEnum);
+			break;
+		default: _error_("mesh "<<EnumToStringx(domaintype)<<" not supported yet");
 	}
+}/*}}}*/
+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){/*{{{*/
+void           LsfReinitializationAnalysis::SetDistanceOnIntersectedElements(FemModel* femmodel){/*{{{*/
 
 	/* Intermediaries */
 	int i;
@@ -450,7 +457,7 @@
 	delete dist_zerolevelset;
 
 }/*}}}*/
-void LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
+void           LsfReinitializationAnalysis::SetDistanceToZeroLevelsetElement(Vector<IssmDouble>* vec_signed_dist, Element* element){/*{{{*/
 
 	if(!element->IsZeroLevelset(MaskIceLevelsetEnum))
 		return;
@@ -509,53 +516,44 @@
 	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;
+void           LsfReinitializationAnalysis::SetReinitSPCs(FemModel* femmodel){/*{{{*/
 
-	for(i=0;i<dim;i++){
-		a[i]=q[i]-s0[i];
-		b[i]=s1[i]-s0[i];
+	int i,k, numnodes;
+	Element* element;
+	Node* node;
+
+	/* deactivate all spcs */
+	for(i=0;i<femmodel->elements->Size();i++){
+		element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
+		for(k=0;k<element->GetNumberOfNodes();k++){
+			node=element->GetNode(k);
+			if(node->IsActive()){
+				node->DofInFSet(0); 
+			}
+		}
 	}
-	
-	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){/*{{{*/
+	SetDistanceOnIntersectedElements(femmodel);
 
-	/*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");
+	/* reactivate spcs 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)){
+			/*iterate over nodes and set spc */
+			numnodes=element->GetNumberOfNodes();
+			IssmDouble* lsf = xNew<IssmDouble>(numnodes);
+			element->GetInputListOnNodes(&lsf[0],MaskIceLevelsetEnum);
+			for(k=0;k<numnodes;k++){
+				node=element->GetNode(k);
+				if(node->IsActive()){
+					node->ApplyConstraint(0,lsf[k]);
+				}
+			}
+			xDelete<IssmDouble>(lsf);
+		}
 	}
-	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: ../trunk-jpl/src/c/analyses/MasstransportAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/MasstransportAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MasstransportAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -29,18 +29,18 @@
 		ElementVector* CreatePVector(Element* element);
 		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: ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/StressbalanceSIAAnalysis.cpp	(revision 18930)
@@ -6,49 +6,61 @@
 #include "../solutionsequences/solutionsequences.h"
 
 /*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){/*{{{*/
+void StressbalanceSIAAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-	/*No specific parameters*/
+	/*Intermediary*/
+	int        count;
+	IssmDouble yts;
+	bool       isSIA;
 
-}/*}}}*/
-void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
-
-	/*Fetch data needed: */
-	bool   isSIA;
-	bool   islevelset;
+	/*Fetch parameters: */
+	iomodel->Constant(&yts,ConstantsYtsEnum);
 	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
-	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
 
-	/*Now, is the flag SIA on? otherwise, do nothing: */
-	if (!isSIA)return;
+	/*Now, is the flag isSIA on? otherwise, do nothing: */
+	if (!isSIA) return;
 
-	iomodel->FetchData(1,FlowequationElementEquationEnum);
+	/*Fetch data: */
+	iomodel->FetchData(3,StressbalanceSpcvxEnum,StressbalanceSpcvyEnum,FlowequationVertexEquationEnum);
 
-	/*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++;
+	/*Initialize conunter*/
+	count=0;
+
+	/*vx and vy are spc'd if we are not on nodeonSIA: */
+	for(int i=0;i<iomodel->numberofvertices;i++){
+		/*keep only this partition's nodes:*/
+		if((iomodel->my_vertices[i])){
+			if (reCast<int,IssmDouble>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
+
+				constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,0,StressbalanceSIAAnalysisEnum));
+				count++;
+
+				constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,1,0,StressbalanceSIAAnalysisEnum));
+				count++;
+			}
+			else{
+				if (!xIsNan<IssmDouble>(iomodel->Data(StressbalanceSpcvxEnum)[i])){
+					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,iomodel->Data(StressbalanceSpcvxEnum)[i]/yts,StressbalanceSIAAnalysisEnum)); //add count'th spc, on node i+1, setting dof 1 to vx.
+					count++;
+				}
+
+				if (!xIsNan<IssmDouble>(iomodel->Data(StressbalanceSpcvyEnum)[i])){
+					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,1,iomodel->Data(StressbalanceSpcvyEnum)[i]/yts,StressbalanceSIAAnalysisEnum)); //add count'th spc, on node i+1, setting dof 2 to vy
+					count++;
+				}
+			}
 		}
 	}
 
-	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(3,StressbalanceSpcvxEnum,StressbalanceSpcvyEnum,FlowequationVertexEquationEnum);
 
-	/*Free data: */
-	iomodel->DeleteData(1,FlowequationElementEquationEnum);
 }/*}}}*/
+void StressbalanceSIAAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+
+	/*No loads*/
+
+}/*}}}*/
 void StressbalanceSIAAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 
 	/*Intermediaries*/
@@ -88,59 +100,47 @@
 				FlowequationVertexEquationEnum,StressbalanceReferentialEnum);
 
 }/*}}}*/
-void StressbalanceSIAAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+int  StressbalanceSIAAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
+	return 2;
+}/*}}}*/
+void StressbalanceSIAAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
-	/*Intermediary*/
-	int        count;
-	IssmDouble yts;
-	bool       isSIA;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&yts,ConstantsYtsEnum);
+	/*Fetch data needed: */
+	bool   isSIA;
+	bool   islevelset;
 	iomodel->Constant(&isSIA,FlowequationIsSIAEnum);
+	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
 
-	/*Now, is the flag isSIA on? otherwise, do nothing: */
-	if (!isSIA) return;
+	/*Now, is the flag SIA on? otherwise, do nothing: */
+	if (!isSIA)return;
 
-	/*Fetch data: */
-	iomodel->FetchData(3,StressbalanceSpcvxEnum,StressbalanceSpcvyEnum,FlowequationVertexEquationEnum);
+	iomodel->FetchData(1,FlowequationElementEquationEnum);
 
-	/*Initialize conunter*/
-	count=0;
-
-	/*vx and vy are spc'd if we are not on nodeonSIA: */
-	for(int i=0;i<iomodel->numberofvertices;i++){
-		/*keep only this partition's nodes:*/
-		if((iomodel->my_vertices[i])){
-			if (reCast<int,IssmDouble>(iomodel->Data(FlowequationVertexEquationEnum)[i])!=SIAApproximationEnum){
-
-				constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,0,StressbalanceSIAAnalysisEnum));
-				count++;
-
-				constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,1,0,StressbalanceSIAAnalysisEnum));
-				count++;
-			}
-			else{
-				if (!xIsNan<IssmDouble>(iomodel->Data(StressbalanceSpcvxEnum)[i])){
-					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,iomodel->Data(StressbalanceSpcvxEnum)[i]/yts,StressbalanceSIAAnalysisEnum)); //add count'th spc, on node i+1, setting dof 1 to vx.
-					count++;
-				}
-
-				if (!xIsNan<IssmDouble>(iomodel->Data(StressbalanceSpcvyEnum)[i])){
-					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,1,iomodel->Data(StressbalanceSpcvyEnum)[i]/yts,StressbalanceSIAAnalysisEnum)); //add count'th spc, on node i+1, setting dof 2 to vy
-					count++;
-				}
-			}
+	/*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(3,StressbalanceSpcvxEnum,StressbalanceSpcvyEnum,FlowequationVertexEquationEnum);
-
+	iomodel->DeleteData(1,FlowequationElementEquationEnum);
 }/*}}}*/
-void StressbalanceSIAAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+void StressbalanceSIAAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	/*No loads*/
+	/*No specific parameters*/
 
 }/*}}}*/
 
@@ -460,7 +460,7 @@
 	return pe;
 
 }/*}}}*/
-void StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+void           StressbalanceSIAAnalysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
 
 	IssmDouble vx,vy;
 	int       *doflist = NULL;
@@ -493,10 +493,10 @@
 	xDelete<int>(doflist);
 	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;
 	IssmDouble  rho_ice,g;
@@ -580,7 +580,7 @@
 	xDelete<IssmDouble>(xyz_list);
 	xDelete<int>(doflist);
 }/*}}}*/
-void StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           StressbalanceSIAAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
 	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
Index: ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.h	(revision 18930)
@@ -12,28 +12,26 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*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: ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.h	(revision 18930)
@@ -12,25 +12,23 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*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: ../trunk-jpl/src/c/analyses/ThermalAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/ThermalAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/ThermalAnalysis.cpp	(revision 18930)
@@ -5,33 +5,45 @@
 #include "../modules/modules.h"
 
 /*Model processing*/
-int  ThermalAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
+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::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
 
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
+	if(iomodel->domaintype==Domain2DhorizontalEnum) _error_("2d meshes not supported yet");
 
-	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));
+	/*create penalties for nodes: no node can have a temperature over the melting point*/
+	iomodel->FetchData(1,ThermalSpctemperatureEnum);
+	CreateSingleNodeToElementConnectivity(iomodel);
 
-	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);
+	for(int i=0;i<iomodel->numberofvertices;i++){
 
-	/*Deal with friction parameters*/
-	int frictionlaw;
-	iomodel->Constant(&frictionlaw,FrictionLawEnum);
-	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
+		/*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::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
 	int frictionlaw;
@@ -121,41 +133,29 @@
 			_error_("not supported");
 	}
 }/*}}}*/
-void ThermalAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void ThermalAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	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){/*{{{*/
+	int     numoutputs;
+	char**  requestedoutputs = NULL;
 
-	/*Only 3d mesh supported*/
-	int finiteelement = P1Enum;
-	if(iomodel->domaintype==Domain3DEnum){
-		IoModelToConstraintsx(constraints,iomodel,ThermalSpctemperatureEnum,ThermalAnalysisEnum,finiteelement);
-	}
+	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));
 
-}/*}}}*/
-void ThermalAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	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);
 
-	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);
-
+	/*Deal with friction parameters*/
+	int frictionlaw;
+	iomodel->Constant(&frictionlaw,FrictionLawEnum);
+	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
 }/*}}}*/
 
 /*Finite Element Analysis*/
@@ -184,6 +184,60 @@
 	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;
+}/*}}}*/
 ElementMatrix* ThermalAnalysis::CreateKMatrixVolume(Element* element){/*{{{*/
 
 	/* Check if ice in element */
@@ -317,60 +371,6 @@
 	delete gauss;
 	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;
-}/*}}}*/
 ElementVector* ThermalAnalysis::CreatePVector(Element* element){/*{{{*/
 	
 	/* Check if ice in element */
@@ -388,88 +388,6 @@
 	delete pe3;
 	return pe;
 }/*}}}*/
-ElementVector* ThermalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
-
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return NULL;
-
-	/*Intermediaries*/
-	int         stabilization;
-	IssmDouble  Jdet,phi,dt;
-	IssmDouble  temperature;
-	IssmDouble  tau_parameter,diameter;
-	IssmDouble  u,v,w;
-	IssmDouble  scalar_def,scalar_transient;
-	IssmDouble* xyz_list = NULL;
-
-	/*Fetch number of nodes and dof for this finite element*/
-	int numnodes = element->GetNumberOfNodes();
-
-	/*Initialize Element vector*/
-	ElementVector* pe     = element->NewElementVector();
-	IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
-	IssmDouble*    dbasis = xNew<IssmDouble>(3*numnodes);
-
-	/*Retrieve all inputs and parameters*/
-	element->GetVerticesCoordinates(&xyz_list);
-	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
-	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
-	IssmDouble  thermalconductivity = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
-	IssmDouble  kappa = thermalconductivity/(rho_ice*heatcapacity);
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	element->FindParam(&stabilization,ThermalStabilizationEnum);
-	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* temperature_input = NULL;
-	if(reCast<bool,IssmDouble>(dt)){temperature_input = element->GetInput(TemperatureEnum); _assert_(temperature_input);}
-	if(stabilization==2) diameter=element->MinEdgeLength(xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	Gauss* gauss=element->NewGauss(3);
-	for(int ig=gauss->begin();ig<gauss->end();ig++){
-		gauss->GaussPoint(ig);
-
-		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
-		element->NodalFunctions(basis,gauss);
-		element->ViscousHeating(&phi,xyz_list,gauss,vx_input,vy_input,vz_input);
-
-		scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
-		if(reCast<bool,IssmDouble>(dt)) scalar_def=scalar_def*dt;
-
-		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_def*basis[i];
-
-		/* Build transient now */
-		if(reCast<bool,IssmDouble>(dt)){
-			temperature_input->GetInputValue(&temperature, gauss);
-			scalar_transient=temperature*Jdet*gauss->weight;
-			for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_transient*basis[i];
-		}
-
-		if(stabilization==2){
-			element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
-
-			vx_input->GetInputValue(&u,gauss);
-			vy_input->GetInputValue(&v,gauss);
-			vz_input->GetInputValue(&w,gauss);
-
-			tau_parameter=element->StabilizationParameter(u,v,w,diameter,kappa);
-
-			for(int i=0;i<numnodes;i++) pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0*numnodes+i]+v*dbasis[1*numnodes+i]+w*dbasis[2*numnodes+i]);
-			if(reCast<bool,IssmDouble>(dt)){
-				for(int i=0;i<numnodes;i++) pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0*numnodes+i]+v*dbasis[1*numnodes+i]+w*dbasis[2*numnodes+i]);
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	xDelete<IssmDouble>(basis);
-	xDelete<IssmDouble>(dbasis);
-	xDelete<IssmDouble>(xyz_list);
-	delete gauss;
-	return pe;
-
-}/*}}}*/
 ElementVector* ThermalAnalysis::CreatePVectorSheet(Element* element){/*{{{*/
 
 	/* Check if ice in element */
@@ -584,39 +502,89 @@
 	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){/*{{{*/
-	/*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)
-	 */
+ElementVector* ThermalAnalysis::CreatePVectorVolume(Element* element){/*{{{*/
 
-	/*Fetch number of nodes for this finite element*/
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return NULL;
+
+	/*Intermediaries*/
+	int         stabilization;
+	IssmDouble  Jdet,phi,dt;
+	IssmDouble  temperature;
+	IssmDouble  tau_parameter,diameter;
+	IssmDouble  u,v,w;
+	IssmDouble  scalar_def,scalar_transient;
+	IssmDouble* xyz_list = NULL;
+
+	/*Fetch number of nodes and dof for this finite element*/
 	int numnodes = element->GetNumberOfNodes();
 
-	/*Get nodal functions derivatives*/
-	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
-	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+	/*Initialize Element vector*/
+	ElementVector* pe     = element->NewElementVector();
+	IssmDouble*    basis  = xNew<IssmDouble>(numnodes);
+	IssmDouble*    dbasis = xNew<IssmDouble>(3*numnodes);
 
-	/*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];
+	/*Retrieve all inputs and parameters*/
+	element->GetVerticesCoordinates(&xyz_list);
+	IssmDouble  rho_ice             = element->GetMaterialParameter(MaterialsRhoIceEnum);
+	IssmDouble  heatcapacity        = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
+	IssmDouble  thermalconductivity = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
+	IssmDouble  kappa = thermalconductivity/(rho_ice*heatcapacity);
+	element->FindParam(&dt,TimesteppingTimeStepEnum);
+	element->FindParam(&stabilization,ThermalStabilizationEnum);
+	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* temperature_input = NULL;
+	if(reCast<bool,IssmDouble>(dt)){temperature_input = element->GetInput(TemperatureEnum); _assert_(temperature_input);}
+	if(stabilization==2) diameter=element->MinEdgeLength(xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	Gauss* gauss=element->NewGauss(3);
+	for(int ig=gauss->begin();ig<gauss->end();ig++){
+		gauss->GaussPoint(ig);
+
+		element->JacobianDeterminant(&Jdet,xyz_list,gauss);
+		element->NodalFunctions(basis,gauss);
+		element->ViscousHeating(&phi,xyz_list,gauss,vx_input,vy_input,vz_input);
+
+		scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
+		if(reCast<bool,IssmDouble>(dt)) scalar_def=scalar_def*dt;
+
+		for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_def*basis[i];
+
+		/* Build transient now */
+		if(reCast<bool,IssmDouble>(dt)){
+			temperature_input->GetInputValue(&temperature, gauss);
+			scalar_transient=temperature*Jdet*gauss->weight;
+			for(int i=0;i<numnodes;i++) pe->values[i]+=scalar_transient*basis[i];
+		}
+
+		if(stabilization==2){
+			element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
+
+			vx_input->GetInputValue(&u,gauss);
+			vy_input->GetInputValue(&v,gauss);
+			vz_input->GetInputValue(&w,gauss);
+
+			tau_parameter=element->StabilizationParameter(u,v,w,diameter,kappa);
+
+			for(int i=0;i<numnodes;i++) pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0*numnodes+i]+v*dbasis[1*numnodes+i]+w*dbasis[2*numnodes+i]);
+			if(reCast<bool,IssmDouble>(dt)){
+				for(int i=0;i<numnodes;i++) pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0*numnodes+i]+v*dbasis[1*numnodes+i]+w*dbasis[2*numnodes+i]);
+			}
+		}
 	}
 
-	/*Clean-up*/
+	/*Clean up and return*/
+	xDelete<IssmDouble>(basis);
 	xDelete<IssmDouble>(dbasis);
+	xDelete<IssmDouble>(xyz_list);
+	delete gauss;
+	return pe;
+
 }/*}}}*/
-void ThermalAnalysis::GetBAdvec(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -645,7 +613,7 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void ThermalAnalysis::GetBAdvecprime(IssmDouble* B,Element* element,IssmDouble* xyz_list,Gauss* gauss){/*{{{*/
+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: 
@@ -674,10 +642,42 @@
 	/*Clean-up*/
 	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
-void ThermalAnalysis::GradientJ(Vector<IssmDouble>* gradient,Element* element,int control_type,int control_index){/*{{{*/
+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
+	 * 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           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;
 	int         i,rheology_law;
@@ -757,7 +757,7 @@
 	xDelete<IssmDouble>(xyz_list);
 	xDelete<int>(doflist);
 }/*}}}*/
-void ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           ThermalAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 
 	bool islevelset;
 	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
Index: ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/AdjointBalancethickness2Analysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,11 +25,11 @@
 		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 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: ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/BalancethicknessAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -29,11 +29,11 @@
 		ElementVector* CreatePVector(Element* element);
 		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: ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/BalancevelocityAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,9 +25,9 @@
 		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);
+		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: ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/UzawaPressureAnalysis.cpp	(revision 18930)
@@ -5,14 +5,27 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Update elements: */
@@ -39,24 +52,11 @@
 	iomodel->FetchDataToInput(elements,PressureEnum,0.);
 	InputUpdateFromConstantx(elements,0.,SigmaNNEnum);
 }/*}}}*/
-void UzawaPressureAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void UzawaPressureAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	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);
+	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRhopEnum));
+	parameters->AddObject(iomodel->CopyConstantObject(AugmentedLagrangianRholambdaEnum));
 }/*}}}*/
-void UzawaPressureAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
-	return;
-}/*}}}*/
-void UzawaPressureAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-	return;
-}/*}}}*/
 
 /*Finite Element Analysis*/
 void           UzawaPressureAnalysis::Core(FemModel* femmodel){/*{{{*/
@@ -163,7 +163,7 @@
 	xDelete<IssmDouble>(dvz);
 	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] */
 
 	/*Fetch number of nodes for this finite element*/
@@ -181,13 +181,13 @@
 	/*Clean-up*/
 	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;
 	int        *doflist       = NULL;
@@ -296,7 +296,7 @@
 	xDelete<IssmDouble>(pressure);
 	xDelete<int>(doflist);
 }/*}}}*/
-void UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           UzawaPressureAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
Index: ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/Balancethickness2Analysis.cpp	(revision 18930)
@@ -5,11 +5,24 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Finite element type*/
@@ -37,22 +50,9 @@
 	}
 
 }/*}}}*/
-void Balancethickness2Analysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
-
-	int finiteelement = P1Enum;
-	::CreateNodes(nodes,iomodel,Balancethickness2AnalysisEnum,finiteelement);
+void Balancethickness2Analysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 }/*}}}*/
-void Balancethickness2Analysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-
-	int finiteelement = P1Enum;
-	IoModelToConstraintsx(constraints,iomodel,BalancethicknessSpcthicknessEnum,Balancethickness2AnalysisEnum,finiteelement);
-
-}/*}}}*/
-void Balancethickness2Analysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-}/*}}}*/
-
 /*Finite Element Analysis*/
 void           Balancethickness2Analysis::Core(FemModel* femmodel){/*{{{*/
 	_error_("not implemented yet");
@@ -61,6 +61,70 @@
 	/*Default, return NULL*/
 	return NULL;
 }/*}}}*/
+void           Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
+
+	/*Intermediaries */
+	IssmDouble       Gamma,h,mu0,ds[2],Cmu,B,k,s,b,normds;
+	const int        n = 3;
+	const IssmDouble Hstar = 500.;
+	const IssmDouble Lstar = 500.e+3;
+	IssmDouble *xyz_list  = NULL;
+
+	/*Fetch number of vertices and allocate output*/
+	int  numnodes = element->GetNumberOfNodes();
+	IssmDouble* D0     = xNew<IssmDouble>(numnodes);
+
+	/*retrieve what we need: */
+	element->GetVerticesCoordinates(&xyz_list);
+	Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum);
+	Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum);
+	Input* surface_input       = element->GetInput(SurfaceEnum);            _assert_(surface_input);
+	Input* B_input             = element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
+	IssmDouble rhog            = element->GetMaterialParameter(MaterialsRhoIceEnum)*element->GetMaterialParameter(ConstantsGEnum);
+
+	/*Calculate damage evolution source term: */
+	Gauss* gauss=element->NewGauss();
+	for (int i=0;i<numnodes;i++){
+		gauss->GaussNode(element->GetElementType(),i);
+		
+		B_input->GetInputValue(&B,gauss);
+		if(surfaceslopex_input && surfaceslopey_input){
+			surfaceslopex_input->GetInputValue(&ds[0],gauss);
+			surfaceslopey_input->GetInputValue(&ds[1],gauss);
+		}
+		else{
+			surface_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
+		}
+
+		/*check slopes*/
+		normds = sqrt(ds[0]*ds[0]+ds[1]*ds[1]);
+		if (normds==0.){
+			_error_("surface slope is zero");
+		}
+		if(normds<1.e-5){
+			ds[0] = ds[0]/normds*1.e+5;
+			ds[1] = ds[1]/normds*1.e+5;
+			normds = 1.e-5;
+		}
+
+		mu0   = pow(2.,(1-3*n)/(2.*n)) * B;
+		Gamma = pow(rhog,n) * pow(Hstar,2*(n+1)) * pow(Hstar/Lstar,2*(n+1)) * 1./pow(mu0,n);
+
+		D0[i] = Gamma*pow(ds[0]*ds[0]+ds[1]*ds[1],(n-1)/2)/(n+2);
+	}
+
+	/*Add input*/
+	element->AddInput(BalancethicknessD0Enum,D0,element->GetElementType());
+	//if(surfaceslopex_input && surfaceslopey_input){
+	//	element->DeleteInput(SurfaceSlopeXEnum);
+	//	element->DeleteInput(SurfaceSlopeYEnum);
+	//}
+	
+	/*Clean up and return*/
+	xDelete<IssmDouble>(D0);
+	xDelete<IssmDouble>(xyz_list);
+	delete gauss;
+}/*}}}*/
 ElementMatrix* Balancethickness2Analysis::CreateJacobianMatrix(Element* element){/*{{{*/
 _error_("Not implemented");
 }/*}}}*/
@@ -150,13 +214,13 @@
 	delete gauss;
 	return pe;
 }/*}}}*/
-void Balancethickness2Analysis::GetSolutionFromInputs(Vector<IssmDouble>* solution,Element* element){/*{{{*/
+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){/*{{{*/
+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){/*{{{*/
+void           Balancethickness2Analysis::InputUpdateFromSolution(IssmDouble* solution,Element* element){/*{{{*/
 
 	/*Intermediaries*/
 	IssmDouble  ds[2],s,b,D;
@@ -210,73 +274,7 @@
 	xDelete<IssmDouble>(vel_list);
 	xDelete<IssmDouble>(xyz_list);
 }/*}}}*/
-void Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           Balancethickness2Analysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	return;
 }/*}}}*/
-
-/*Specifics*/
-void Balancethickness2Analysis::CreateD0(Element* element){/*{{{*/
-
-	/*Intermediaries */
-	IssmDouble       Gamma,h,mu0,ds[2],Cmu,B,k,s,b,normds;
-	const int        n = 3;
-	const IssmDouble Hstar = 500.;
-	const IssmDouble Lstar = 500.e+3;
-	IssmDouble *xyz_list  = NULL;
-
-	/*Fetch number of vertices and allocate output*/
-	int  numnodes = element->GetNumberOfNodes();
-	IssmDouble* D0     = xNew<IssmDouble>(numnodes);
-
-	/*retrieve what we need: */
-	element->GetVerticesCoordinates(&xyz_list);
-	Input* surfaceslopex_input = element->GetInput(SurfaceSlopeXEnum);
-	Input* surfaceslopey_input = element->GetInput(SurfaceSlopeYEnum);
-	Input* surface_input       = element->GetInput(SurfaceEnum);            _assert_(surface_input);
-	Input* B_input             = element->GetInput(MaterialsRheologyBEnum); _assert_(B_input);
-	IssmDouble rhog            = element->GetMaterialParameter(MaterialsRhoIceEnum)*element->GetMaterialParameter(ConstantsGEnum);
-
-	/*Calculate damage evolution source term: */
-	Gauss* gauss=element->NewGauss();
-	for (int i=0;i<numnodes;i++){
-		gauss->GaussNode(element->GetElementType(),i);
-		
-		B_input->GetInputValue(&B,gauss);
-		if(surfaceslopex_input && surfaceslopey_input){
-			surfaceslopex_input->GetInputValue(&ds[0],gauss);
-			surfaceslopey_input->GetInputValue(&ds[1],gauss);
-		}
-		else{
-			surface_input->GetInputDerivativeValue(&ds[0],xyz_list,gauss);
-		}
-
-		/*check slopes*/
-		normds = sqrt(ds[0]*ds[0]+ds[1]*ds[1]);
-		if (normds==0.){
-			_error_("surface slope is zero");
-		}
-		if(normds<1.e-5){
-			ds[0] = ds[0]/normds*1.e+5;
-			ds[1] = ds[1]/normds*1.e+5;
-			normds = 1.e-5;
-		}
-
-		mu0   = pow(2.,(1-3*n)/(2.*n)) * B;
-		Gamma = pow(rhog,n) * pow(Hstar,2*(n+1)) * pow(Hstar/Lstar,2*(n+1)) * 1./pow(mu0,n);
-
-		D0[i] = Gamma*pow(ds[0]*ds[0]+ds[1]*ds[1],(n-1)/2)/(n+2);
-	}
-
-	/*Add input*/
-	element->AddInput(BalancethicknessD0Enum,D0,element->GetElementType());
-	//if(surfaceslopex_input && surfaceslopey_input){
-	//	element->DeleteInput(SurfaceSlopeXEnum);
-	//	element->DeleteInput(SurfaceSlopeYEnum);
-	//}
-	
-	/*Clean up and return*/
-	xDelete<IssmDouble>(D0);
-	xDelete<IssmDouble>(xyz_list);
-	delete gauss;
-}/*}}}*/
Index: ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/DamageEvolutionAnalysis.cpp	(revision 18930)
@@ -5,9 +5,60 @@
 #include "../modules/modules.h"
 
 /*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){/*{{{*/
 
 	/*Intermediaries*/
@@ -44,61 +95,216 @@
 	}
 
 }/*}}}*/
-void DamageEvolutionAnalysis::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
-	int finiteelement;
-	bool   islevelset;
+/*Finite Element Analysis*/
+void           DamageEvolutionAnalysis::Core(FemModel* femmodel){/*{{{*/
+	_error_("not implemented");
+}/*}}}*/
+void           DamageEvolutionAnalysis::CreateDamageFInputExp(Element* element){/*{{{*/
 
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
-	iomodel->Constant(&islevelset,TransientIslevelsetEnum);
+	/*Intermediaries */
+	IssmDouble epsf,stress_threshold,eps0;
+	IssmDouble damage,B,n,epseff;
+	IssmDouble eps_xx,eps_yy,eps_xy,eps1,eps2,epstmp;
+	int domaintype,damagelaw;
 
-	/*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++;
-		}
+	/*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);
+	}
 
-	/*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);
+	/*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;}
 
-	if(islevelset){
-		iomodel->FetchDataToInput(elements,IceMaskNodeActivationEnum);
+		/*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::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void           DamageEvolutionAnalysis::CreateDamageFInputPralong(Element* element){/*{{{*/
 
-	int finiteelement;
+	/*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;
 
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
-	::CreateNodes(nodes,iomodel,DamageEvolutionAnalysisEnum,finiteelement);
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
+	/*Fetch number of vertices and allocate output*/
+	int numnodes = element->GetNumberOfNodes();
+	IssmDouble* f   = xNew<IssmDouble>(numnodes);
 
-	int finiteelement;
-	iomodel->Constant(&finiteelement,DamageElementinterpEnum);
+	/*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);
 
-	IoModelToConstraintsx(constraints,iomodel,DamageSpcdamageEnum,DamageEvolutionAnalysisEnum,finiteelement);
+	/*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);
+	}
 
-}/*}}}*/
-void DamageEvolutionAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
+	/*retrieve the desired type of equivalent stress*/
+	element->FindParam(&equivstress,DamageEquivStressEnum);
 
-	/*Nothing for now*/
+	/*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 */
 
-/*Finite Element Analysis*/
-void           DamageEvolutionAnalysis::Core(FemModel* femmodel){/*{{{*/
-	_error_("not implemented");
+			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){/*{{{*/
 	/*Default, return NULL*/
@@ -341,7 +547,7 @@
 	delete gauss;
 	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
 	 * by: 
@@ -369,7 +575,7 @@
 	/*Clean-up*/
 	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
 	 * by: 
@@ -398,13 +604,13 @@
 	xDelete<IssmDouble>(dbasis);
 
 }/*}}}*/
-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;
 	IssmDouble  max_damage;
@@ -444,7 +650,7 @@
 	xDelete<IssmDouble>(newdamage);
 	xDelete<int>(doflist);
 }/*}}}*/
-void DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
+void           DamageEvolutionAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/
 	/*Default, do nothing*/
 	bool islevelset;
 	femmodel->parameters->FindParam(&islevelset,TransientIslevelsetEnum);
@@ -453,211 +659,3 @@
 	}
 	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: ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/MeshdeformationAnalysis.cpp	(revision 18930)
@@ -5,22 +5,22 @@
 #include "../modules/modules.h"
 
 /*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");
 }/*}}}*/
 void MeshdeformationAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
 	   _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");
 }/*}}}*/
 
@@ -41,16 +41,16 @@
 ElementVector* MeshdeformationAnalysis::CreatePVector(Element* element){/*{{{*/
 _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: ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp
===================================================================
--- ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/EnthalpyAnalysis.cpp	(revision 18930)
@@ -6,31 +6,104 @@
 #include "../solutionsequences/solutionsequences.h"
 
 /*Model processing*/
-int  EnthalpyAnalysis::DofsPerNode(int** doflist,int domaintype,int approximation){/*{{{*/
-	return 1;
-}/*}}}*/
-void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
+void EnthalpyAnalysis::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-	int     numoutputs;
-	char**  requestedoutputs = NULL;
+	/*Intermediary*/
+	int        count;
+	int        M,N;
+	bool       spcpresent = false;
+	IssmDouble heatcapacity;
+	IssmDouble referencetemperature;
 
-	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));
+	/*Output*/
+	IssmDouble *spcvector  = NULL;
+	IssmDouble* times=NULL;
+	IssmDouble* values=NULL;
 
-	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);
+	/*Fetch parameters: */
+	iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
+	iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
 
-	/*Deal with friction parameters*/
-	int frictionlaw;
-	iomodel->Constant(&frictionlaw,FrictionLawEnum);
-	if(frictionlaw==4 || frictionlaw==6) parameters->AddObject(iomodel->CopyConstantObject(FrictionGammaEnum));
+	/*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::UpdateElements(Elements* elements,IoModel* iomodel,int analysis_counter,int analysis_type){/*{{{*/
 
 	bool dakota_analysis,islevelset,isenthalpy;
@@ -131,104 +204,245 @@
 	/*Free data: */
 	iomodel->DeleteData(3,TemperatureEnum,WaterfractionEnum,PressureEnum);
 }/*}}}*/
-void EnthalpyAnalysis::CreateNodes(Nodes* nodes,IoModel* iomodel){/*{{{*/
+void EnthalpyAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/
 
-	if(iomodel->domaintype==Domain3DEnum) iomodel->FetchData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
-	::CreateNodes(nodes,iomodel,EnthalpyAnalysisEnum,P1Enum);
-	iomodel->DeleteData(2,MeshVertexonbaseEnum,MeshVertexonsurfaceEnum);
+	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::CreateConstraints(Constraints* constraints,IoModel* iomodel){/*{{{*/
 
-	/*Intermediary*/
-	int        count;
-	int        M,N;
-	bool       spcpresent = false;
-	IssmDouble heatcapacity;
-	IssmDouble referencetemperature;
+/*Finite Element Analysis*/
+void           EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
 
-	/*Output*/
-	IssmDouble *spcvector  = NULL;
-	IssmDouble* times=NULL;
-	IssmDouble* values=NULL;
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
 
-	/*Fetch parameters: */
-	iomodel->Constant(&heatcapacity,MaterialsHeatcapacityEnum);
-	iomodel->Constant(&referencetemperature,ConstantsReferencetemperatureEnum);
+	/* Only update Constraints at the base of grounded ice*/
+	if(!(element->IsOnBase()) || element->IsFloating()) return;
 
-	/*return if 2d mesh*/
-	if(iomodel->domaintype==Domain2DhorizontalEnum) return;
+	/*Intermediary*/
+	bool        isdynamicbasalspc;
+	int         numindices;
+	int        *indices = NULL;
+	Node*       node = NULL;
+	IssmDouble	pressure;
 
-	/*Fetch data: */
-	iomodel->FetchData(&spcvector,&M,&N,ThermalSpctemperatureEnum);
+	/*Check wether dynamic basal boundary conditions are activated */
+	element->FindParam(&isdynamicbasalspc,ThermalIsdynamicbasalspcEnum);
+	if(!isdynamicbasalspc) return;
 
-	//FIX ME: SHOULD USE IOMODELCREATECONSTRAINTS 
-	/*Transient or static?:*/
-	if(M==iomodel->numberofvertices){
-		/*static: just create Constraints objects*/
-		count=0;
+	/*Get parameters and inputs: */
+	Input* pressure_input		 = element->GetInput(PressureEnum);							 _assert_(pressure_input);
 
-		for(int i=0;i<iomodel->numberofvertices;i++){
-			/*keep only this partition's nodes:*/
-			if((iomodel->my_vertices[i])){
+	/*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());
 
-				if (!xIsNan<IssmDouble>(spcvector[i])){
+	GaussPenta* gauss=new GaussPenta();
+	for(int i=0;i<numindices;i++){
+		gauss->GaussNode(element->GetElementType(),indices[i]);
 
-					constraints->AddObject(new SpcStatic(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,heatcapacity*(spcvector[i]-referencetemperature),EnthalpyAnalysisEnum));
-					count++;
+		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);
 	}
-	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];
-		}
+	/*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*/
 
-		/*Create constraints from x,y,z: */
-		for(int i=0;i<iomodel->numberofvertices;i++){
+	/* Check if ice in element */
+	if(!element->IsIceInElement()) return;
 
-			/*keep only this partition's nodes:*/
-			if((iomodel->my_vertices[i])){
+	/* Only compute melt rates at the base of grounded ice*/
+	if(!element->IsOnBase() || element->IsFloating()) return;
 
-				/*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
-				}
+	/* 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;
 
-				if(spcpresent){
-					constraints->AddObject(new SpcTransient(iomodel->constraintcounter+count+1,iomodel->nodecounter+i+1,0,N,times,values,EnthalpyAnalysisEnum));
-					count++;
-				}
-				xDelete<IssmDouble>(values);
+	/*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);
 	}
-	else{
-		_error_("Size of field " << EnumToStringx(ThermalSpctemperatureEnum) << " not supported");
-	}
+	element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
 
-	/*Free ressources:*/
-	iomodel->DeleteData(spcvector,ThermalSpctemperatureEnum);
-	xDelete<IssmDouble>(times);
-	xDelete<IssmDouble>(values);
+	/*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::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/
-
-	/*No loads */
-}/*}}}*/
-
-/*Finite Element Analysis*/
-void EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
+void           EnthalpyAnalysis::Core(FemModel* femmodel){/*{{{*/
 	if(VerboseSolution()) _printf0_("   computing enthalpy\n");
 	femmodel->SetCurrentConfiguration(EnthalpyAnalysisEnum);
 	solutionsequence_thermal_nonlinear(femmodel);
@@ -740,386 +954,76 @@
 	xDelete<IssmDouble>(xyz_list_base);
 	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: */
+void           EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
+	/*Drain excess water fraction in ice column: */
 	for(int i=0;i<femmodel->elements->Size();i++){
 		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		ComputeBasalMeltingrate(element);
+		DrainWaterfractionIcecolumn(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*/
+void           EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
 
 	/* 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*/
+	int iv,is,vertexdown,vertexup,numsegments;	
+	IssmDouble dt, height_element;
+	IssmDouble rho_water, rho_ice;
+	int numvertices = element->GetNumberOfVertices();
 
-	/* 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;
+	IssmDouble* xyz_list = NULL;
+	IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
+	IssmDouble* pressures = xNew<IssmDouble>(numvertices);
+	IssmDouble* temperatures = xNew<IssmDouble>(numvertices);
+	IssmDouble* waterfractions = xNew<IssmDouble>(numvertices);
+	IssmDouble* deltawaterfractions = xNew<IssmDouble>(numvertices);
 	int        *pairindices   = NULL;
+	
+	rho_ice=element->GetMaterialParameter(MaterialsRhoIceEnum);
+	rho_water=element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
 
-	/*Fetch parameters*/
 	element->GetVerticesCoordinates(&xyz_list);
-	element->GetVerticesCoordinatesBase(&xyz_list_base);
-	element->GetInputValue(&converged,ConvergedEnum);
+	element->GetInputListOnVertices(enthalpies,EnthalpyEnum);
+	element->GetInputListOnVertices(pressures,PressureEnum);
+
 	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	element->FindParam(&yts, ConstantsYtsEnum);
+	for(iv=0;iv<numvertices;iv++){ 
+		element->EnthalpyToThermal(&temperatures[iv],&waterfractions[iv], enthalpies[iv],pressures[iv]); 
+		deltawaterfractions[iv]=DrainageFunctionWaterfraction(waterfractions[iv], dt);
+	}
+	
+	/*drain waterfraction, feed updated variables back into model*/
+	for(iv=0;iv<numvertices;iv++){
+		if(reCast<bool,IssmDouble>(dt))
+			waterfractions[iv]-=deltawaterfractions[iv]*dt;
+		else
+			waterfractions[iv]-=deltawaterfractions[iv];
+		element->ThermalToEnthalpy(&enthalpies[iv], temperatures[iv], waterfractions[iv], pressures[iv]);
+	}
+	element->AddInput(EnthalpyEnum,enthalpies,P1Enum);
+  	element->AddInput(WaterfractionEnum,waterfractions,P1Enum);
 
-	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);
+	/*return meltwater column equivalent to drained water*/
 	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);
+		height_element=fabs(xyz_list[vertexup*3+2]-xyz_list[vertexdown*3+2]);
+		pdrainrate_element[is]=(deltawaterfractions[vertexdown]+deltawaterfractions[vertexup])/2.*height_element; // return water equivalent of drainage
+		_assert_(pdrainrate_element[is]>=0.);
 	}
-	element->AddInput(BasalforcingsGroundediceMeltingRateEnum,basalmeltingrates,P1Enum);
 
 	/*Clean up and return*/
-	delete gauss;
-	delete friction;
 	xDelete<int>(pairindices);
+	xDelete<IssmDouble>(xyz_list);
 	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);
+	xDelete<IssmDouble>(temperatures);
+	xDelete<IssmDouble>(waterfractions);
+	xDelete<IssmDouble>(deltawaterfractions);
 }/*}}}*/
-void EnthalpyAnalysis::DrainWaterfraction(FemModel* femmodel){/*{{{*/
-	/*Drain excess water fraction in ice column: */
-	for(int i=0;i<femmodel->elements->Size();i++){
-		Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
-		DrainWaterfractionIcecolumn(element);
-	}
-}/*}}}*/
-void EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
+void           EnthalpyAnalysis::DrainWaterfractionIcecolumn(Element* element){/*{{{*/
 
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return;
@@ -1160,144 +1064,133 @@
 	xDelete<IssmDouble>(drainrate_element);
 	xDelete<IssmDouble>(watercolumn);
 }/*}}}*/
-void EnthalpyAnalysis::DrainWaterfraction(Element* element, IssmDouble* pdrainrate_element){/*{{{*/
+IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
 
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
+	IssmDouble heatcapacity             = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
+	IssmDouble temperateiceconductivity = element->GetMaterialParameter(MaterialsTemperateiceconductivityEnum);
+	IssmDouble thermalconductivity      = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
 
-	/*Intermediaries*/
-	int iv,is,vertexdown,vertexup,numsegments;	
-	IssmDouble dt, height_element;
-	IssmDouble rho_water, rho_ice;
-	int numvertices = element->GetNumberOfVertices();
+	if(enthalpy < PureIceEnthalpy(element,pressure)){
+		return thermalconductivity/heatcapacity;
+	}
+	else{
+		return temperateiceconductivity/heatcapacity;
+	}
+}/*}}}*/
+IssmDouble     EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
 
-	IssmDouble* xyz_list = NULL;
-	IssmDouble* enthalpies = xNew<IssmDouble>(numvertices);
-	IssmDouble* pressures = xNew<IssmDouble>(numvertices);
-	IssmDouble* temperatures = xNew<IssmDouble>(numvertices);
-	IssmDouble* waterfractions = xNew<IssmDouble>(numvertices);
-	IssmDouble* deltawaterfractions = xNew<IssmDouble>(numvertices);
-	int        *pairindices   = NULL;
-	
-	rho_ice=element->GetMaterialParameter(MaterialsRhoIceEnum);
-	rho_water=element->GetMaterialParameter(MaterialsRhoSeawaterEnum);
+	int         iv;
+	IssmDouble  lambda;                   /* fraction of cold ice    */
+	IssmDouble  kappa,kappa_c,kappa_t; /* enthalpy conductivities */
+	IssmDouble  Hc,Ht;
 
-	element->GetVerticesCoordinates(&xyz_list);
-	element->GetInputListOnVertices(enthalpies,EnthalpyEnum);
+	/*Get pressures and enthalpies on vertices*/
+	int         numvertices = element->GetNumberOfVertices();
+	IssmDouble* pressures   = xNew<IssmDouble>(numvertices);
+	IssmDouble* enthalpies  = xNew<IssmDouble>(numvertices);
+	IssmDouble* PIE         = xNew<IssmDouble>(numvertices);
+	IssmDouble* dHpmp       = xNew<IssmDouble>(numvertices);
 	element->GetInputListOnVertices(pressures,PressureEnum);
+	element->GetInputListOnVertices(enthalpies,enthalpy_enum);
+	for(iv=0;iv<numvertices;iv++){
+		PIE[iv]   = PureIceEnthalpy(element,pressures[iv]);
+		dHpmp[iv] = enthalpies[iv]-PIE[iv];
+	}
 
-	element->FindParam(&dt,TimesteppingTimeStepEnum);
-	for(iv=0;iv<numvertices;iv++){ 
-		element->EnthalpyToThermal(&temperatures[iv],&waterfractions[iv], enthalpies[iv],pressures[iv]); 
-		deltawaterfractions[iv]=DrainageFunctionWaterfraction(waterfractions[iv], dt);
+	bool allequalsign = true;
+	if(dHpmp[0]<0.){
+		for(iv=1; iv<numvertices;iv++) allequalsign=(allequalsign && (dHpmp[iv]<0.));
 	}
-	
-	/*drain waterfraction, feed updated variables back into model*/
-	for(iv=0;iv<numvertices;iv++){
-		if(reCast<bool,IssmDouble>(dt))
-			waterfractions[iv]-=deltawaterfractions[iv]*dt;
-		else
-			waterfractions[iv]-=deltawaterfractions[iv];
-		element->ThermalToEnthalpy(&enthalpies[iv], temperatures[iv], waterfractions[iv], pressures[iv]);
+	else{
+		for(iv=1; iv<numvertices;iv++) allequalsign=(allequalsign && (dHpmp[iv]>=0.));
 	}
-	element->AddInput(EnthalpyEnum,enthalpies,P1Enum);
-  	element->AddInput(WaterfractionEnum,waterfractions,P1Enum);
 
-	/*return meltwater column equivalent to drained water*/
-	element->VerticalSegmentIndices(&pairindices,&numsegments);
-	for(is=0;is<numsegments;is++){
-		vertexdown = pairindices[is*2+0];
-		vertexup   = pairindices[is*2+1];
-		height_element=fabs(xyz_list[vertexup*3+2]-xyz_list[vertexdown*3+2]);
-		pdrainrate_element[is]=(deltawaterfractions[vertexdown]+deltawaterfractions[vertexup])/2.*height_element; // return water equivalent of drainage
-		_assert_(pdrainrate_element[is]>=0.);
+	if(allequalsign){
+		kappa = EnthalpyDiffusionParameter(element,enthalpies[0],pressures[0]);
 	}
+	else{
+		/* return harmonic mean of thermal conductivities, weighted by fraction of cold/temperate ice,
+			cf Patankar 1980, pp44 */
+		kappa_c = EnthalpyDiffusionParameter(element,PureIceEnthalpy(element,0.)-1.,0.);
+		kappa_t = EnthalpyDiffusionParameter(element,PureIceEnthalpy(element,0.)+1.,0.);
+		Hc=0.; Ht=0.;
+		for(iv=0; iv<numvertices;iv++){
+			if(enthalpies[iv]<PIE[iv])
+			 Hc+=(PIE[iv]-enthalpies[iv]);
+			else
+			 Ht+=(enthalpies[iv]-PIE[iv]);
+		}
+		_assert_((Hc+Ht)>0.);
+		lambda = Hc/(Hc+Ht);
+		kappa  = kappa_c*kappa_t/(lambda*kappa_t+(1.-lambda)*kappa_c); // ==(lambda/kappa_c + (1.-lambda)/kappa_t)^-1
+	}	
 
 	/*Clean up and return*/
-	xDelete<int>(pairindices);
-	xDelete<IssmDouble>(xyz_list);
+	xDelete<IssmDouble>(PIE);
+	xDelete<IssmDouble>(dHpmp);
+	xDelete<IssmDouble>(pressures);
 	xDelete<IssmDouble>(enthalpies);
-	xDelete<IssmDouble>(pressures);
-	xDelete<IssmDouble>(temperatures);
-	xDelete<IssmDouble>(waterfractions);
-	xDelete<IssmDouble>(deltawaterfractions);
+	return kappa;
 }/*}}}*/
-void EnthalpyAnalysis::UpdateBasalConstraints(FemModel* femmodel){/*{{{*/
+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)
+	 */
 
-	/*Update basal dirichlet BCs for enthalpy: */
-	Vector<IssmDouble>* spc           = NULL;
-	IssmDouble*         serial_spc    = NULL;
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
 
-	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);
-	}
+	/*Get nodal functions*/
+	IssmDouble* basis=xNew<IssmDouble>(numnodes);
+	element->NodalFunctions(basis,gauss);
 
-	/*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);
+	/*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];
 	}
 
-	femmodel->UpdateConstraintsx();
-
-	/*Delete*/
-	xDelete<IssmDouble>(serial_spc);
+	/*Clean-up*/
+	xDelete<IssmDouble>(basis);
 }/*}}}*/
-void EnthalpyAnalysis::ApplyBasalConstraints(IssmDouble* serial_spc,Element* element){/*{{{*/
+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)
+	 */
 
-	/* Check if ice in element */
-	if(!element->IsIceInElement()) return;
+	/*Fetch number of nodes for this finite element*/
+	int numnodes = element->GetNumberOfNodes();
 
-	/* Only update Constraints at the base of grounded ice*/
-	if(!(element->IsOnBase()) || element->IsFloating()) return;
+	/*Get nodal functions derivatives*/
+	IssmDouble* dbasis=xNew<IssmDouble>(3*numnodes);
+	element->NodalFunctionsDerivatives(dbasis,xyz_list,gauss);
 
-	/*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);
+	/*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];
 	}
 
-	/*Free ressources:*/
-	xDelete<int>(indices);
-	delete gauss;
+	/*Clean-up*/
+	xDelete<IssmDouble>(dbasis);
 }/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+void           EnthalpyAnalysis::GetBasalConstraints(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
 
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return;
@@ -1321,7 +1214,7 @@
 		GetBasalConstraintsTransient(vec_spc,element);
 	}
 }/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+void           EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
 
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return;
@@ -1335,7 +1228,7 @@
 	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
 
 	/*Get parameters and inputs: */
-	Input* enthalpy_input       = element->GetInput(EnthalpyEnum);                    _assert_(enthalpy_input); //TODO: check EnthalpyPicard?
+	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);
@@ -1347,11 +1240,10 @@
 
 	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);
@@ -1360,7 +1252,6 @@
 		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
@@ -1379,13 +1270,12 @@
 				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);
+				// 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:*/
@@ -1394,7 +1284,7 @@
 	delete gauss;
 	delete gaussup;
 }/*}}}*/
-void EnthalpyAnalysis::GetBasalConstraintsSteadystate(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
+void           EnthalpyAnalysis::GetBasalConstraintsTransient(Vector<IssmDouble>* vec_spc,Element* element){/*{{{*/
 
 	/* Check if ice in element */
 	if(!element->IsIceInElement()) return;
@@ -1408,7 +1298,7 @@
 	IssmDouble	enthalpy, enthalpyup, pressure, pressureup, watercolumn, meltingrate;
 
 	/*Get parameters and inputs: */
-	Input* enthalpy_input		 = element->GetInput(EnthalpyPicardEnum);					 _assert_(enthalpy_input);
+	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);
@@ -1420,10 +1310,11 @@
 
 	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);
@@ -1432,6 +1323,7 @@
 		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
@@ -1450,12 +1342,13 @@
 				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);
+				// 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:*/
@@ -1464,8 +1357,40 @@
 	delete gauss;
 	delete gaussup;
 }/*}}}*/
-int EnthalpyAnalysis::GetThermalBasalCondition(Element* element, IssmDouble enthalpy, IssmDouble enthalpyup, IssmDouble pressure, IssmDouble pressureup, IssmDouble watercolumn, IssmDouble meltingrate){/*{{{*/
+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;
 
@@ -1494,7 +1419,7 @@
 	_assert_(state>=0);
 	return state;
 }/*}}}*/
-IssmDouble EnthalpyAnalysis::GetWetIceConductivity(Element* element, IssmDouble enthalpy, IssmDouble pressure){/*{{{*/
+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)
@@ -1503,87 +1428,158 @@
 
 	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){/*{{{*/
 
-/*Intermediaries*/
-IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameter(Element* element,IssmDouble enthalpy,IssmDouble pressure){/*{{{*/
+	bool        converged;
+	int         i,rheology_law;
+	IssmDouble  B_average,s_average,T_average=0.,P_average=0.;
+	int        *doflist   = NULL;
+	IssmDouble *xyz_list  = NULL;
 
-	IssmDouble heatcapacity             = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
-	IssmDouble temperateiceconductivity = element->GetMaterialParameter(MaterialsTemperateiceconductivityEnum);
-	IssmDouble thermalconductivity      = element->GetMaterialParameter(MaterialsThermalconductivityEnum);
+	/*Fetch number of nodes and dof for this finite element*/
+	int numnodes    = element->GetNumberOfNodes();
 
-	if(enthalpy < PureIceEnthalpy(element,pressure)){
-		return thermalconductivity/heatcapacity;
-	}
-	else{
-		return temperateiceconductivity/heatcapacity;
-	}
-}/*}}}*/
-IssmDouble EnthalpyAnalysis::EnthalpyDiffusionParameterVolume(Element* element,int enthalpy_enum){/*{{{*/
+	/*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);
 
-	int         iv;
-	IssmDouble  lambda;                   /* fraction of cold ice    */
-	IssmDouble  kappa,kappa_c,kappa_t; /* enthalpy conductivities */
-	IssmDouble  Hc,Ht;
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numnodes;i++){
+		values[i]=solution[doflist[i]];
 
-	/*Get pressures and enthalpies on vertices*/
-	int         numvertices = element->GetNumberOfVertices();
-	IssmDouble* pressures   = xNew<IssmDouble>(numvertices);
-	IssmDouble* enthalpies  = xNew<IssmDouble>(numvertices);
-	IssmDouble* PIE         = xNew<IssmDouble>(numvertices);
-	IssmDouble* dHpmp       = xNew<IssmDouble>(numvertices);
-	element->GetInputListOnVertices(pressures,PressureEnum);
-	element->GetInputListOnVertices(enthalpies,enthalpy_enum);
-	for(iv=0;iv<numvertices;iv++){
-		PIE[iv]   = PureIceEnthalpy(element,pressures[iv]);
-		dHpmp[iv] = enthalpies[iv]-PIE[iv];
+		/*Check solution*/
+		if(xIsNan<IssmDouble>(values[i])) _error_("NaN found in solution vector");
 	}
 
-	bool allequalsign = true;
-	if(dHpmp[0]<0.){
-		for(iv=1; iv<numvertices;iv++) allequalsign=(allequalsign && (dHpmp[iv]<0.));
+	/*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{
-		for(iv=1; iv<numvertices;iv++) allequalsign=(allequalsign && (dHpmp[iv]>=0.));
+		element->AddInput(EnthalpyPicardEnum,values,element->GetElementType());
 	}
 
-	if(allequalsign){
-		kappa = EnthalpyDiffusionParameter(element,enthalpies[0],pressures[0]);
-	}
-	else{
-		/* return harmonic mean of thermal conductivities, weighted by fraction of cold/temperate ice,
-			cf Patankar 1980, pp44 */
-		kappa_c = EnthalpyDiffusionParameter(element,PureIceEnthalpy(element,0.)-1.,0.);
-		kappa_t = EnthalpyDiffusionParameter(element,PureIceEnthalpy(element,0.)+1.,0.);
-		Hc=0.; Ht=0.;
-		for(iv=0; iv<numvertices;iv++){
-			if(enthalpies[iv]<PIE[iv])
-			 Hc+=(PIE[iv]-enthalpies[iv]);
-			else
-			 Ht+=(enthalpies[iv]-PIE[iv]);
-		}
-		_assert_((Hc+Ht)>0.);
-		lambda = Hc/(Hc+Ht);
-		kappa  = kappa_c*kappa_t/(lambda*kappa_t+(1.-lambda)*kappa_c); // ==(lambda/kappa_c + (1.-lambda)/kappa_t)^-1
-	}	
+	/*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){/*{{{*/
 
-	/*Clean up and return*/
-	xDelete<IssmDouble>(PIE);
-	xDelete<IssmDouble>(dHpmp);
-	xDelete<IssmDouble>(pressures);
-	xDelete<IssmDouble>(enthalpies);
-	return kappa;
+	/*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     EnthalpyAnalysis::PureIceEnthalpy(Element* element,IssmDouble pressure){/*{{{*/
 
 	IssmDouble heatcapacity         = element->GetMaterialParameter(MaterialsHeatcapacityEnum);
 	IssmDouble referencetemperature = element->GetMaterialParameter(ConstantsReferencetemperatureEnum);
 
 	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);
 	IssmDouble beta         = element->GetMaterialParameter(MaterialsBetaEnum);
 
 	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: ../trunk-jpl/src/c/analyses/LevelsetAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/LevelsetAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/LevelsetAnalysis.h	(revision 18930)
@@ -12,12 +12,12 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
@@ -25,14 +25,14 @@
 		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);
-		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: ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h
===================================================================
--- ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h	(revision 18929)
+++ ../trunk-jpl/src/c/analyses/StressbalanceVerticalAnalysis.h	(revision 18930)
@@ -12,28 +12,28 @@
 
 	public:
 		/*Model processing*/
+		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);
-		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);
 
 		/*Finite element Analysis*/
 		void           Core(FemModel* femmodel);
 		ElementVector* CreateDVector(Element* element);
 		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
