Index: /issm/trunk/src/ad/eraselinks.sh
===================================================================
--- /issm/trunk/src/ad/eraselinks.sh	(revision 9774)
+++ /issm/trunk/src/ad/eraselinks.sh	(revision 9775)
@@ -7,5 +7,6 @@
 rm shared
 rm toolkits
-rm iorm EnumDefinitions
+rm io
+rm EnumDefinitions
 rm modules
 rm solutions
Index: /issm/trunk/src/c/Container/DataSet.cpp
===================================================================
--- /issm/trunk/src/c/Container/DataSet.cpp	(revision 9774)
+++ /issm/trunk/src/c/Container/DataSet.cpp	(revision 9775)
@@ -229,4 +229,5 @@
 				dataset->AddObject(triavertexinput);}
 				break;
+			#ifdef _HAVE_THREED_
 			case PentaVertexInputEnum:{
 				PentaVertexInput* pentavertexinput=NULL;
@@ -235,4 +236,5 @@
 				dataset->AddObject(pentavertexinput);}
 				break;
+			#endif
 			case TransientInputEnum:{
 				TransientInput* transientinput=NULL;
@@ -261,4 +263,5 @@
 				dataset->AddObject(triavertexelementresult);}
 				break;
+			 #ifdef _HAVE_THREED_
 			case PentaVertexElementResultEnum:{
 				PentaVertexElementResult* pentavertexelementresult=NULL;
@@ -273,4 +276,5 @@
 				dataset->AddObject(penta);}
 				break;
+			#endif
 			case MaticeEnum:{
 				Matice* matice=NULL;
@@ -327,4 +331,5 @@
 				dataset->AddObject(numericalflux);}
 				break;
+			#ifdef _HAVE_RIFTS_
 			case RiftfrontEnum:{
 				Riftfront* riftfront=NULL;
@@ -333,4 +338,5 @@
 				dataset->AddObject(riftfront);}
 				break;
+			#endif
 			case DoubleInputEnum:{
 				DoubleInput* doubleinput=NULL;
Index: /issm/trunk/src/c/Container/Loads.cpp
===================================================================
--- /issm/trunk/src/c/Container/Loads.cpp	(revision 9774)
+++ /issm/trunk/src/c/Container/Loads.cpp	(revision 9775)
@@ -78,21 +78,4 @@
 }
 /*}}}*/
-/*FUNCTION Loads::OutputRifts{{{1*/
-void  Loads::OutputRifts(Vec riftproperties){
-
-	int i;
-
-	for(i=0;i<this->Size();i++){
-
-		Object* object=(Object*)this->GetObjectByOffset(i);
-
-		if(object->Enum()==RiftfrontEnum){
-
-			Riftfront* riftfront=(Riftfront*)object;
-			riftfront->OutputProperties(riftproperties);
-		}
-	}
-}
-/*}}}*/
 /*FUNCTION Loads::SetCurrentConfiguration{{{1*/
 void Loads::SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters){
Index: /issm/trunk/src/c/Container/Loads.h
===================================================================
--- /issm/trunk/src/c/Container/Loads.h	(revision 9774)
+++ /issm/trunk/src/c/Container/Loads.h	(revision 9775)
@@ -28,5 +28,4 @@
 		void  Configure(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters);
 		int   NumberOfLoads(void);
-		void  OutputRifts(Vec riftproperties);
 		void  SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters);
 		/*}}}*/
Index: /issm/trunk/src/c/Makefile.am
===================================================================
--- /issm/trunk/src/c/Makefile.am	(revision 9774)
+++ /issm/trunk/src/c/Makefile.am	(revision 9775)
@@ -1,4 +1,5 @@
 INCLUDES = @DAKOTAINCL@ @PETSCINCL@ @SLEPCINCL@ @MPIINCL@ @MATLABINCL@  @METISINCL@  @CHACOINCL@ @SCOTCHINCL@ @PLAPACKINCL@  @BLASLAPACKINCL@ @MKLINCL@ @MUMPSINCL@  @TRIANGLEINCL@ @HYPREINCL@ @MLINCL@ @TAOINCL@
 
+#Library declaration {{{1
 #Compile serial library, and then try and compile parallel library
 if NOSERIAL
@@ -16,9 +17,8 @@
 endif
 
-#Overload library, to overload any non-standard symbols.
-libOverload_a_SOURCES = ./shared/String/stricmp.c
-libOverload_a_CFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(COPTFLAGS)
-
-#Serial compilation
+#}}}
+
+#For serial compilation
+#ISSM serial library{{{1
 libISSM_a_SOURCES = ./include/macros.h\
 					./include/typedefs.h\
@@ -689,6 +689,4 @@
 					./modules/InputConvergencex/InputConvergencex.cpp\
 					./modules/InputConvergencex/InputConvergencex.h\
-					./modules/OutputRiftsx/OutputRiftsx.h\
-					./modules/OutputRiftsx/OutputRiftsx.cpp\
 					./modules/Bamgx/Bamgx.cpp\
 					./modules/Bamgx/Bamgx.h\
@@ -712,128 +710,16 @@
 endif
 
-#Parallel compilation
+#}}}
+
+#For parallel compilation
+#ISSM parallel library  {{{1
 libpISSM_a_SOURCES = ./include/macros.h\
 					./include/typedefs.h\
 					./include/types.h\
-					./include/globals.h\
 					./include/include.h\
 					./objects/objects.h\
 					./objects/Object.h\
-					./objects/Bamg/BamgGeom.h\
-					./objects/Bamg/BamgGeom.cpp\
-					./objects/Bamg/BamgMesh.h\
-					./objects/Bamg/BamgMesh.cpp\
-					./objects/Bamg/BamgOpts.h\
-					./objects/Bamg/BamgOpts.cpp\
-					./objects/Bamg/BamgObjects.h \
-					./objects/Bamg/CrackedEdge.h\
-					./objects/Bamg/CrackedEdge.cpp\
-					./objects/Bamg/Curve.h\
-					./objects/Bamg/Curve.cpp\
-					./objects/Bamg/Direction.h\
-					./objects/Bamg/Direction.cpp\
-					./objects/Bamg/DoubleAndInt.h\
-					./objects/Bamg/Edge.h\
-					./objects/Bamg/Edge.cpp\
-					./objects/Bamg/GeomEdge.h\
-					./objects/Bamg/GeomEdge.cpp\
-					./objects/Bamg/GeomSubDomain.h\
-					./objects/Bamg/GeomSubDomain.cpp\
-					./objects/Bamg/GeomVertex.h\
-					./objects/Bamg/GeomVertex.cpp\
-					./objects/Bamg/Geometry.h\
-					./objects/Bamg/Geometry.cpp\
-					./objects/Bamg/ListofIntersectionTriangles.cpp\
-					./objects/Bamg/ListofIntersectionTriangles.h\
-					./objects/Bamg/EigenMetric.cpp\
-					./objects/Bamg/Metric.cpp\
-					./objects/Bamg/Metric.h\
-					./objects/Bamg/QuadTree.cpp\
-					./objects/Bamg/QuadTree.h\
-					./objects/Bamg/R2.h\
-					./objects/Bamg/SetOfE4.cpp\
-					./objects/Bamg/SetOfE4.h\
-					./objects/Bamg/SubDomain.h\
-					./objects/Bamg/SubDomain.cpp\
-					./objects/Bamg/AdjacentTriangle.h\
-					./objects/Bamg/AdjacentTriangle.cpp\
-					./objects/Bamg/Triangle.cpp\
-					./objects/Bamg/Triangle.h\
-					./objects/Bamg/BamgVertex.cpp\
-					./objects/Bamg/BamgVertex.h\
-					./objects/Bamg/VertexOnEdge.h\
-					./objects/Bamg/VertexOnEdge.cpp\
-					./objects/Bamg/VertexOnGeom.h\
-					./objects/Bamg/VertexOnGeom.cpp\
-					./objects/Bamg/VertexOnVertex.h\
-					./objects/Bamg/VertexOnVertex.cpp\
-					./objects/Bamg/Mesh.h\
-					./objects/Bamg/Mesh.cpp\
 					./objects/Gauss/GaussTria.h\
 					./objects/Gauss/GaussTria.cpp\
-					./objects/Gauss/GaussPenta.h\
-					./objects/Gauss/GaussPenta.cpp\
-					./objects/KML/KML_Attribute.cpp\
-					./objects/KML/KML_Attribute.h\
-					./objects/KML/KML_ColorStyle.cpp\
-					./objects/KML/KML_ColorStyle.h\
-					./objects/KML/KML_Container.cpp\
-					./objects/KML/KML_Container.h\
-					./objects/KML/KML_Document.cpp\
-					./objects/KML/KML_Document.h\
-					./objects/KML/KML_Feature.cpp\
-					./objects/KML/KML_Feature.h\
-					./objects/KML/KML_File.cpp\
-					./objects/KML/KML_File.h\
-					./objects/KML/KML_Folder.cpp\
-					./objects/KML/KML_Folder.h\
-					./objects/KML/KML_Geometry.cpp\
-					./objects/KML/KML_Geometry.h\
-					./objects/KML/KML_GroundOverlay.cpp\
-					./objects/KML/KML_GroundOverlay.h\
-					./objects/KML/KML_Icon.cpp\
-					./objects/KML/KML_Icon.h\
-					./objects/KML/KML_LatLonBox.cpp\
-					./objects/KML/KML_LatLonBox.h\
-					./objects/KML/KML_LinearRing.cpp\
-					./objects/KML/KML_LinearRing.h\
-					./objects/KML/KML_LineString.cpp\
-					./objects/KML/KML_LineString.h\
-					./objects/KML/KML_LineStyle.cpp\
-					./objects/KML/KML_LineStyle.h\
-					./objects/KML/KML_MultiGeometry.cpp\
-					./objects/KML/KML_MultiGeometry.h\
-					./objects/KML/KML_Object.cpp\
-					./objects/KML/KML_Object.h\
-					./objects/KML/KML_Overlay.cpp\
-					./objects/KML/KML_Overlay.h\
-					./objects/KML/KML_Placemark.cpp\
-					./objects/KML/KML_Placemark.h\
-					./objects/KML/KML_Polygon.cpp\
-					./objects/KML/KML_Polygon.h\
-					./objects/KML/KML_PolyStyle.cpp\
-					./objects/KML/KML_PolyStyle.h\
-					./objects/KML/KML_Style.cpp\
-					./objects/KML/KML_Style.h\
-					./objects/KML/KML_StyleSelector.cpp\
-					./objects/KML/KML_StyleSelector.h\
-					./objects/KML/KML_SubStyle.cpp\
-					./objects/KML/KML_SubStyle.h\
-					./objects/KML/KMLFileReadUtils.cpp\
-					./objects/KML/KMLFileReadUtils.h\
-					./objects/Options/Option.cpp\
-					./objects/Options/Option.h\
-					./objects/Options/OptionDouble.cpp\
-					./objects/Options/OptionDouble.h\
-					./objects/Options/OptionLogical.cpp\
-					./objects/Options/OptionLogical.h\
-					./objects/Options/OptionChar.cpp\
-					./objects/Options/OptionChar.h\
-					./objects/Options/OptionStruct.cpp\
-					./objects/Options/OptionStruct.h\
-					./objects/Options/OptionCell.cpp\
-					./objects/Options/OptionCell.h\
-					./objects/Options/OptionUtilities.cpp\
-					./objects/Options/OptionUtilities.h\
 					./objects/Update.h\
 					./objects/Element.h\
@@ -848,6 +734,8 @@
 					./objects/Loads/Friction.h\
 					./objects/Loads/Friction.cpp\
-					./objects/DakotaPlugin.h\
-					./objects/DakotaPlugin.cpp\
+					./objects/Inputs/TransientInput.h\
+					./objects/Inputs/TransientInput.cpp\
+					./objects/Constraints/SpcTransient.cpp\
+					./objects/Constraints/SpcTransient.h\
 					./objects/DofIndexing.h\
 					./objects/DofIndexing.cpp\
@@ -869,6 +757,4 @@
 					./objects/ElementResults/TriaVertexElementResult.h\
 					./objects/ElementResults/TriaVertexElementResult.cpp\
-					./objects/ElementResults/PentaVertexElementResult.h\
-					./objects/ElementResults/PentaVertexElementResult.cpp\
 					./objects/ElementResults/BoolElementResult.h\
 					./objects/ElementResults/BoolElementResult.cpp\
@@ -898,6 +784,4 @@
 					./objects/Inputs/TriaVertexInput.h\
 					./objects/Inputs/TriaVertexInput.cpp\
-					./objects/Inputs/PentaVertexInput.h\
-					./objects/Inputs/PentaVertexInput.cpp\
 					./objects/Inputs/BoolInput.h\
 					./objects/Inputs/BoolInput.cpp\
@@ -906,16 +790,6 @@
 					./objects/Inputs/DoubleInput.h\
 					./objects/Inputs/DoubleInput.cpp\
-					./objects/Inputs/ControlInput.h\
-					./objects/Inputs/ControlInput.cpp\
 					./objects/Inputs/DatasetInput.h\
 					./objects/Inputs/DatasetInput.cpp\
-					./objects/Inputs/TransientInput.h\
-					./objects/Inputs/TransientInput.cpp\
-					./objects/Elements/Penta.h\
-					./objects/Elements/Penta.cpp\
-					./objects/Elements/PentaHook.h\
-					./objects/Elements/PentaHook.cpp\
-					./objects/Elements/PentaRef.h\
-					./objects/Elements/PentaRef.cpp\
 					./objects/Materials/Matice.h\
 					./objects/Materials/Matice.cpp\
@@ -927,6 +801,4 @@
 					./objects/Constraints/SpcDynamic.cpp\
 					./objects/Constraints/SpcDynamic.h\
-					./objects/Constraints/SpcTransient.cpp\
-					./objects/Constraints/SpcTransient.h\
 					./objects/Loads/Penpair.cpp\
 					./objects/Loads/Penpair.h\
@@ -935,6 +807,4 @@
 					./objects/Loads/Icefront.cpp\
 					./objects/Loads/Icefront.h\
-					./objects/Loads/Riftfront.cpp\
-					./objects/Loads/Riftfront.h\
 					./objects/Loads/Numericalflux.cpp\
 					./objects/Loads/Numericalflux.h\
@@ -994,14 +864,6 @@
 					./Container/Vertices.cpp\
 					./shared/shared.h\
-					./shared/Threads/issm_threads.h\
-					./shared/Threads/LaunchThread.cpp\
-					./shared/Threads/PartitionRange.cpp\
 					./shared/Alloc/alloc.h\
 					./shared/Alloc/alloc.cpp\
-					./shared/Matlab/matlabshared.h\
-					./shared/Matlab/ModuleBoot.cpp\
-					./shared/Matlab/mxGetAssignedField.cpp\
-					./shared/Matlab/mxGetField.cpp\
-					./shared/Matlab/CheckNumMatlabArguments.cpp\
 					./shared/Matrix/matrix.h\
 					./shared/Matrix/MatrixUtils.cpp\
@@ -1016,7 +878,4 @@
 					./shared/Numerics/cross.cpp\
 					./shared/Numerics/norm.cpp\
-					./shared/Numerics/BrentSearch.cpp\
-					./shared/Numerics/OptimalSearch.cpp\
-					./shared/Numerics/OptFunc.cpp\
 					./shared/Numerics/extrema.cpp\
 					./shared/Numerics/UnitConversion.cpp\
@@ -1025,15 +884,4 @@
 					./shared/Exceptions/Exceptions.cpp\
 					./shared/Exceptions/exprintf.cpp\
-					./shared/Exp/exp.h\
-					./shared/Exp/IsInPoly.cpp\
-					./shared/Exp/IsInPolySerial.cpp\
-					./shared/Exp/DomainOutlineRead.cpp\
-					./shared/Exp/DomainOutlineWrite.cpp\
-					./shared/TriMesh/trimesh.h\
-					./shared/TriMesh/AssociateSegmentToElement.cpp\
-					./shared/TriMesh/GridInsideHole.cpp\
-					./shared/TriMesh/OrderSegments.cpp\
-					./shared/TriMesh/SplitMeshForRifts.cpp\
-					./shared/TriMesh/TriMeshUtils.cpp\
 					./shared/Sorting/binary_search.cpp\
 					./shared/Sorting/sorting.h\
@@ -1046,13 +894,4 @@
 					./shared/Elements/GetNumberOfDofs.cpp\
 					./shared/String/sharedstring.h\
-					./shared/Bamg/Abs.h \
-					./shared/Bamg/BigPrimeNumber.h\
-					./shared/Bamg/BigPrimeNumber.cpp\
-					./shared/Bamg/BinaryRand.h \
-					./shared/Bamg/det.h \
-					./shared/Bamg/Exchange.h \
-					./shared/Bamg/extrema.h \
-					./shared/Bamg/HeapSort.h \
-					./shared/Bamg/OppositeAngle.h \
 					./toolkits/petsc\
 					./toolkits/petsc/patches\
@@ -1098,22 +937,7 @@
 					./io/Disk/pfopen.cpp\
 					./io/Disk/pfclose.cpp\
-					./io/Matlab/matlabio.h\
-					./io/Matlab/WriteMatlabData.cpp\
-					./io/Matlab/FetchMatlabData.cpp\
-					./io/Matlab/OptionParse.cpp\
 					./io/PrintfFunction.cpp\
 					./EnumDefinitions/EnumDefinitions.h\
 					./EnumDefinitions/EnumToModelField.cpp\
-					./modules/AddExternalResultx/AddExternalResultx.h\
-					./modules/AddExternalResultx/AddExternalResultx.cpp\
-					./modules/Chacox/Chacox.h\
-					./modules/Chacox/Chacox.cpp\
-					./modules/Chacox/input_parse.cpp\
-					./modules/Chacox/chaco_seconds.cpp\
-					./modules/Chacox/user_params.cpp\
-					./modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp\
-					./modules/GroundingLineMigrationx/GroundingLineMigrationx.h\
-					./modules/GroundingLineMigrationx/GroundingLineMigrationxLocal.h\
-					./modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp\
 					./modules/ModelProcessorx/ModelProcessorx.h\
 					./modules/ModelProcessorx/ModelProcessorx.cpp\
@@ -1128,52 +952,4 @@
 					./modules/ModelProcessorx/CreateNumberNodeToElementConnectivity.cpp\
 					./modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp\
-					./modules/ModelProcessorx/DiagnosticHoriz/UpdateElementsDiagnosticHoriz.cpp\
-					./modules/ModelProcessorx/DiagnosticHoriz/CreateNodesDiagnosticHoriz.cpp \
-					./modules/ModelProcessorx/DiagnosticHoriz/CreateConstraintsDiagnosticHoriz.cpp \
-					./modules/ModelProcessorx/DiagnosticHoriz/CreateLoadsDiagnosticHoriz.cpp\
-					./modules/ModelProcessorx/DiagnosticVert/UpdateElementsDiagnosticVert.cpp\
-					./modules/ModelProcessorx/DiagnosticVert/CreateNodesDiagnosticVert.cpp \
-					./modules/ModelProcessorx/DiagnosticVert/CreateConstraintsDiagnosticVert.cpp \
-					./modules/ModelProcessorx/DiagnosticVert/CreateLoadsDiagnosticVert.cpp\
-					./modules/ModelProcessorx/DiagnosticHutter/UpdateElementsDiagnosticHutter.cpp\
-					./modules/ModelProcessorx/DiagnosticHutter/CreateNodesDiagnosticHutter.cpp \
-					./modules/ModelProcessorx/DiagnosticHutter/CreateConstraintsDiagnosticHutter.cpp \
-					./modules/ModelProcessorx/DiagnosticHutter/CreateLoadsDiagnosticHutter.cpp\
-					./modules/ModelProcessorx/BedSlope/UpdateElementsBedSlope.cpp\
-					./modules/ModelProcessorx/BedSlope/CreateNodesBedSlope.cpp \
-					./modules/ModelProcessorx/BedSlope/CreateConstraintsBedSlope.cpp\
-					./modules/ModelProcessorx/BedSlope/CreateLoadsBedSlope.cpp\
-					./modules/ModelProcessorx/SurfaceSlope/UpdateElementsSurfaceSlope.cpp\
-					./modules/ModelProcessorx/SurfaceSlope/CreateNodesSurfaceSlope.cpp \
-					./modules/ModelProcessorx/SurfaceSlope/CreateConstraintsSurfaceSlope.cpp\
-					./modules/ModelProcessorx/SurfaceSlope/CreateLoadsSurfaceSlope.cpp\
-					./modules/ModelProcessorx/Control/CreateParametersControl.cpp\
-					./modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp\
-					./modules/ModelProcessorx/Thermal/UpdateElementsThermal.cpp\
-					./modules/ModelProcessorx/Thermal/CreateNodesThermal.cpp\
-					./modules/ModelProcessorx/Thermal/CreateConstraintsThermal.cpp\
-					./modules/ModelProcessorx/Thermal/CreateLoadsThermal.cpp\
-					./modules/ModelProcessorx/Enthalpy/UpdateElementsEnthalpy.cpp\
-					./modules/ModelProcessorx/Enthalpy/CreateNodesEnthalpy.cpp\
-					./modules/ModelProcessorx/Enthalpy/CreateConstraintsEnthalpy.cpp\
-					./modules/ModelProcessorx/Enthalpy/CreateLoadsEnthalpy.cpp\
-					./modules/ModelProcessorx/Hydrology/UpdateElementsHydrology.cpp\
-					./modules/ModelProcessorx/Hydrology/CreateNodesHydrology.cpp\
-					./modules/ModelProcessorx/Hydrology/CreateConstraintsHydrology.cpp\
-					./modules/ModelProcessorx/Hydrology/CreateLoadsHydrology.cpp\
-					./modules/ModelProcessorx/Melting/UpdateElementsMelting.cpp\
-					./modules/ModelProcessorx/Melting/CreateNodesMelting.cpp\
-					./modules/ModelProcessorx/Melting/CreateConstraintsMelting.cpp\
-					./modules/ModelProcessorx/Melting/CreateLoadsMelting.cpp\
-					./modules/ModelProcessorx/Prognostic/UpdateElementsPrognostic.cpp\
-					./modules/ModelProcessorx/Prognostic/CreateNodesPrognostic.cpp\
-					./modules/ModelProcessorx/Prognostic/CreateConstraintsPrognostic.cpp\
-					./modules/ModelProcessorx/Prognostic/CreateLoadsPrognostic.cpp\
-					./modules/ModelProcessorx/Balancethickness/UpdateElementsBalancethickness.cpp\
-					./modules/ModelProcessorx/Balancethickness/CreateNodesBalancethickness.cpp\
-					./modules/ModelProcessorx/Balancethickness/CreateConstraintsBalancethickness.cpp\
-					./modules/ModelProcessorx/Balancethickness/CreateLoadsBalancethickness.cpp\
-					./modules/ModelProcessorx/Transient/UpdateElementsTransient.cpp\
-					./modules/ModelProcessorx/Qmu/CreateParametersQmu.cpp\
 					./modules/ParsePetscOptionsx/ParsePetscOptionsx.h\
 					./modules/ParsePetscOptionsx/ParsePetscOptionsx.cpp\
@@ -1182,86 +958,24 @@
 					./modules/NodalValuex/NodalValuex.h\
 					./modules/NodalValuex/NodalValuex.cpp\
-					./modules/TriaSearchx/TriaSearchx.h\
-					./modules/TriaSearchx/TriaSearchx.cpp\
 					./modules/VerticesDofx/VerticesDofx.h\
 					./modules/VerticesDofx/VerticesDofx.cpp\
 					./modules/OutputResultsx/OutputResultsx.h\
 					./modules/OutputResultsx/OutputResultsx.cpp\
-					./modules/MinVelx/MinVelx.h\
-					./modules/MinVelx/MinVelx.cpp\
-					./modules/MaxVelx/MaxVelx.h\
-					./modules/MaxVelx/MaxVelx.cpp\
-					./modules/MaxAbsVxx/MaxAbsVxx.h\
-					./modules/MaxAbsVxx/MaxAbsVxx.cpp\
-					./modules/MaxAbsVyx/MaxAbsVyx.h\
-					./modules/MaxAbsVyx/MaxAbsVyx.cpp\
-					./modules/MaxAbsVzx/MaxAbsVzx.h\
-					./modules/MaxAbsVzx/MaxAbsVzx.cpp\
-					./modules/MaxVxx/MaxVxx.h\
-					./modules/MaxVxx/MaxVxx.cpp\
-					./modules/MaxVyx/MaxVyx.h\
-					./modules/MaxVyx/MaxVyx.cpp\
-					./modules/MaxVzx/MaxVzx.h\
-					./modules/MaxVzx/MaxVzx.cpp\
-					./modules/MinVxx/MinVxx.h\
-					./modules/MinVxx/MinVxx.cpp\
-					./modules/MinVyx/MinVyx.h\
-					./modules/MinVyx/MinVyx.cpp\
-					./modules/MinVzx/MinVzx.h\
-					./modules/MinVzx/MinVzx.cpp\
-					./modules/KMLMeshWritex/KMLFileReadx.h\
-					./modules/KMLMeshWritex/KMLFileReadx.cpp\
-					./modules/KMLMeshWritex/KMLMeshWritex.h\
-					./modules/KMLMeshWritex/KMLMeshWritex.cpp\
-					./modules/KMLOverlayx/KMLOverlayx.h\
-					./modules/KMLOverlayx/KMLOverlayx.cpp\
-					./modules/Xy2llx/Xy2llx.h\
-					./modules/Xy2llx/Xy2llx.cpp\
-					./modules/Ll2xyx/Ll2xyx.h\
-					./modules/Ll2xyx/Ll2xyx.cpp\
-					./modules/Exp2Kmlx/Exp2Kmlx.cpp\
-					./modules/Exp2Kmlx/Exp2Kmlx.cpp\
-					./modules/Kml2Expx/Kml2Expx.cpp\
-					./modules/Kml2Expx/Kml2Expx.cpp\
 					./modules/InputDuplicatex/InputDuplicatex.h\
 					./modules/InputDuplicatex/InputDuplicatex.cpp\
 					./modules/InputScalex/InputScalex.h\
 					./modules/InputScalex/InputScalex.cpp\
-					./modules/InputControlUpdatex/InputControlUpdatex.h\
-					./modules/InputControlUpdatex/InputControlUpdatex.cpp\
 					./modules/SurfaceAreax/SurfaceAreax.h\
 					./modules/SurfaceAreax/SurfaceAreax.cpp\
-					./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.h\
-					./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.cpp\
-					./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.h\
-					./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.cpp\
-					./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.h\
-					./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.cpp\
-					./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.h\
-					./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.cpp\
-					./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.h\
-					./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.cpp\
-					./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.h\
-					./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.cpp\
-					./modules/CostFunctionx/CostFunctionx.h\
-					./modules/CostFunctionx/CostFunctionx.cpp\
 					./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.h\
 					./modules/CreateNodalConstraintsx/CreateNodalConstraintsx.cpp\
-					./modules/Orthx/Orthx.h\
-					./modules/Orthx/Orthx.cpp\
 					./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.h\
 					./modules/UpdateDynamicConstraintsx/UpdateDynamicConstraintsx.cpp\
-					./modules/Gradjx/Gradjx.h\
-					./modules/Gradjx/Gradjx.cpp\
 					./modules/IoModelToConstraintsx/IoModelToConstraintsx.h\
 					./modules/IoModelToConstraintsx/IoModelToConstraintsx.cpp\
 					./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.h\
 					./modules/InputUpdateFromConstantx/InputUpdateFromConstantx.cpp\
-					./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.h\
-					./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.cpp\
 					./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.h\
 					./modules/InputUpdateFromSolutionx/InputUpdateFromSolutionx.cpp\
-					./modules/DakotaResponsesx/DakotaResponsesx.h\
-					./modules/DakotaResponsesx/DakotaResponsesx.cpp\
 					./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.h\
 					./modules/GetSolutionFromInputsx/GetSolutionFromInputsx.cpp\
@@ -1270,6 +984,4 @@
 					./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.h\
 					./modules/InputUpdateFromVectorx/InputUpdateFromVectorx.cpp\
-					./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.h\
-					./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.cpp\
 					./modules/InputArtificialNoisex/InputArtificialNoisex.h\
 					./modules/InputArtificialNoisex/InputArtificialNoisex.cpp\
@@ -1288,35 +1000,6 @@
 					./modules/UpdateConstraintsx/UpdateConstraintsx.h\
 					./modules/UpdateConstraintsx/UpdateConstraintsx.cpp\
-					./modules/InterpFromGridToMeshx/InterpFromGridToMeshx.cpp\
-					./modules/InterpFromGridToMeshx/InterpFromGridToMeshx.h\
-					./modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp\
-					./modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp\
-					./modules/InterpFromMesh2dx/InterpFromMesh2dx.h\
-					./modules/InterpFromMeshToMesh2dx/InterpFromMeshToMesh2dx.cpp\
-					./modules/InterpFromMeshToMesh2dx/InterpFromMeshToMesh2dx.h\
-					./modules/InterpFromMeshToMesh3dx/InterpFromMeshToMesh3dx.cpp\
-					./modules/InterpFromMeshToMesh3dx/InterpFromMeshToMesh3dx.h\
-					./modules/InterpFromMeshToGridx/InterpFromMeshToGridx.cpp\
-					./modules/InterpFromMeshToGridx/InterpFromMeshToGridx.h\
-					./modules/HoleFillerx/HoleFillerx.cpp\
-					./modules/HoleFillerx/HoleFillerx.h\
-					./modules/AverageFilterx/AverageFilterx.cpp\
-					./modules/AverageFilterx/AverageFilterx.h\
-					./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
-					./modules/AverageOntoPartitionx/AverageOntoPartitionx.h\
 					./modules/MeshPartitionx/MeshPartitionx.cpp\
 					./modules/MeshPartitionx/MeshPartitionx.h\
-					./modules/MeshProfileIntersectionx/MeshProfileIntersectionx.cpp\
-					./modules/MeshProfileIntersectionx/MeshProfileIntersectionx.h\
-					./modules/MeshProfileIntersectionx/MeshSegmentsIntersection.cpp\
-					./modules/MeshProfileIntersectionx/ElementSegmentsIntersection.cpp\
-					./modules/MeshProfileIntersectionx/ElementSegment.cpp\
-					./modules/MeshProfileIntersectionx/SegmentIntersect.cpp\
-					./modules/MeshProfileIntersectionx/NodeInElement.cpp\
-					./modules/ContourToMeshx/ContourToMeshx.cpp\
-					./modules/ContourToMeshx/ContourToMeshxt.cpp\
-					./modules/ContourToMeshx/ContourToMeshx.h\
-					./modules/Reducevectorgtosx/Reducevectorgtosx.cpp\
-					./modules/Reducevectorgtosx/Reducevectorgtosx.h\
 					./modules/Reducevectorgtofx/Reducevectorgtofx.cpp\
 					./modules/Reducevectorgtofx/Reducevectorgtofx.h\
@@ -1327,12 +1010,4 @@
 					./modules/StringToEnumx/StringToEnumx.cpp\
 					./modules/StringToEnumx/StringToEnumx.h\
-					./modules/MassFluxx/MassFluxx.cpp\
-					./modules/MassFluxx/MassFluxx.h\
-					./modules/ControlInputGetGradientx/ControlInputGetGradientx.cpp\
-					./modules/ControlInputGetGradientx/ControlInputGetGradientx.h\
-					./modules/ControlInputSetGradientx/ControlInputSetGradientx.cpp\
-					./modules/ControlInputSetGradientx/ControlInputSetGradientx.h\
-					./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.cpp\
-					./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.h\
 					./modules/SystemMatricesx/SystemMatricesx.cpp\
 					./modules/SystemMatricesx/SystemMatricesx.h\
@@ -1340,7 +1015,4 @@
 					./modules/ConstraintsStatex/ConstraintsStatex.h\
 					./modules/ConstraintsStatex/ConstraintsStateLocal.h\
-					./modules/ConstraintsStatex/RiftConstraintsState.cpp\
-					./modules/ConstraintsStatex/ThermalConstraintsState.cpp\
-					./modules/ConstraintsStatex/ThermalIsPresent.cpp\
 					./modules/Responsex/Responsex.h\
 					./modules/Responsex/Responsex.cpp\
@@ -1349,5 +1021,4 @@
 					./modules/ResetConstraintsx/ResetConstraintsx.h\
 					./modules/ResetConstraintsx/ResetConstraintsx.cpp\
-					./modules/ResetConstraintsx/ThermalConstraintsReset.cpp\
 					./modules/Solverx/Solverx.cpp\
 					./modules/Solverx/Solverx.h\
@@ -1355,68 +1026,262 @@
 					./modules/VecMergex/VecMergex.cpp\
 					./modules/VecMergex/VecMergex.h\
-					./modules/Scotchx/Scotchx.cpp\
-					./modules/Scotchx/Scotchx.h\
 					./modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp\
 					./modules/Mergesolutionfromftogx/Mergesolutionfromftogx.h\
-					./modules/Dakotax/Dakotax.h\
-					./modules/Dakotax/Dakotax.cpp\
-					./modules/Dakotax/DakotaMPI_Bcast.cpp\
-					./modules/Dakotax/DakotaFree.cpp\
-					./modules/Dakotax/SpawnCore.cpp\
-					./modules/Dakotax/SpawnCoreParallel.cpp\
-					./modules/Dakotax/DescriptorIndex.cpp\
 					./modules/InputToResultx/InputToResultx.cpp\
 					./modules/InputToResultx/InputToResultx.h\
 					./modules/InputConvergencex/InputConvergencex.cpp\
 					./modules/InputConvergencex/InputConvergencex.h\
-					./modules/OutputRiftsx/OutputRiftsx.h\
-					./modules/OutputRiftsx/OutputRiftsx.cpp\
-					./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.cpp\
-					./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.h\
-					./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.cpp\
-					./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.h\
-					./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.cpp\
-					./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.h\
-					./modules/RheologyBbarx/RheologyBbarx.cpp\
-					./modules/RheologyBbarx/RheologyBbarx.h\
-					./solutions/diagnostic_core.cpp\
 					./solutions/convergence.cpp\
-					./solutions/thermal_core.cpp\
-					./solutions/thermal_core_step.cpp\
-					./solutions/enthalpy_core.cpp\
 					./solutions/WriteLockFile.cpp\
-					./solutions/control_core.cpp\
-					./solutions/controltao_core.cpp\
-					./solutions/controlrestart.cpp\
-					./solutions/controlconvergence.cpp\
-					./solutions/objectivefunctionC.cpp\
-					./solutions/gradient_core.cpp\
-					./solutions/adjointdiagnostic_core.cpp\
-					./solutions/adjointbalancethickness_core.cpp\
-					./solutions/prognostic_core.cpp\
-					./solutions/balancethickness_core.cpp\
-					./solutions/surfaceslope_core.cpp\
-					./solutions/bedslope_core.cpp\
-					./solutions/hydrology_core.cpp\
-					./solutions/hydrology_core_step.cpp\
-					./solutions/transient_core.cpp\
-					./solutions/groundinglinemigration2d_core.cpp\
-					./solutions/steadystate_core.cpp\
-					./solutions/steadystateconvergence.cpp\
 					./solutions/ResetBoundaryConditions.cpp\
 					./solutions/AnalysisConfiguration.cpp\
 					./solutions/CorePointerFromSolutionEnum.cpp\
-					./solutions/AdjointCorePointerFromSolutionEnum.cpp\
 					./solvers/solver_linear.cpp\
-					./solvers/solver_adjoint_linear.cpp\
-					./solvers/solver_nonlinear.cpp\
-					./solvers/solver_stokescoupling_nonlinear.cpp\
-					./solvers/solver_thermal_nonlinear.cpp\
-					./modules/Bamgx/Bamgx.cpp\
-					./modules/Bamgx/Bamgx.h\
-					./modules/BamgConvertMeshx/BamgConvertMeshx.cpp\
-					./modules/BamgConvertMeshx/BamgConvertMeshx.h
-
-libpISSM_a_CXXFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(CXXOPTFLAGS)
+					./solvers/solver_nonlinear.cpp
+
+
+libpISSM_a_CXXFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(CXXOPTFLAGS) 
+#}}}
+#Overload library, to overload any non-standard symbols. {{{1
+libOverload_a_SOURCES = ./shared/String/stricmp.c
+libOverload_a_CFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(COPTFLAGS)
+#}}}
+#DAKOTA sources  {{{1
+if DAKOTA
+libpISSM_a_SOURCES +=  ./objects/DakotaPlugin.h\
+					  ./objects/DakotaPlugin.cpp\
+					  ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.h\
+					  ./modules/InputUpdateFromDakotax/InputUpdateFromDakotax.cpp\
+					  ./modules/DakotaResponsesx/DakotaResponsesx.h\
+					  ./modules/DakotaResponsesx/DakotaResponsesx.cpp\
+					  ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.h\
+					  ./modules/InputUpdateFromVectorDakotax/InputUpdateFromVectorDakotax.cpp\
+					  ./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
+					  ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h\
+					  ./modules/Dakotax/Dakotax.h\
+					  ./modules/Dakotax/Dakotax.cpp\
+					  ./modules/Dakotax/DakotaMPI_Bcast.cpp\
+					  ./modules/Dakotax/DakotaFree.cpp\
+					  ./modules/Dakotax/SpawnCore.cpp\
+					  ./modules/Dakotax/SpawnCoreParallel.cpp\
+					  ./modules/Dakotax/DescriptorIndex.cpp\
+					  ./modules/AverageOntoPartitionx/AverageOntoPartitionx.cpp\
+					  ./modules/ModelProcessorx/Qmu/CreateParametersQmu.cpp\
+					  ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h
+endif
+#}}}
+#Transient sources  {{{1
+if TRANSIENT
+libpISSM_a_SOURCES +=  ./solutions/transient_core.cpp\
+					   ./modules/ModelProcessorx/Transient/UpdateElementsTransient.cpp
+endif
+#}}}
+#Steadystate sources  {{{1
+if STEADYSTATE
+libpISSM_a_SOURCES += ./solutions/steadystate_core.cpp\
+					  ./solutions/steadystateconvergence.cpp
+endif
+#}}}
+#Prognostic sources  {{{1
+if PROGNOSTIC
+libpISSM_a_SOURCES +=  ./solutions/prognostic_core.cpp\
+					   ./modules/ModelProcessorx/Prognostic/UpdateElementsPrognostic.cpp\
+					   ./modules/ModelProcessorx/Prognostic/CreateNodesPrognostic.cpp\
+					   ./modules/ModelProcessorx/Prognostic/CreateConstraintsPrognostic.cpp\
+					   ./modules/ModelProcessorx/Prognostic/CreateLoadsPrognostic.cpp
+
+endif
+#}}}
+#Thermal sources  {{{1
+if THERMAL
+libpISSM_a_SOURCES +=  ./solutions/thermal_core.cpp\
+					   ./solutions/thermal_core_step.cpp\
+					   ./solutions/enthalpy_core.cpp\
+					   ./solvers/solver_thermal_nonlinear.cpp\
+					   ./modules/ModelProcessorx/Thermal/UpdateElementsThermal.cpp\
+					   ./modules/ModelProcessorx/Thermal/CreateNodesThermal.cpp\
+					   ./modules/ModelProcessorx/Thermal/CreateConstraintsThermal.cpp\
+					   ./modules/ModelProcessorx/Thermal/CreateLoadsThermal.cpp\
+					   ./modules/ModelProcessorx/Enthalpy/UpdateElementsEnthalpy.cpp\
+					   ./modules/ModelProcessorx/Enthalpy/CreateNodesEnthalpy.cpp\
+					   ./modules/ModelProcessorx/Enthalpy/CreateConstraintsEnthalpy.cpp\
+					   ./modules/ModelProcessorx/Enthalpy/CreateLoadsEnthalpy.cpp\
+					   ./modules/ModelProcessorx/Melting/UpdateElementsMelting.cpp\
+					   ./modules/ModelProcessorx/Melting/CreateNodesMelting.cpp\
+					   ./modules/ModelProcessorx/Melting/CreateConstraintsMelting.cpp\
+					   ./modules/ModelProcessorx/Melting/CreateLoadsMelting.cpp\
+					   ./modules/ConstraintsStatex/ThermalConstraintsState.cpp\
+					   ./modules/ConstraintsStatex/ThermalIsPresent.cpp\
+					   ./modules/ResetConstraintsx/ThermalConstraintsReset.cpp
+endif
+#}}}
+#Control sources  {{{1
+if CONTROL
+libpISSM_a_SOURCES += ./solutions/control_core.cpp\
+					  ./solutions/controltao_core.cpp\
+					  ./solutions/controlrestart.cpp\
+					  ./solutions/controlconvergence.cpp\
+					  ./solutions/objectivefunctionC.cpp\
+					  ./solutions/gradient_core.cpp\
+					  ./solutions/adjointdiagnostic_core.cpp\
+					  ./solutions/adjointbalancethickness_core.cpp\
+					  ./solutions/AdjointCorePointerFromSolutionEnum.cpp\
+					  ./solvers/solver_adjoint_linear.cpp\
+					  ./modules/ControlInputGetGradientx/ControlInputGetGradientx.cpp\
+					  ./modules/ControlInputGetGradientx/ControlInputGetGradientx.h\
+					  ./modules/ControlInputSetGradientx/ControlInputSetGradientx.cpp\
+					  ./modules/ControlInputSetGradientx/ControlInputSetGradientx.h\
+					  ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.cpp\
+					  ./modules/ControlInputScaleGradientx/ControlInputScaleGradientx.h\
+					  ./modules/ModelProcessorx/Control/CreateParametersControl.cpp\
+					  ./modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp\
+					  ./modules/InputControlUpdatex/InputControlUpdatex.h\
+					  ./modules/InputControlUpdatex/InputControlUpdatex.cpp\
+					  ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.h\
+					  ./modules/SurfaceAbsVelMisfitx/SurfaceAbsVelMisfitx.cpp\
+					  ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.h\
+					  ./modules/SurfaceRelVelMisfitx/SurfaceRelVelMisfitx.cpp\
+					  ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.h\
+					  ./modules/SurfaceLogVelMisfitx/SurfaceLogVelMisfitx.cpp\
+					  ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.h\
+					  ./modules/SurfaceLogVxVyMisfitx/SurfaceLogVxVyMisfitx.cpp\
+					  ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.h\
+					  ./modules/SurfaceAverageVelMisfitx/SurfaceAverageVelMisfitx.cpp\
+					  ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.h\
+					  ./modules/ThicknessAbsMisfitx/ThicknessAbsMisfitx.cpp\
+					  ./modules/CostFunctionx/CostFunctionx.h\
+					  ./modules/CostFunctionx/CostFunctionx.cpp\
+					  ./modules/Orthx/Orthx.h\
+					  ./modules/Orthx/Orthx.cpp\
+					  ./modules/Gradjx/Gradjx.h\
+					  ./modules/Gradjx/Gradjx.cpp\
+					  ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.cpp\
+					  ./modules/DragCoefficientAbsGradientx/DragCoefficientAbsGradientx.h\
+					  ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.cpp\
+					  ./modules/ThicknessAbsGradientx/ThicknessAbsGradientx.h\
+					  ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.cpp\
+					  ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.h\
+					  ./objects/Inputs/ControlInput.h\
+					  ./objects/Inputs/ControlInput.cpp\
+					  ./shared/Numerics/BrentSearch.cpp\
+					  ./shared/Numerics/OptimalSearch.cpp\
+					  ./shared/Numerics/OptFunc.cpp
+endif
+#}}}
+#Hydrology sources  {{{1
+if HYDROLOGY
+libpISSM_a_SOURCES += ./modules/ModelProcessorx/Hydrology/UpdateElementsHydrology.cpp\
+					  ./modules/ModelProcessorx/Hydrology/CreateNodesHydrology.cpp\
+					  ./modules/ModelProcessorx/Hydrology/CreateConstraintsHydrology.cpp\
+					  ./modules/ModelProcessorx/Hydrology/CreateLoadsHydrology.cpp\
+					  ./solutions/hydrology_core.cpp\
+					  ./solutions/hydrology_core_step.cpp
+endif
+#}}}
+#Diagnostic sources  {{{1
+if DIAGNOSTIC
+libpISSM_a_SOURCES += ./modules/ModelProcessorx/DiagnosticHoriz/UpdateElementsDiagnosticHoriz.cpp\
+					  ./modules/ModelProcessorx/DiagnosticHoriz/CreateNodesDiagnosticHoriz.cpp \
+					  ./modules/ModelProcessorx/DiagnosticHoriz/CreateConstraintsDiagnosticHoriz.cpp \
+					  ./modules/ModelProcessorx/DiagnosticHoriz/CreateLoadsDiagnosticHoriz.cpp\
+					  ./modules/ModelProcessorx/DiagnosticVert/UpdateElementsDiagnosticVert.cpp\
+					  ./modules/ModelProcessorx/DiagnosticVert/CreateNodesDiagnosticVert.cpp \
+					  ./modules/ModelProcessorx/DiagnosticVert/CreateConstraintsDiagnosticVert.cpp \
+					  ./modules/ModelProcessorx/DiagnosticVert/CreateLoadsDiagnosticVert.cpp\
+					  ./modules/ModelProcessorx/DiagnosticHutter/UpdateElementsDiagnosticHutter.cpp\
+					  ./modules/ModelProcessorx/DiagnosticHutter/CreateNodesDiagnosticHutter.cpp \
+					  ./modules/ModelProcessorx/DiagnosticHutter/CreateConstraintsDiagnosticHutter.cpp \
+					  ./modules/ModelProcessorx/DiagnosticHutter/CreateLoadsDiagnosticHutter.cpp\
+					  ./solutions/diagnostic_core.cpp\
+					  ./solvers/solver_stokescoupling_nonlinear.cpp
+endif
+#}}}
+#Balanced sources  {{{1
+if BALANCED
+libpISSM_a_SOURCES += ./modules/ModelProcessorx/Balancethickness/UpdateElementsBalancethickness.cpp\
+					  ./modules/ModelProcessorx/Balancethickness/CreateNodesBalancethickness.cpp\
+					  ./modules/ModelProcessorx/Balancethickness/CreateConstraintsBalancethickness.cpp\
+					  ./modules/ModelProcessorx/Balancethickness/CreateLoadsBalancethickness.cpp\
+					  ./solutions/balancethickness_core.cpp
+endif
+#}}}
+#Responses sources  {{{1
+if RESPONSES
+libpISSM_a_SOURCES += ./modules/MinVelx/MinVelx.h\
+					  ./modules/MinVelx/MinVelx.cpp\
+					  ./modules/MaxVelx/MaxVelx.h\
+					  ./modules/MaxVelx/MaxVelx.cpp\
+					  ./modules/MaxAbsVxx/MaxAbsVxx.h\
+					  ./modules/MaxAbsVxx/MaxAbsVxx.cpp\
+					  ./modules/MaxAbsVyx/MaxAbsVyx.h\
+					  ./modules/MaxAbsVyx/MaxAbsVyx.cpp\
+					  ./modules/MaxAbsVzx/MaxAbsVzx.h\
+					  ./modules/MaxAbsVzx/MaxAbsVzx.cpp\
+					  ./modules/MaxVxx/MaxVxx.h\
+					  ./modules/MaxVxx/MaxVxx.cpp\
+					  ./modules/MaxVyx/MaxVyx.h\
+					  ./modules/MaxVyx/MaxVyx.cpp\
+					  ./modules/MaxVzx/MaxVzx.h\
+					  ./modules/MaxVzx/MaxVzx.cpp\
+					  ./modules/MinVxx/MinVxx.h\
+					  ./modules/MinVxx/MinVxx.cpp\
+					  ./modules/MinVyx/MinVyx.h\
+					  ./modules/MinVyx/MinVyx.cpp\
+					  ./modules/MinVzx/MinVzx.h\
+					  ./modules/MinVzx/MinVzx.cpp\
+					  ./modules/RheologyBbarx/RheologyBbarx.cpp\
+					  ./modules/RheologyBbarx/RheologyBbarx.h\
+					  ./modules/MassFluxx/MassFluxx.cpp\
+					  ./modules/MassFluxx/MassFluxx.h
+endif
+#}}}
+#Slope sources  {{{1
+if SLOPE
+libpISSM_a_SOURCES += ./modules/ModelProcessorx/BedSlope/UpdateElementsBedSlope.cpp\
+					  ./modules/ModelProcessorx/BedSlope/CreateNodesBedSlope.cpp \
+					  ./modules/ModelProcessorx/BedSlope/CreateConstraintsBedSlope.cpp\
+					  ./modules/ModelProcessorx/BedSlope/CreateLoadsBedSlope.cpp\
+					  ./modules/ModelProcessorx/SurfaceSlope/UpdateElementsSurfaceSlope.cpp\
+					  ./modules/ModelProcessorx/SurfaceSlope/CreateNodesSurfaceSlope.cpp \
+					  ./modules/ModelProcessorx/SurfaceSlope/CreateConstraintsSurfaceSlope.cpp\
+					  ./modules/ModelProcessorx/SurfaceSlope/CreateLoadsSurfaceSlope.cpp\
+					  ./solutions/surfaceslope_core.cpp\
+					  ./solutions/bedslope_core.cpp
+endif
+#}}}
+#GroundingLine sources  {{{1
+if GROUNDINGLINE
+libpISSM_a_SOURCES += ./modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp\
+					  ./modules/GroundingLineMigrationx/GroundingLineMigrationx.h\
+					  ./modules/GroundingLineMigrationx/GroundingLineMigrationxLocal.h\
+					  ./modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp\
+					  ./solutions/groundinglinemigration2d_core.cpp
+endif
+#}}}
+#Rifts sources  {{{1
+if RIFTS
+libpISSM_a_SOURCES += ./objects/Loads/Riftfront.cpp\
+					  ./objects/Loads/Riftfront.h\
+					  ./modules/ConstraintsStatex/RiftConstraintsState.cpp
+endif
+#}}}
+#3D sources  {{{1
+if THREED
+libpISSM_a_SOURCES += ./objects/Gauss/GaussPenta.h\
+					  ./objects/Gauss/GaussPenta.cpp\
+					  ./objects/ElementResults/PentaVertexElementResult.h\
+					  ./objects/ElementResults/PentaVertexElementResult.cpp\
+					  ./objects/Inputs/PentaVertexInput.h\
+					  ./objects/Inputs/PentaVertexInput.cpp\
+					  ./objects/Elements/Penta.h\
+					  ./objects/Elements/Penta.cpp\
+					  ./objects/Elements/PentaHook.h\
+					  ./objects/Elements/PentaHook.cpp\
+					  ./objects/Elements/PentaRef.h\
+					  ./objects/Elements/PentaRef.cpp
+endif
+#}}}
+
+#Executable {{{1
 
 if NOPARALLEL
@@ -1426,6 +1291,18 @@
 endif
 
-LDADD =    ./libpISSM.a $(PETSCLIB) $(TAOLIB) $(FLIBS) $(PLAPACKLIB)  $(MUMPSLIB) $(SCALAPACKLIB)  $(BLACSLIB) $(HYPRELIB) $(MLLIB) $(DAKOTALIB) $(METISLIB) $(CHACOLIB) $(SCOTCHLIB) $(BLASLAPACKLIB)  $(MKLLIB) $(MPILIB) $(MATHLIB) $(FORTRANLIB) $(GRAPHICSLIB) libOverload.a $(MULTITHREADINGLIB)
+#Standard libraries
+LDADD =      ./libpISSM.a ./libOverload.a
+
+if AD
+LDADD +=    ./libAD.a
+endif
+
+#External packages
+LDADD += $(PETSCLIB) $(TAOLIB) $(FLIBS) $(PLAPACKLIB)  $(MUMPSLIB) $(SCALAPACKLIB)  $(BLACSLIB) $(HYPRELIB) $(MLLIB) $(DAKOTALIB) $(METISLIB) $(CHACOLIB) $(SCOTCHLIB) $(BLASLAPACKLIB)  $(MKLLIB) $(MPILIB) $(MATHLIB) $(FORTRANLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(ADICLIB) 
+
 
 issm_exe_SOURCES = solutions/issm.cpp
-issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_  $(CXXOPTFLAGS) $(COPTFLAGS)
+issm_exe_CXXFLAGS= -fPIC -D_PARALLEL_  $(CXXOPTFLAGS) $(COPTFLAGS) 
+
+#}}}
+
Index: /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp	(revision 9774)
+++ /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp	(revision 9775)
@@ -69,5 +69,9 @@
 	_printf_(VerboseQmu(),"%s%s%s\n","Starting ",EnumToStringx(solution_type)," core:");
 	CorePointerFromSolutionEnum(&solutioncore,femmodel->parameters,solution_type);
+	#ifdef _HAVE_CONTROL_
 	if(control_analysis)solutioncore=&control_core;
+	#else
+	_error_("ISSM was not compiled with control capabilities, exiting!");
+	#endif
 
 	/*Run the core solution sequence: */
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp	(revision 9774)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp	(revision 9775)
@@ -32,4 +32,6 @@
 	/*Now, branch onto analysis dependent model generation: */
 	switch(analysis_type){
+
+		#ifdef _HAVE_DIAGNOSTIC_
 		case DiagnosticHorizAnalysisEnum:
 			CreateNodesDiagnosticHoriz(pnodes, iomodel);
@@ -52,19 +54,7 @@
 			UpdateElementsDiagnosticHutter(elements,iomodel,analysis_counter,analysis_type);
 			break;
-
-		case BedSlopeAnalysisEnum:
-			CreateNodesBedSlope(pnodes, iomodel);
-			CreateConstraintsBedSlope(pconstraints,iomodel);
-			CreateLoadsBedSlope(ploads,iomodel);
-			UpdateElementsBedSlope(elements,iomodel,analysis_counter,analysis_type);
-			break;
-
-		case SurfaceSlopeAnalysisEnum:
-			CreateNodesSurfaceSlope(pnodes, iomodel);
-			CreateConstraintsSurfaceSlope(pconstraints,iomodel);
-			CreateLoadsSurfaceSlope(ploads,iomodel);
-			UpdateElementsSurfaceSlope(elements,iomodel,analysis_counter,analysis_type);
-			break;
-
+		#endif
+		
+		#ifdef _HAVE_HYDROLOGY_
 		case HydrologyAnalysisEnum:
 			CreateNodesHydrology(pnodes, iomodel);
@@ -73,4 +63,5 @@
 			UpdateElementsHydrology(elements,iomodel,analysis_counter,analysis_type);
 			break;
+		#endif
 
 		#ifdef _HAVE_THERMAL_
@@ -97,4 +88,30 @@
 		#endif
 
+		#ifdef _HAVE_BALANCED_
+		case BalancethicknessAnalysisEnum:
+			CreateNodesBalancethickness(pnodes, iomodel);
+			CreateConstraintsBalancethickness(pconstraints,iomodel);
+			CreateLoadsBalancethickness(ploads,iomodel);
+			UpdateElementsBalancethickness(elements,iomodel,analysis_counter,analysis_type);
+			break;
+		#endif
+
+		#ifdef _HAVE_SLOPE_
+		case BedSlopeAnalysisEnum:
+			CreateNodesBedSlope(pnodes, iomodel);
+			CreateConstraintsBedSlope(pconstraints,iomodel);
+			CreateLoadsBedSlope(ploads,iomodel);
+			UpdateElementsBedSlope(elements,iomodel,analysis_counter,analysis_type);
+			break;
+
+		case SurfaceSlopeAnalysisEnum:
+			CreateNodesSurfaceSlope(pnodes, iomodel);
+			CreateConstraintsSurfaceSlope(pconstraints,iomodel);
+			CreateLoadsSurfaceSlope(ploads,iomodel);
+			UpdateElementsSurfaceSlope(elements,iomodel,analysis_counter,analysis_type);
+			break;
+		#endif
+
+		#ifdef _HAVE_PROGNOSTIC_
 		case PrognosticAnalysisEnum:
 			CreateNodesPrognostic(pnodes, iomodel);
@@ -103,11 +120,6 @@
 			UpdateElementsPrognostic(elements,iomodel,analysis_counter,analysis_type);
 			break;
+		#endif
 
-		case BalancethicknessAnalysisEnum:
-			CreateNodesBalancethickness(pnodes, iomodel);
-			CreateConstraintsBalancethickness(pconstraints,iomodel);
-			CreateLoadsBalancethickness(ploads,iomodel);
-			UpdateElementsBalancethickness(elements,iomodel,analysis_counter,analysis_type);
-			break;
 
 		default:
@@ -124,8 +136,10 @@
 
 	/*Update Elements in case we are running a transient solution: */
+	#ifdef _HAVE_TRANSIENT_
 	parameters=*pparameters;
 	if(analysis_counter==(nummodels-1)&& solution_type==TransientSolutionEnum){
 		UpdateElementsTransient(elements,parameters,iomodel,analysis_counter,analysis_type);
 	}
+	#endif
 
 	/*Sort datasets: */
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp	(revision 9774)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp	(revision 9775)
@@ -46,5 +46,7 @@
 	/*Fetch data needed: */
 	iomodel->FetchData(4,MeshElementsEnum,MeshElementconnectivityEnum,MaterialsRheologyBEnum,MaterialsRheologyNEnum);
+	#ifdef _HAVE_THREED_
 	if(dim==3)          iomodel->FetchData(2,MeshUpperelementsEnum,MeshLowerelementsEnum);
+	#endif
 	if(control_analysis)iomodel->FetchData(3,InversionControlParametersEnum,InversionMinParametersEnum,InversionMaxParametersEnum);
 	
@@ -55,5 +57,7 @@
 			/*Create and add tria element to elements dataset: */
 			if(dim==2) elements->AddObject(new Tria(i+1,i,i,iomodel,nummodels));
+	        #ifdef _HAVE_THREED_
 			else       elements->AddObject(new Penta(i+1,i,i,iomodel,nummodels));
+	        #endif
 
 			/*Create and add material property to materials dataset: */
Index: /issm/trunk/src/c/modules/Responsex/Responsex.cpp
===================================================================
--- /issm/trunk/src/c/modules/Responsex/Responsex.cpp	(revision 9774)
+++ /issm/trunk/src/c/modules/Responsex/Responsex.cpp	(revision 9775)
@@ -19,5 +19,6 @@
 
 	switch (StringToEnumx(response_descriptor)){
-		
+
+		#ifdef _HAVE_RESPONSES_
 		case MinVelEnum:                 MinVelx(                  responses, elements,nodes, vertices, loads, materials, parameters,process_units); break;
 		case MaxVelEnum:                 MaxVelx(                  responses, elements,nodes, vertices, loads, materials, parameters,process_units); break;
@@ -44,4 +45,7 @@
 		case FrictionCoefficientEnum:NodalValuex(responses, FrictionCoefficientEnum,elements,nodes, vertices, loads, materials, parameters,process_units); break;
 		default: _error_(" response descriptor \"%s\" not supported yet!",response_descriptor); break;
+		#else
+		default: _error_(" ISSM was not compiled with responses capabilities, exiting!");
+		#endif
 	}
 
Index: /issm/trunk/src/c/modules/modules.h
===================================================================
--- /issm/trunk/src/c/modules/modules.h	(revision 9774)
+++ /issm/trunk/src/c/modules/modules.h	(revision 9775)
@@ -84,5 +84,4 @@
 #include "./Orthx/Orthx.h"
 #include "./OutputResultsx/OutputResultsx.h"
-#include "./OutputRiftsx/OutputRiftsx.h"
 #include "./ConstraintsStatex/ConstraintsStatex.h"
 #include "./PointCloudFindNeighborsx/PointCloudFindNeighborsx.h"
Index: /issm/trunk/src/c/objects/Elements/Element.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Element.h	(revision 9774)
+++ /issm/trunk/src/c/objects/Elements/Element.h	(revision 9775)
@@ -69,5 +69,5 @@
 		virtual void   InputCreate(double scalar,int name,int code)=0;
 		virtual void   InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code)=0;
-				virtual void   ProcessResultsUnits(void)=0;
+		virtual void   ProcessResultsUnits(void)=0;
 		virtual void   RequestedOutput(int output_enum,int step,double time)=0;
 		virtual void   MinVel(double* pminvel, bool process_units)=0;
Index: /issm/trunk/src/c/objects/Elements/Penta.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 9774)
+++ /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 9775)
@@ -524,43 +524,4 @@
 }
 /*}}}*/
-/*FUNCTION Penta::CreateDVectorDiagnosticHoriz {{{1*/
-ElementVector* Penta::CreateDVectorDiagnosticHoriz(void){
-
-	int approximation;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	switch(approximation){
-		case StokesApproximationEnum:
-			return CreateDVectorDiagnosticStokes();
-		default:
-			return NULL; //no need for doftypes outside of stokes approximation
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::CreateDVectorDiagnosticStokes{{{1*/
-ElementVector* Penta::CreateDVectorDiagnosticStokes(void){
-
-	/*output: */
-	ElementVector* De=NULL;
-	/*intermediary: */
-	int approximation;
-	int i;
-
-	/*Initialize Element vector and return if necessary*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=StokesApproximationEnum) return NULL;
-
-	De=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	for (i=0;i<NUMVERTICES;i++){
-		De->values[i*4+0]=VelocityEnum;
-		De->values[i*4+1]=VelocityEnum;
-		De->values[i*4+2]=VelocityEnum;
-		De->values[i*4+3]=PressureEnum;
-	}
-
-	return De;
-}
-/*}}}*/
 /*FUNCTION Penta::CreateKMatrix {{{1*/
 void  Penta::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){
@@ -581,4 +542,5 @@
 	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
 	switch(analysis_type){
+		#ifdef _HAVE_DIAGNOSTIC_
 		case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum:
 			Ke=CreateKMatrixDiagnosticHoriz(); De=CreateDVectorDiagnosticHoriz();
@@ -590,4 +552,5 @@
 			Ke=CreateKMatrixDiagnosticVert();
 			break;
+		#endif
 		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
 			Ke=CreateKMatrixSlope();
@@ -596,7 +559,9 @@
 			Ke=CreateKMatrixPrognostic();
 			break;
+		#ifdef _HAVE_BALANCED_
 		case BalancethicknessAnalysisEnum:
 			Ke=CreateKMatrixBalancethickness();
 			break;
+		#endif
 		#ifdef _HAVE_THERMAL_
 		case ThermalAnalysisEnum:
@@ -626,10 +591,7 @@
 }
 /*}}}*/
-/*FUNCTION Penta::CreateKMatrixBalancethickness {{{1*/
-ElementMatrix* Penta::CreateKMatrixBalancethickness(void){
-
-	/*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 
-	  bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build 
-	  the stiffness matrix. */
+/*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/
+ElementMatrix* Penta::CreateKMatrixPrognostic(void){
+
 	if (!IsOnBed()) return NULL;
 
@@ -638,7 +600,6 @@
 	this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
 
-	/*Spawn Tria element from the base of the Penta: */
 	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixBalancethickness();
+	ElementMatrix* Ke=tria->CreateKMatrixPrognostic();
 	delete tria->matice; delete tria;
 
@@ -651,1134 +612,4 @@
 }
 /*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){
-	
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous();
-	ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction();
-	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
-	
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){
-
-	/*Constants*/
-	const int    numdofm=NDOF2*NUMVERTICES2D;
-	const int    numdofp=NDOF2*NUMVERTICES;
-	const int    numdoftotal=2*NDOF2*NUMVERTICES;
-
-	/*Intermediaries */
-	int         i,j,ig;
-	double      Jdet;
-	double      viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
-	double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
-	double      xyz_list[NUMVERTICES][3];
-	double      B[3][numdofp];
-	double      Bprime[3][numdofm];
-	double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
-	double      D_scalar;
-	double      Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix 
-	double      Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point.
-	GaussPenta *gauss=NULL;
-	GaussTria  *gauss_tria=NULL;
-
-	/*Find penta on bed as pattyn must be coupled to the dofs on the bed: */
-	Penta* pentabase=GetBasalElement();
-	Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-	ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,PattynApproximationEnum);
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-	delete Ke1; delete Ke2;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
-	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
-	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	gauss_tria=new GaussTria();
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-		gauss->SynchronizeGaussTria(gauss_tria);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss);
-		tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
-
-		this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
-		this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
-		matice->GetViscosity3d(&viscosity, &epsilon[0]);
-		matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
-
-		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
-		D_scalar=2*newviscosity*gauss->weight*Jdet;
-		for (i=0;i<3;i++) D[i][i]=D_scalar;
-
-		TripleMultiply( &B[0][0],3,numdofp,1,
-					&D[0][0],3,3,0,
-					&Bprime[0][0],3,numdofm,0,
-					&Ke_gg_gaussian[0][0],0);
-
-		for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
-	} 
-	for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
-	for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i];
-
-	/*Clean-up and return*/
-	delete tria->matice; delete tria;
-	delete gauss;
-	delete gauss_tria;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){
-
-	/*Constants*/
-	const int numdof        = NDOF2 *NUMVERTICES;
-	const int numdoftotal   = NDOF4 *NUMVERTICES;
-	
-	/*Intermediaries */
-	int       i,j,ig,analysis_type;
-	double    Jdet2d,slope_magnitude,alpha2;
-	double    xyz_list[NUMVERTICES][3];
-	double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double    slope[3]={0.0,0.0,0.0};
-	double    MAXSLOPE=.06; // 6 %
-	double    MOUNTAINKEXPONENT=10;
-	double    L[2][numdof];
-	double    DL[2][2]                  ={{ 0,0 },{0,0}}; //for basal drag
-	double    DL_scalar;
-	double    Ke_gg[numdof][numdof]     ={0.0};
-	double    Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
-	Friction  *friction = NULL;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix and return if necessary*/
-	if(IsOnShelf() || !IsOnBed()) return NULL;
-	ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-	ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
-	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
-	delete Ke1; delete Ke2;
-
-	/*retrieve inputs :*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
-
-	/*build friction object, used later on: */
-	friction=new Friction("2d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/*Friction: */
-		friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
-
-		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
-		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
-		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
-
-		if (slope_magnitude>MAXSLOPE){
-			alpha2=pow((double)10,MOUNTAINKEXPONENT);
-		}
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
-		GetL(&L[0][0], gauss,NDOF2);
-
-		DL_scalar=alpha2*gauss->weight*Jdet2d;
-		for (i=0;i<2;i++) DL[i][i]=DL_scalar; 
-		
-		/*  Do the triple producte tL*D*L: */
-		TripleMultiply( &L[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&L[0][0],2,numdof,0,
-					&Ke_gg_gaussian[0][0],0);
-
-		for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
-	}
-
-	for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j];
-	for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j];
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokes{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokes(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealStokesViscous();
-	ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealStokesFriction();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesViscous{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesViscous(void){
-
-	/*Constants*/
-	const int    numdofm=NDOF2*NUMVERTICES2D;
-	const int    numdofs=NDOF4*NUMVERTICES;
-	const int    numdoftotal=2*numdofm+numdofs;
-
-	/*Intermediaries */
-	int         i,j,ig;
-	double      Jdet;
-	double      viscosity,stokesreconditioning; //viscosity
-	double      epsilon[6]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
-	double      xyz_list[NUMVERTICES][3];
-	double      B[4][numdofs+3];
-	double      Bprime[4][numdofm];
-	double      B2[3][numdofm];
-	double      Bprime2[3][numdofs+3];
-	double      D[4][4]={0.0};            // material matrix, simple scalar matrix.
-	double      D2[3][3]={0.0};            // material matrix, simple scalar matrix.
-	double      D_scalar;
-	double      Ke_gg[numdofs][numdofm]={0.0}; //local element stiffness matrix 
-	double      Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix 
-	double      Ke_gg_gaussian[numdofs+3][numdofm]; //stiffness matrix evaluated at the gaussian point.
-	double      Ke_gg_gaussian2[numdofm][numdofs+3]; //stiffness matrix evaluated at the gaussian point.
-	GaussPenta *gauss=NULL;
-	GaussTria  *gauss_tria=NULL;
-
-	/*Find penta on bed as stokes must be coupled to the dofs on the bed: */
-	Penta* pentabase=GetBasalElement();
-	Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-
-	/*Initialize Element matrix and return if necessary*/
-	ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-	ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,StokesApproximationEnum);
-	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
-	delete Ke1; delete Ke2;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	gauss_tria=new GaussTria();
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-		gauss->SynchronizeGaussTria(gauss_tria);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBMacAyealStokes(&B[0][0], &xyz_list[0][0], gauss);
-		tria->GetBprimeMacAyealStokes(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
-		tria->GetBMacAyealStokes(&B2[0][0], &xyz_list[0][0], gauss_tria);
-		GetBprimeMacAyealStokes(&Bprime2[0][0], &xyz_list[0][0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity, &epsilon[0]);
-
-		D_scalar=2*viscosity*gauss->weight*Jdet;
-		for (i=0;i<3;i++) D[i][i]=D_scalar;
-		D[3][3]=-gauss->weight*Jdet*stokesreconditioning;
-		for (i=0;i<3;i++) D2[i][i]=D_scalar;
-
-		TripleMultiply( &B[0][0],4,numdofs+3,1,
-					&D[0][0],4,4,0,
-					&Bprime[0][0],4,numdofm,0,
-					&Ke_gg_gaussian[0][0],0);
-
-		TripleMultiply( &B2[0][0],3,numdofm,1,
-					&D2[0][0],3,3,0,
-					&Bprime2[0][0],3,numdofs+3,0,
-					&Ke_gg_gaussian2[0][0],0);
-
-		for( i=0; i<numdofs; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
-		for( i=0; i<numdofm; i++) for(j=0;j<numdofs; j++) Ke_gg2[i][j]+=Ke_gg_gaussian2[i][j];
-	} 
-	for(i=0;i<numdofs;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
-	for(i=0;i<numdofm;i++) for(j=0;j<numdofs;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg2[i][j];
-
-	/*Clean-up and return*/
-	delete tria->matice; delete tria;
-	delete gauss;
-	delete gauss_tria;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesFriction {{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesFriction(void){
-
-	/*Constants*/
-	const int numdof=NUMVERTICES*NDOF4;
-	const int numdofm=NUMVERTICES*NDOF2;
-	const int numdof2d=NUMVERTICES2D*NDOF4;
-	const int numdof2dm=NUMVERTICES2D*NDOF2;
-	const int numdoftot=numdof+numdofm;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        analysis_type,approximation;
-	double     stokesreconditioning;
-	double     viscosity,alpha2_gauss,Jdet2d;
-	double	  bed_normal[3];
-	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double     xyz_list[NUMVERTICES][3];
-	double	  xyz_list_tria[NUMVERTICES2D][3];
-	double     LMacAyealStokes[8][numdof2dm];
-	double     LprimeMacAyealStokes[8][numdof2d];
-	double     DLMacAyealStokes[8][8]={0.0};
-	double     LStokesMacAyeal[4][numdof2d];
-	double     LprimeStokesMacAyeal[4][numdof2dm];
-	double     DLStokesMacAyeal[4][4]={0.0};
-	double     Ke_drag_gaussian[numdof2dm][numdof2d];
-	double     Ke_drag_gaussian2[numdof2d][numdof2dm];
-	Friction*  friction=NULL;
-	GaussPenta *gauss=NULL;
-
-	/*If on water or not Stokes, skip stiffness: */
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(IsOnShelf() || !IsOnBed()) return NULL;
-	ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-	ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
-	delete Ke1; delete Ke2;
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/*build friction object, used later on: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
-		GetLMacAyealStokes(&LMacAyealStokes[0][0], gauss);
-		GetLprimeMacAyealStokes(&LprimeMacAyealStokes[0][0], &xyz_list[0][0], gauss);
-		GetLStokesMacAyeal(&LStokesMacAyeal[0][0], gauss);
-		GetLprimeStokesMacAyeal(&LprimeStokesMacAyeal[0][0], &xyz_list[0][0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		BedNormal(&bed_normal[0],xyz_list_tria);
-		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
-
-		DLMacAyealStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLMacAyealStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLMacAyealStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
-		DLMacAyealStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
-		DLMacAyealStokes[4][4]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
-		DLMacAyealStokes[5][5]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
-		DLMacAyealStokes[6][6]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
-		DLMacAyealStokes[7][7]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
-
-		DLStokesMacAyeal[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLStokesMacAyeal[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLStokesMacAyeal[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
-		DLStokesMacAyeal[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
-		
-		TripleMultiply( &LMacAyealStokes[0][0],8,numdof2dm,1,
-					&DLMacAyealStokes[0][0],8,8,0,
-					&LprimeMacAyealStokes[0][0],8,numdof2d,0,
-					&Ke_drag_gaussian[0][0],0);
-
-		TripleMultiply( &LStokesMacAyeal[0][0],4,numdof2d,1,
-					&DLStokesMacAyeal[0][0],4,4,0,
-					&LprimeStokesMacAyeal[0][0],4,numdof2dm,0,
-					&Ke_drag_gaussian2[0][0],0);
-
-		for(i=0;i<numdof2dm;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdoftot+j+numdofm]+=Ke_drag_gaussian[i][j];
-		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2dm;j++) Ke->values[(i+numdofm)*numdoftot+j]+=Ke_drag_gaussian2[i][j];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/
-ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
-	ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
-	delete Ke1;
-	delete Ke2;
-	Ke1=CreateKMatrixDiagnosticPattyn();
-	Ke2=CreateKMatrixDiagnosticStokes();
-
-	/*Constants*/
-	const int    numdofp=NDOF2*NUMVERTICES;
-	const int    numdofs=NDOF4*NUMVERTICES;
-	const int    numdoftotal=(NDOF2+NDOF4)*NUMVERTICES;
-	int          i,j;
-
-	for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){
-		Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0];
-		Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1];
-	}
-	for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){
-		Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0];
-		Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1];
-	}
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){
-
-	int approximation;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	switch(approximation){
-		case MacAyealApproximationEnum:
-			return CreateKMatrixDiagnosticMacAyeal2d();
-		case PattynApproximationEnum:
-			return CreateKMatrixDiagnosticPattyn();
-		case StokesApproximationEnum:
-			return CreateKMatrixDiagnosticStokes();
-		case HutterApproximationEnum:
-			return NULL;
-		case NoneApproximationEnum:
-			return NULL;
-		case MacAyealPattynApproximationEnum:
-			return CreateKMatrixDiagnosticMacAyealPattyn();
-		case MacAyealStokesApproximationEnum:
-			return CreateKMatrixDiagnosticMacAyealStokes();
-		case PattynStokesApproximationEnum:
-			return CreateKMatrixDiagnosticPattynStokes();
-		default:
-			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){
-
-	/*Constants*/
-	const int numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries*/
-	int       connectivity[2];
-	int       i,i0,i1,j0,j1;
-	double    one0,one1;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Spawn 3 beam elements: */
-	for(i=0;i<3;i++){
-		/*2 dofs of first node*/
-		i0=2*i;
-		i1=2*i+1;
-		/*2 dofs of second node*/
-		j0=2*(i+3);
-		j1=2*(i+3)+1;
-
-		/*Find connectivity for the two nodes*/
-		connectivity[0]=nodes[i]->GetConnectivity();
-		connectivity[1]=nodes[i+3]->GetConnectivity();
-		one0=1/(double)connectivity[0];
-		one1=1/(double)connectivity[1];
-
-		/*Create matrix for these two nodes*/
-		if (IsOnBed() && IsOnSurface()){
-			Ke->values[i0*numdof+i0]=one0;
-			Ke->values[i1*numdof+i1]=one0;
-			Ke->values[j0*numdof+i0]=-one1;
-			Ke->values[j0*numdof+j0]=one1;
-			Ke->values[j1*numdof+i1]=-one1;
-			Ke->values[j1*numdof+j1]=one1;
-		}
-		else if (IsOnBed()){
-			Ke->values[i0*numdof+i0]=one0;
-			Ke->values[i1*numdof+i1]=one0;
-			Ke->values[j0*numdof+i0]=-2*one1;
-			Ke->values[j0*numdof+j0]=2*one1;
-			Ke->values[j1*numdof+i1]=-2*one1;
-			Ke->values[j1*numdof+j1]=2*one1;
-		}
-		else if (IsOnSurface()){
-			Ke->values[j0*numdof+i0]=-one1;
-			Ke->values[j0*numdof+j0]=one1;
-			Ke->values[j1*numdof+i1]=-one1;
-			Ke->values[j1*numdof+j1]=one1;
-		}
-		else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity
-			Ke->values[j0*numdof+i0]=-2*one1;
-			Ke->values[j0*numdof+j0]=2*one1;
-			Ke->values[j1*numdof+i1]=-2*one1;
-			Ke->values[j1*numdof+j1]=2*one1;
-		}
-	}
-
-	/*Clean up and return*/
-	return Ke;
-}
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){
-
-	/*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 
-	  bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build 
-	  the stiffness matrix. */
-	if (!IsOnBed()) return NULL;
-
-	/*Depth Averaging B*/
-	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal();
-	delete tria->matice; delete tria;
-
-	/*Delete B averaged*/
-	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
-
-	/*clean up and return*/
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){
-
-	/*Constants*/
-	const int    numdof2d=2*NUMVERTICES2D;
-
-	/*Intermediaries */
-	int         i,j,ig,approximation;
-	double      Jdet;
-	double      viscosity, oldviscosity, newviscosity, viscosity_overshoot;
-	double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
-	double      epsilons[6]; //6 for stokes
-	double      xyz_list[NUMVERTICES][3];
-	double      B[3][numdof2d];
-	double      Bprime[3][numdof2d];
-	double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
-	double      D_scalar;
-	double      Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point.
-	Tria*       tria=NULL;
-	Penta*      pentabase=NULL;
-	GaussPenta *gauss=NULL;
-	GaussTria  *gauss_tria=NULL;
-
-	/*Find penta on bed as this is a macayeal elements: */
-	pentabase=GetBasalElement();
-	tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum);
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES);
-	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
-	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
-	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
-	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	gauss_tria=new GaussTria();
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-		gauss->SynchronizeGaussTria(gauss_tria);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria);
-		tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
-
-		if(approximation==MacAyealPattynApproximationEnum){
-			this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
-			this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
-			matice->GetViscosity3d(&viscosity, &epsilon[0]);
-			matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
-
-			newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
-		}
-		else if (approximation==MacAyealStokesApproximationEnum){
-			this->GetStrainRate3d(&epsilons[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-			matice->GetViscosity3dStokes(&newviscosity,&epsilons[0]);
-		}
-		else _error_("approximation %i (%s) not supported yet",approximation,EnumToStringx(approximation));
-
-		D_scalar=2*newviscosity*gauss->weight*Jdet;
-		for (i=0;i<3;i++) D[i][i]=D_scalar;
-
-		TripleMultiply( &B[0][0],3,numdof2d,1,
-					&D[0][0],3,3,0,
-					&Bprime[0][0],3,numdof2d,0,
-					&Ke_gg_gaussian[0][0],0);
-
-		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];
-	}
-
-	/*Clean up and return*/
-	delete tria->matice;
-	delete tria;
-	delete gauss_tria;
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){
-
-	/*Initialize Element matrix and return if necessary*/
-	if(IsOnShelf() || !IsOnBed()) return NULL;
-
-	/*Build a tria element using the 3 nodes of the base of the penta. Then use 
-	 * the tria functionality to build a friction stiffness matrix on these 3
-	 * nodes: */
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction();
-	delete tria->matice; delete tria;
-
-	/*clean-up and return*/
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn();
-	ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	delete Ke3;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealStokes{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealStokes(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
-	ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealStokes();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	delete Ke3;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){
-
-	/*Constants*/
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        approximation;
-	double     xyz_list[NUMVERTICES][3];
-	double     Jdet;
-	double     viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
-	double     epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
-	double     D_scalar;
-	double     D[5][5]={0.0};            // material matrix, simple scalar matrix.
-	double     B[5][numdof];
-	double     Bprime[5][numdof];
-	Tria*      tria=NULL;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
-	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
-	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBPattyn(&B[0][0], &xyz_list[0][0], gauss);
-		GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss);
-
-		this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
-		this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
-		matice->GetViscosity3d(&viscosity, &epsilon[0]);
-		matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
-		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
-
-		D_scalar=2*newviscosity*gauss->weight*Jdet;
-		for (i=0;i<5;i++) D[i][i]=D_scalar;
-
-		TripleMultiply( &B[0][0],5,numdof,1,
-					&D[0][0],5,5,0,
-					&Bprime[0][0],5,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){
-
-	/*Constants*/
-	const int numdof   = NDOF2*NUMVERTICES;
-	
-	/*Intermediaries */
-	int       i,j,ig;
-	int       analysis_type;
-	double    xyz_list[NUMVERTICES][3];
-	double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double    slope_magnitude,alpha2,Jdet;
-	double    slope[3]={0.0,0.0,0.0};
-	double    MAXSLOPE=.06; // 6 %
-	double    MOUNTAINKEXPONENT=10;
-	double    L[2][numdof];
-	double    DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
-	double    DL_scalar;
-	Friction  *friction = NULL;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix and return if necessary*/
-	if(IsOnShelf() || !IsOnBed()) return NULL;
-
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
-
-	/*build friction object, used later on: */
-	friction=new Friction("2d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
-		GetL(&L[0][0], gauss,NDOF2);
-
-		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-		friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); 
-		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
-
-		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
-		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
-		if (slope_magnitude>MAXSLOPE){
-			alpha2=pow((double)10,MOUNTAINKEXPONENT);
-		}
-		
-		DL_scalar=alpha2*gauss->weight*Jdet;
-		for (i=0;i<2;i++) DL[i][i]=DL_scalar;
-		
-		TripleMultiply( &L[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&L[0][0],2,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
-	ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	delete Ke3;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){
-
-	/*Intermediaries */
-	int        i,j,ig,approximation;
-	double     Jdet,viscosity,stokesreconditioning;
-	double     xyz_list[NUMVERTICES][3];
-	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double     B[8][27];
-	double     B_prime[8][27];
-	double     D_scalar;
-	double     D[8][8]={0.0};
-	double     Ke_temp[27][27]={0.0}; //for the six nodes and the bubble 
-	double     Ke_gaussian[27][27];
-	GaussPenta *gauss=NULL;
-
-	/*If on water or not Stokes, skip stiffness: */
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 
-		GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss); 
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		D_scalar=gauss->weight*Jdet;
-		for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
-		for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
-
-		TripleMultiply( &B[0][0],8,27,1,
-					&D[0][0],8,8,0,
-					&B_prime[0][0],8,27,0,
-					&Ke_gaussian[0][0],0);
-
-		for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
-	}
-
-	/*Condensation*/
-	ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]);
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){
-
-	/*Constants*/
-	const int numdof=NUMVERTICES*NDOF4;
-	const int numdof2d=NUMVERTICES2D*NDOF4;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        analysis_type,approximation;
-	double     stokesreconditioning;
-	double     viscosity,alpha2_gauss,Jdet2d;
-	double	  bed_normal[3];
-	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double     xyz_list[NUMVERTICES][3];
-	double	  xyz_list_tria[NUMVERTICES2D][3];
-	double     LStokes[14][numdof2d];
-	double     LprimeStokes[14][numdof2d];
-	double     DLStokes[14][14]={0.0};
-	double     Ke_drag_gaussian[numdof2d][numdof2d];
-	Friction*  friction=NULL;
-	GaussPenta *gauss=NULL;
-
-	/*If on water or not Stokes, skip stiffness: */
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum &&  approximation!=PattynStokesApproximationEnum)) return NULL;
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/*build friction object, used later on: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
-		GetLStokes(&LStokes[0][0], gauss);
-		GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		BedNormal(&bed_normal[0],xyz_list_tria);
-		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
-
-		DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
-		DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
-		DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
-		DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
-		DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
-		DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
-		DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
-		DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2];
-		DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0;
-		DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0;
-		DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
-		DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
-		DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2];
-
-		TripleMultiply( &LStokes[0][0],14,numdof2d,1,
-					&DLStokes[0][0],14,14,0,
-					&LprimeStokes[0][0],14,numdof2d,0,
-					&Ke_drag_gaussian[0][0],0);
-
-		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){
-	
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int         i,j,ig;
-	double      Jdet;
-	double      xyz_list[NUMVERTICES][3];
-	double      B[NDOF1][NUMVERTICES];
-	double      Bprime[NDOF1][NUMVERTICES];
-	double      DL_scalar;
-	GaussPenta  *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBVert(&B[0][0], &xyz_list[0][0], gauss);
-		GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss);
-
-		DL_scalar=gauss->weight*Jdet;
-
-		TripleMultiply( &B[0][0],1,NUMVERTICES,1,
-					&DL_scalar,1,1,0,
-					&Bprime[0][0],1,NUMVERTICES,0,
-					&Ke->values[0],1);
-	} 
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/
-ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){
-
-	if (!IsOnSurface()) return NULL;
-
-	/*Constants*/
-	const int numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int       i,j,ig;
-	double    xyz_list[NUMVERTICES][3];
-	double    xyz_list_tria[NUMVERTICES2D][3];
-	double    surface_normal[3];
-	double    Jdet2d,DL_scalar;
-	double    basis[NUMVERTICES];
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i+3][j];
-	SurfaceNormal(&surface_normal[0],xyz_list_tria);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(3,4,5,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		DL_scalar= - gauss->weight*Jdet2d*surface_normal[2]; 
-
-		TripleMultiply( basis,1,numdof,1,
-					&DL_scalar,1,1,0,
-					basis,1,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixPrognostic {{{1*/
-ElementMatrix* Penta::CreateKMatrixPrognostic(void){
-
-	if (!IsOnBed()) return NULL;
-
-	/*Depth Averaging Vx and Vy*/
-	this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
-	this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
-
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixPrognostic();
-	delete tria->matice; delete tria;
-
-	/*Delete Vx and Vy averaged*/
-	this->inputs->DeleteInput(VxAverageEnum);
-	this->inputs->DeleteInput(VyAverageEnum);
-
-	/*clean up and return*/
-	return Ke;
-}
-/*}}}*/
 /*FUNCTION Penta::CreateKMatrixSlope {{{1*/
 ElementMatrix* Penta::CreateKMatrixSlope(void){
@@ -1794,2053 +625,4 @@
 }
 /*}}}*/
-
-#ifdef _HAVE_THERMAL_
-/*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/
-ElementMatrix* Penta::CreateKMatrixEnthalpy(void){
-	
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixEnthalpyVolume();
-	ElementMatrix* Ke2=CreateKMatrixEnthalpyShelf();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-	
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixEnthalpyVolume {{{1*/
-ElementMatrix* Penta::CreateKMatrixEnthalpyVolume(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        stabilization;
-	int        i,j,ig,found=0;
-	double     Jdet,u,v,w,um,vm,wm;
-	double     gravity,rho_ice,rho_water;
-	double     epsvel=2.220446049250313e-16;
-	double     heatcapacity,thermalconductivity,dt;
-	double     pressure,enthalpy;
-	double     latentheat,kappa;
-	double     tau_parameter,diameter;
-	double     xyz_list[NUMVERTICES][3];
-	double     B[3][numdof];
-	double     Bprime[3][numdof];
-	double     B_conduct[3][numdof];
-	double     B_advec[3][numdof];
-	double     B_stab[2][numdof];
-	double     Bprime_advec[3][numdof];
-	double     L[numdof];
-	double     dbasis[3][6];
-	double     D_scalar_conduct,D_scalar_advec;
-	double     D_scalar_trans,D_scalar_stab;
-	double     D[3][3];
-	double     K[2][2]={0.0};
-	Tria*      tria=NULL;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	gravity=matpar->GetG();
-	heatcapacity=matpar->GetHeatCapacity();
-	latentheat=matpar->GetLatentHeat();
-	thermalconductivity=matpar->GetThermalConductivity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
-	Input* pressure_input=inputs->GetInput(PressureEnum);      _assert_(pressure_input);
-	Input* enthalpy_input=inputs->GetInput(EnthalpyEnum);      _assert_(enthalpy_input);
-	Input* vx_input=inputs->GetInput(VxEnum);                  _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);                  _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);                  _assert_(vz_input);
-	Input* vxm_input=inputs->GetInput(VxMeshEnum);             _assert_(vxm_input);
-	Input* vym_input=inputs->GetInput(VyMeshEnum);             _assert_(vym_input);
-	Input* vzm_input=inputs->GetInput(VzMeshEnum);             _assert_(vzm_input);
-	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Conduction: */  
-		/*Need to change that depending on enthalpy value -> cold or temperate ice: */  
-
-		GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss); 
-
-		enthalpy_input->GetParameterValue(&enthalpy, gauss);
-		pressure_input->GetParameterValue(&pressure, gauss);
-		kappa=matpar->GetEnthalpyDiffusionParameter(enthalpy,pressure);
-		D_scalar_conduct=gauss->weight*Jdet*kappa;
-		if(dt) D_scalar_conduct=D_scalar_conduct*dt;
-
-		D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
-		D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
-		D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
-
-		TripleMultiply(&B_conduct[0][0],3,numdof,1,
-					&D[0][0],3,3,0,
-					&B_conduct[0][0],3,numdof,0,
-					&Ke->values[0],1);
-
-		/*Advection: */
-
-		GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss); 
-		GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss); 
-
-		vx_input->GetParameterValue(&u, gauss);
-		vy_input->GetParameterValue(&v, gauss);
-		vz_input->GetParameterValue(&w, gauss);
-		vxm_input->GetParameterValue(&um,gauss);
-		vym_input->GetParameterValue(&vm,gauss);
-		vzm_input->GetParameterValue(&wm,gauss);
-
-		D_scalar_advec=gauss->weight*Jdet;
-		if(dt) D_scalar_advec=D_scalar_advec*dt;
-
-		D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
-		D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
-		D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
-
-		TripleMultiply(&B_advec[0][0],3,numdof,1,
-					&D[0][0],3,3,0,
-					&Bprime_advec[0][0],3,numdof,0,
-					&Ke->values[0],1);
-
-		/*Transient: */
-
-		if(dt){
-			GetNodalFunctionsP1(&L[0], gauss);
-			D_scalar_trans=gauss->weight*Jdet;
-			D_scalar_trans=D_scalar_trans;
-
-			TripleMultiply(&L[0],numdof,1,0,
-						&D_scalar_trans,1,1,0,
-						&L[0],1,numdof,0,
-						&Ke->values[0],1);
-		}
-
-		/*Artifficial diffusivity*/
-
-		if(stabilization==1){
-			/*Build K: */
-			D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
-			if(dt) D_scalar_stab=D_scalar_stab*dt;
-			K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
-			K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
-
-			GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss); 
-
-			TripleMultiply(&B_stab[0][0],2,numdof,1,
-						&K[0][0],2,2,0,
-						&B_stab[0][0],2,numdof,0,
-						&Ke->values[0],1);
-		}
-		else if(stabilization==2){
-
-			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-			tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
-
-			for(i=0;i<numdof;i++){
-				for(j=0;j<numdof;j++){
-					Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
-					  ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
-				}
-			}
-			if(dt){
-				for(i=0;i<numdof;i++){
-					for(j=0;j<numdof;j++){
-						Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
-					}
-				}
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixEnthalpyShelf {{{1*/
-ElementMatrix* Penta::CreateKMatrixEnthalpyShelf(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int       i,j,ig;
-	double    mixed_layer_capacity,thermal_exchange_velocity;
-	double    rho_ice,rho_water,heatcapacity;
-	double    Jdet2d,dt;
-	double    xyz_list[NUMVERTICES][3];
-	double	 xyz_list_tria[NUMVERTICES2D][3];
-	double    basis[NUMVERTICES];
-	double    D_scalar;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix and return if necessary*/
-	if (!IsOnBed() || !IsOnShelf()) return NULL;
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
-	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/* Start looping on the number of gauss (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-		
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-				
-		D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(rho_ice*heatcapacity);
-		if(dt) D_scalar=dt*D_scalar;
-
-		TripleMultiply(&basis[0],numdof,1,0,
-					&D_scalar,1,1,0,
-					&basis[0],1,numdof,0,
-					&Ke->values[0],1);
-	}
-	
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixMelting {{{1*/
-ElementMatrix* Penta::CreateKMatrixMelting(void){
-
-	if (!IsOnBed()) return NULL;
-
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixMelting();
-
-	delete tria->matice; delete tria;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixThermal {{{1*/
-ElementMatrix* Penta::CreateKMatrixThermal(void){
-	
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixThermalVolume();
-	ElementMatrix* Ke2=CreateKMatrixThermalShelf();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-	
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/
-ElementMatrix* Penta::CreateKMatrixThermalVolume(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        stabilization;
-	int        i,j,ig,found=0;
-	double     Jdet,u,v,w,um,vm,wm;
-	double     epsvel=2.220446049250313e-16;
-	double     gravity,rho_ice,rho_water;
-	double     heatcapacity,thermalconductivity,dt;
-	double     tau_parameter,diameter;
-	double     xyz_list[NUMVERTICES][3];
-	double     B[3][numdof];
-	double     Bprime[3][numdof];
-	double     B_conduct[3][numdof];
-	double     B_advec[3][numdof];
-	double     B_stab[2][numdof];
-	double     Bprime_advec[3][numdof];
-	double     L[numdof];
-	double     dbasis[3][6];
-	double     D_scalar_conduct,D_scalar_advec;
-	double     D_scalar_trans,D_scalar_stab;
-	double     D[3][3];
-	double     K[2][2]={0.0};
-	Tria*      tria=NULL;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	gravity=matpar->GetG();
-	heatcapacity=matpar->GetHeatCapacity();
-	thermalconductivity=matpar->GetThermalConductivity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);      _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);      _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);      _assert_(vz_input);
-	Input* vxm_input=inputs->GetInput(VxMeshEnum); _assert_(vxm_input);
-	Input* vym_input=inputs->GetInput(VyMeshEnum); _assert_(vym_input);
-	Input* vzm_input=inputs->GetInput(VzMeshEnum); _assert_(vzm_input);
-	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Conduction: */
-
-		GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss); 
-
-		D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));
-		if(dt) D_scalar_conduct=D_scalar_conduct*dt;
-
-		D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
-		D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
-		D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
-
-		TripleMultiply(&B_conduct[0][0],3,numdof,1,
-					&D[0][0],3,3,0,
-					&B_conduct[0][0],3,numdof,0,
-					&Ke->values[0],1);
-
-		/*Advection: */
-
-		GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss); 
-		GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss); 
-
-		vx_input->GetParameterValue(&u, gauss);
-		vy_input->GetParameterValue(&v, gauss);
-		vz_input->GetParameterValue(&w, gauss);
-		vxm_input->GetParameterValue(&um,gauss);
-		vym_input->GetParameterValue(&vm,gauss);
-		vzm_input->GetParameterValue(&wm,gauss);
-
-		D_scalar_advec=gauss->weight*Jdet;
-		if(dt) D_scalar_advec=D_scalar_advec*dt;
-
-		D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
-		D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
-		D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
-
-		TripleMultiply(&B_advec[0][0],3,numdof,1,
-					&D[0][0],3,3,0,
-					&Bprime_advec[0][0],3,numdof,0,
-					&Ke->values[0],1);
-
-		/*Transient: */
-
-		if(dt){
-			GetNodalFunctionsP1(&L[0], gauss);
-			D_scalar_trans=gauss->weight*Jdet;
-			D_scalar_trans=D_scalar_trans;
-
-			TripleMultiply(&L[0],numdof,1,0,
-						&D_scalar_trans,1,1,0,
-						&L[0],1,numdof,0,
-						&Ke->values[0],1);
-		}
-
-		/*Artifficial diffusivity*/
-
-		if(stabilization==1){
-			/*Build K: */
-			D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
-			if(dt) D_scalar_stab=D_scalar_stab*dt;
-			K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
-			K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
-
-			GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss); 
-
-			TripleMultiply(&B_stab[0][0],2,numdof,1,
-						&K[0][0],2,2,0,
-						&B_stab[0][0],2,numdof,0,
-						&Ke->values[0],1);
-		}
-		else if(stabilization==2){
-
-			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-			tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
-
-			for(i=0;i<numdof;i++){
-				for(j=0;j<numdof;j++){
-					Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
-					  ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
-				}
-			}
-			if(dt){
-				for(i=0;i<numdof;i++){
-					for(j=0;j<numdof;j++){
-						Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
-					}
-				}
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/
-ElementMatrix* Penta::CreateKMatrixThermalShelf(void){
-
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int       i,j,ig;
-	double    mixed_layer_capacity,thermal_exchange_velocity;
-	double    rho_ice,rho_water,heatcapacity;
-	double    Jdet2d,dt;
-	double    xyz_list[NUMVERTICES][3];
-	double	 xyz_list_tria[NUMVERTICES2D][3];
-	double    basis[NUMVERTICES];
-	double    D_scalar;
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element matrix and return if necessary*/
-	if (!IsOnBed() || !IsOnShelf()) return NULL;
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
-	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/* Start looping on the number of gauss (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-		
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-				
-		D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
-		if(dt) D_scalar=dt*D_scalar;
-
-		TripleMultiply(&basis[0],numdof,1,0,
-					&D_scalar,1,1,0,
-					&basis[0],1,numdof,0,
-					&Ke->values[0],1);
-	}
-	
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorEnthalpy {{{1*/
-ElementVector* Penta::CreatePVectorEnthalpy(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorEnthalpyVolume();
-	ElementVector* pe2=CreatePVectorEnthalpySheet();
-	ElementVector* pe3=CreatePVectorEnthalpyShelf();
-	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	delete pe3;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorEnthalpyVolume {{{1*/
-ElementVector* Penta::CreatePVectorEnthalpyVolume(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries*/
-	int    i,j,ig,found=0;
-	int    friction_type,stabilization;
-	double Jdet,phi,dt;
-	double rho_ice,heatcapacity;
-	double thermalconductivity;
-	double viscosity,temperature;
-	double tau_parameter,diameter;
-	double u,v,w;
-	double scalar_def,scalar_transient;
-	double temperature_list[NUMVERTICES];
-	double xyz_list[NUMVERTICES][3];
-	double L[numdof];
-	double dbasis[3][6];
-	double epsilon[6];
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	thermalconductivity=matpar->GetThermalConductivity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-	Input* temperature_input=NULL;
-	if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
-	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,3);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(&L[0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-		GetPhi(&phi, &epsilon[0], viscosity);
-
-		scalar_def=phi/(rho_ice)*Jdet*gauss->weight;
-		if(dt) scalar_def=scalar_def*dt;
-
-		for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
-
-		/* Build transient now */
-		if(dt){
-			temperature_input->GetParameterValue(&temperature, gauss);
-			scalar_transient=temperature*Jdet*gauss->weight;
-			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
-		}
-
-		if(stabilization==2){
-			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-			vx_input->GetParameterValue(&u, gauss);
-			vy_input->GetParameterValue(&v, gauss);
-			vz_input->GetParameterValue(&w, gauss);
-
-			tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
-
-			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
-			if(dt){
-				for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorEnthalpyShelf {{{1*/
-ElementVector* Penta::CreatePVectorEnthalpyShelf(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     Jdet2d;
-	double     heatcapacity,h_pmp;
-	double     mixed_layer_capacity,thermal_exchange_velocity;
-	double     rho_ice,rho_water,pressure,dt,scalar_ocean;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3];
-	double     basis[NUMVERTICES];
-	GaussPenta* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/* Ice/ocean heat exchange flux on ice shelf base */
-	if (!IsOnBed() || !IsOnShelf()) return NULL;
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
-	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		pressure_input->GetParameterValue(&pressure,gauss);
-		h_pmp=matpar->PureIceEnthalpy(pressure);
-
-		scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(h_pmp)/(rho_ice*heatcapacity);
-		if(dt) scalar_ocean=dt*scalar_ocean;
-
-		for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorEnthalpySheet {{{1*/
-ElementVector* Penta::CreatePVectorEnthalpySheet(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        analysis_type;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double     Jdet2d,dt;
-	double     rho_ice,heatcapacity,geothermalflux_value;
-	double     basalfriction,alpha2,vx,vy;
-	double     scalar;
-	double     basis[NUMVERTICES];
-	Friction*  friction=NULL;
-	GaussPenta* gauss=NULL;
-
-	/* Geothermal flux on ice sheet base and basal friction */
-	if (!IsOnBed() || IsOnShelf()) return NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
-	Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
-
-	/*Build frictoin element, needed later: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
-		friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
-		
-		scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(rho_ice);
-		if(dt) scalar=dt*scalar;
-
-		for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorMelting {{{1*/
-ElementVector* Penta::CreatePVectorMelting(void){
-	return NULL;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorThermal {{{1*/
-ElementVector* Penta::CreatePVectorThermal(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorThermalVolume();
-	ElementVector* pe2=CreatePVectorThermalSheet();
-	ElementVector* pe3=CreatePVectorThermalShelf();
-	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	delete pe3;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/
-ElementVector* Penta::CreatePVectorThermalVolume(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries*/
-	int    i,j,ig,found=0;
-	int    friction_type,stabilization;
-	double Jdet,phi,dt;
-	double rho_ice,heatcapacity;
-	double thermalconductivity;
-	double viscosity,temperature;
-	double tau_parameter,diameter;
-	double u,v,w;
-	double scalar_def,scalar_transient;
-	double temperature_list[NUMVERTICES];
-	double xyz_list[NUMVERTICES][3];
-	double L[numdof];
-	double dbasis[3][6];
-	double epsilon[6];
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	thermalconductivity=matpar->GetThermalConductivity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-	Input* temperature_input=NULL;
-	if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
-	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,3);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(&L[0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-		GetPhi(&phi, &epsilon[0], viscosity);
-
-		scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
-		if(dt) scalar_def=scalar_def*dt;
-
-		for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
-
-		/* Build transient now */
-		if(dt){
-			temperature_input->GetParameterValue(&temperature, gauss);
-			scalar_transient=temperature*Jdet*gauss->weight;
-			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
-		}
-
-		if(stabilization==2){
-			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-			vx_input->GetParameterValue(&u, gauss);
-			vy_input->GetParameterValue(&v, gauss);
-			vz_input->GetParameterValue(&w, gauss);
-
-			tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
-
-			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
-			if(dt){
-				for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/
-ElementVector* Penta::CreatePVectorThermalShelf(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     Jdet2d;
-	double     mixed_layer_capacity,thermal_exchange_velocity;
-	double     rho_ice,rho_water,pressure,dt,scalar_ocean;
-	double     heatcapacity,t_pmp;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3];
-	double     basis[NUMVERTICES];
-	GaussPenta* gauss=NULL;
-
-	/* Ice/ocean heat exchange flux on ice shelf base */
-	if (!IsOnBed() || !IsOnShelf()) return NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
-	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		pressure_input->GetParameterValue(&pressure,gauss);
-		t_pmp=matpar->TMeltingPoint(pressure);
-
-		scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
-		if(dt) scalar_ocean=dt*scalar_ocean;
-
-		for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/
-ElementVector* Penta::CreatePVectorThermalSheet(void){
-
-	/*Constants*/
-	const int  numdof=NUMVERTICES*NDOF1;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        analysis_type;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double     Jdet2d,dt;
-	double     rho_ice,heatcapacity,geothermalflux_value;
-	double     basalfriction,alpha2,vx,vy;
-	double     scalar;
-	double     basis[NUMVERTICES];
-	Friction*  friction=NULL;
-	GaussPenta* gauss=NULL;
-
-	/* Geothermal flux on ice sheet base and basal friction */
-	if (!IsOnBed() || IsOnShelf()) return NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	rho_ice=matpar->GetRhoIce();
-	heatcapacity=matpar->GetHeatCapacity();
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
-	Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
-
-	/*Build frictoin element, needed later: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
-		friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
-		
-		scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
-		if(dt) scalar=dt*scalar;
-
-		for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/
-void  Penta::GetSolutionFromInputsThermal(Vec solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       values[numdof];
-	double       temp;
-	GaussPenta   *gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	Input* t_input=inputs->GetInput(TemperatureEnum); _assert_(t_input);
-
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-		/*Recover temperature*/
-		gauss->GaussVertex(i);
-		t_input->GetParameterValue(&temp,gauss);
-		values[i]=temp;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsEnthalpy{{{1*/
-void  Penta::GetSolutionFromInputsEnthalpy(Vec solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       values[numdof];
-	double       enthalpy;
-	GaussPenta   *gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	Input* h_input=inputs->GetInput(EnthalpyEnum); _assert_(h_input);
-
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-		/*Recover temperature*/
-		gauss->GaussVertex(i);
-		h_input->GetParameterValue(&enthalpy,gauss);
-		values[i]=enthalpy;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/
-void  Penta::InputUpdateFromSolutionThermal(double* solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	bool   converged;
-	int    i,rheology_law;
-	double xyz_list[NUMVERTICES][3];
-	double values[numdof];
-	double B[numdof];
-	double B_average,s_average;
-	int*   doflist=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++){
-		values[i]=solution[doflist[i]];
-
-		/*Check solution*/
-		if(isnan(values[i])) _error_("NaN found in solution vector");
-		//if(values[i]<0)      printf("temperature < 0°K found in solution vector\n");
-		//if(values[i]>275)    printf("temperature > 275°K found in solution vector (Paterson's rheology associated is negative)\n");
-	}
-
-	/*Get all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-
-	this->inputs->GetParameterValue(&converged,ConvergedEnum);
-	if(converged){
-		this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values));
-
-		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
-		 * otherwise the rheology could be negative*/
-		this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
-		switch(rheology_law){
-			case NoneEnum:
-				/*Do nothing: B is not temperature dependent*/
-				break;
-			case PatersonEnum:
-				B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0);
-				for(i=0;i<numdof;i++) B[i]=B_average;
-				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
-				break;
-			case ArrheniusEnum:
-				surface_input->GetParameterAverage(&s_average);
-				B_average=Arrhenius((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0,
-							s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
-							matice->GetN());
-				for(i=0;i<numdof;i++) B[i]=B_average;
-				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
-				break;
-			default:
-				_error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
-
-		}
-	}
-	else{
-		this->inputs->AddInput(new PentaVertexInput(TemperaturePicardEnum,values));
-	}
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionEnthalpy {{{1*/
-void  Penta::InputUpdateFromSolutionEnthalpy(double* solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	bool   converged;
-	int    i,rheology_law;
-	double xyz_list[NUMVERTICES][3];
-	double values[numdof];
-	double pressure[NUMVERTICES];
-	double temperatures[numdof];
-	double waterfraction[numdof];
-	double B[numdof];
-	double B_average,s_average;
-	int*   doflist=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++){
-		values[i]=solution[doflist[i]];
-
-		/*Check solution*/
-		if(isnan(values[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetParameterListOnVertices(&pressure[0],PressureEnum);
-	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	
-
-//	this->inputs->GetParameterValue(&converged,ConvergedEnum);
-//	if(converged){
-		/*Convert enthalpy into temperature and water fraction*/
-		for(i=0;i<numdof;i++) matpar->EnthalpyToThermal(&temperatures[i],&waterfraction[i],values[i],pressure[i]);
-			
-		this->inputs->AddInput(new PentaVertexInput(EnthalpyEnum,values));
-		this->inputs->AddInput(new PentaVertexInput(WaterfractionEnum,waterfraction));
-		this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,temperatures));
-
-		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
-		 * otherwise the rheology could be negative*/
-		this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
-		switch(rheology_law){
-			case NoneEnum:
-				/*Do nothing: B is not temperature dependent*/
-				break;
-			case PatersonEnum:
-				B_average=Paterson((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0);
-				for(i=0;i<numdof;i++) B[i]=B_average;
-				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
-				break;
-			case ArrheniusEnum:
-				surface_input->GetParameterAverage(&s_average);
-				B_average=Arrhenius((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0,
-							s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
-							matice->GetN());
-				for(i=0;i<numdof;i++) B[i]=B_average;
-				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
-				break;
-			default:
-				_error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
-
-		}
-//	}
-//	else{
-//		this->inputs->AddInput(new PentaVertexInput(EnthalpyPicardEnum,values));
-//	}
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-#endif
-
-#ifdef _HAVE_CONTROL_
-/*FUNCTION Penta::ControlInputGetGradient{{{1*/
-void Penta::ControlInputGetGradient(Vec gradient,int enum_type){
-
-	int doflist1[NUMVERTICES];
-	Input* input=NULL;
-
-	if(enum_type==MaterialsRheologyBbarEnum){
-		if(!IsOnBed()) return;
-		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
-	}
-	else{
-		input=inputs->GetInput(enum_type);
-	}
-	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
-	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
-
-	this->GetDofList1(&doflist1[0]);
-	((ControlInput*)input)->GetGradient(gradient,&doflist1[0]);
-
-}/*}}}*/
-/*FUNCTION Penta::ControlInputScaleGradient{{{1*/
-void Penta::ControlInputScaleGradient(int enum_type,double scale){
-
-	Input* input=NULL;
-
-	if(enum_type==MaterialsRheologyBbarEnum){
-		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
-	}
-	else{
-		input=inputs->GetInput(enum_type);
-	}
-	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
-	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
-
-	((ControlInput*)input)->ScaleGradient(scale);
-}/*}}}*/
-/*FUNCTION Penta::ControlInputSetGradient{{{1*/
-void Penta::ControlInputSetGradient(double* gradient,int enum_type){
-
-	int    doflist1[NUMVERTICES];
-	double grad_list[NUMVERTICES];
-	Input* grad_input=NULL;
-	Input* input=NULL;
-
-	if(enum_type==MaterialsRheologyBbarEnum){
-		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
-	}
-	else{
-		input=inputs->GetInput(enum_type);
-	}
-	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
-	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
-
-	this->GetDofList1(&doflist1[0]);
-	for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]];
-	grad_input=new PentaVertexInput(GradientEnum,grad_list);
-	((ControlInput*)input)->SetGradient(grad_input);
-
-}/*}}}*/
-/*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/
-ElementVector* Penta::CreatePVectorAdjointHoriz(void){
-
-	int approximation;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	switch(approximation){
-		case MacAyealApproximationEnum:
-			return CreatePVectorAdjointMacAyeal();
-		case PattynApproximationEnum:
-			return CreatePVectorAdjointPattyn();
-		case NoneApproximationEnum:
-			return NULL;
-		case StokesApproximationEnum:
-			return CreatePVectorAdjointStokes();
-		default:
-			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/
-ElementVector* Penta::CreatePVectorAdjointMacAyeal(){
-
-	if (!IsOnBed()) return NULL;
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementVector* pe=tria->CreatePVectorAdjointHoriz();
-	delete tria->matice; delete tria;
-
-	/*clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/
-ElementVector* Penta::CreatePVectorAdjointPattyn(void){
-
-	if (!IsOnSurface()) return NULL;
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-	ElementVector* pe=tria->CreatePVectorAdjointHoriz();
-	delete tria->matice; delete tria;
-
-	/*clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/
-ElementVector* Penta::CreatePVectorAdjointStokes(void){
-
-	if (!IsOnSurface()) return NULL;
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-	ElementVector* pe=tria->CreatePVectorAdjointStokes();
-	delete tria->matice; delete tria;
-
-	/*clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::Gradj {{{1*/
-void  Penta::Gradj(Vec gradient,int control_type){
-	/*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
-
-	int              i,approximation;
-	Tria*            tria=NULL;
-
-	/*If on water, skip grad (=0): */
-	if(IsOnWater())return;
-
-	/*First deal with ∂/∂alpha(KU-F)*/
-	switch(control_type){
-
-		case FrictionCoefficientEnum:
-			inputs->GetParameterValue(&approximation,ApproximationEnum);
-			switch(approximation){
-				case MacAyealApproximationEnum:
-					GradjDragMacAyeal(gradient);
-					break;
-				case PattynApproximationEnum:
-					GradjDragPattyn(gradient);
-					break;
-				case StokesApproximationEnum:
-					GradjDragStokes(gradient);
-					break;
-				case NoneApproximationEnum:
-					/*Gradient is 0*/
-					break;
-				default:
-					_error_("approximation %s not supported yet",EnumToStringx(approximation));
-			}
-			break;
-
-		case MaterialsRheologyBbarEnum:
-			inputs->GetParameterValue(&approximation,ApproximationEnum);
-			switch(approximation){
-				case MacAyealApproximationEnum:
-					GradjBbarMacAyeal(gradient);
-					break;
-				case PattynApproximationEnum:
-					GradjBbarPattyn(gradient);
-					break;
-				case StokesApproximationEnum:
-					GradjBbarStokes(gradient);
-					break;
-				case NoneApproximationEnum:
-					/*Gradient is 0*/
-					break;
-				default:
-					_error_("approximation %s not supported yet",EnumToStringx(approximation));
-			}
-			break;
-
-		default:
-			_error_("control type %s not supported yet: ",EnumToStringx(control_type));
-	}
-
-	/*Now deal with ∂J/∂alpha*/
-	int        *responses = NULL;
-	int         num_responses,resp;
-	this->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);
-	this->parameters->FindParam(&responses,NULL,NULL,StepResponsesEnum);
-
-	for(resp=0;resp<num_responses;resp++) switch(responses[resp]){
-
-		case ThicknessAbsMisfitEnum:
-		case SurfaceAbsVelMisfitEnum:
-		case SurfaceRelVelMisfitEnum:
-		case SurfaceLogVelMisfitEnum:
-		case SurfaceLogVxVyMisfitEnum:
-		case SurfaceAverageVelMisfitEnum:
-			/*Nothing, J does not depends on the parameter being inverted for*/
-			break;
-		case DragCoefficientAbsGradientEnum:
-			if (!IsOnBed()) return;
-			tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-			tria->GradjDragGradient(gradient,resp);
-			delete tria->matice; delete tria;
-			break;
-		case RheologyBbarAbsGradientEnum:
-			if (!IsOnBed()) return;
-			tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-			tria->GradjBGradient(gradient,resp);
-			delete tria->matice; delete tria;
-			break;
-		default:
-			_error_("response %s not supported yet",EnumToStringx(responses[resp]));
-	}
-	xfree((void**)&responses);
-}
-/*}}}*/
-/*FUNCTION Penta::GradjDragMacAyeal {{{1*/
-void  Penta::GradjDragMacAyeal(Vec gradient){
-
-	/*Gradient is 0 if on shelf or not on bed*/
-	if(IsOnShelf() || !IsOnBed()) return;
-
-	/*Spawn tria*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	tria->GradjDragMacAyeal(gradient);
-	delete tria->matice; delete tria;
-
-} /*}}}*/
-/*FUNCTION Penta::GradjDragPattyn {{{1*/
-void  Penta::GradjDragPattyn(Vec gradient){
-
-	int        i,j,ig;
-	int        analysis_type;
-	int        doflist1[NUMVERTICES];
-	double     vx,vy,lambda,mu,alpha_complement,Jdet;
-	double     bed,thickness,Neff,drag;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double     dk[NDOF3]; 
-	double     grade_g[NUMVERTICES]={0.0};
-	double     grade_g_gaussian[NUMVERTICES];
-	double     basis[6];
-	Friction*  friction=NULL;
-	GaussPenta  *gauss=NULL;
-
-	/*Gradient is 0 if on shelf or not on bed*/
-	if(IsOnShelf() || !IsOnBed()) return;
-
-	/*Retrieve all inputs and parameters*/
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	GetDofList1(&doflist1[0]);
-	Input* adjointx_input=inputs->GetInput(AdjointxEnum);               _assert_(adjointx_input);
-	Input* adjointy_input=inputs->GetInput(AdjointyEnum);               _assert_(adjointy_input);
-	Input* vx_input=inputs->GetInput(VxEnum);                           _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);                           _assert_(vy_input);
-	Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
-
-	/*Build frictoin element, needed later: */
-	friction=new Friction("2d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		/*Build alpha_complement_list: */
-		friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
-
-		dragcoefficient_input->GetParameterValue(&drag, gauss);
-		adjointx_input->GetParameterValue(&lambda, gauss);
-		adjointy_input->GetParameterValue(&mu, gauss);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
-
-		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
-		for (i=0;i<NUMVERTICES;i++){
-			grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; /*basis are 0 for the 3 upper nodes*/
-		}
-
-		/*Add gradje_g_gaussian vector to gradje_g: */
-		for(i=0;i<NUMVERTICES;i++){
-			_assert_(!isnan(grade_g[i]));
-			grade_g[i]+=grade_g_gaussian[i];
-		}
-	}
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-}
-/*}}}*/
-/*FUNCTION Penta::GradjDragStokes {{{1*/
-void  Penta::GradjDragStokes(Vec gradient){
-
-	int        i,j,ig;
-	int        analysis_type;
-	int        doflist1[NUMVERTICES];
-	double     bed,thickness,Neff;
-	double     lambda,mu,xi,Jdet,vx,vy,vz;
-	double     alpha_complement,drag;
-	double     surface_normal[3],bed_normal[3];
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
-	double     dk[NDOF3]; 
-	double     basis[6];
-	double     grade_g[NUMVERTICES]={0.0};
-	double     grade_g_gaussian[NUMVERTICES];
-	Friction*  friction=NULL;
-	GaussPenta* gauss=NULL;
-
-	/*Gradient is 0 if on shelf or not on bed*/
-	if(IsOnShelf() || !IsOnBed()) return;
-
-	/*Retrieve all inputs and parameters*/
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	GetDofList1(&doflist1[0]);
-	Input* drag_input    =inputs->GetInput(FrictionCoefficientEnum); _assert_(drag_input);
-	Input* vx_input      =inputs->GetInput(VxEnum);              _assert_(vx_input);
-	Input* vy_input      =inputs->GetInput(VyEnum);              _assert_(vy_input);
-	Input* vz_input      =inputs->GetInput(VzEnum);              _assert_(vz_input);
-	Input* adjointx_input=inputs->GetInput(AdjointxEnum);        _assert_(adjointx_input);
-	Input* adjointy_input=inputs->GetInput(AdjointyEnum);        _assert_(adjointy_input);
-	Input* adjointz_input=inputs->GetInput(AdjointzEnum);        _assert_(adjointz_input);
-
-	/*Build frictoin element, needed later: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,4);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/*Recover alpha_complement and drag: */
-		friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
-		drag_input->GetParameterValue(&drag,gauss);
-
-		/*recover lambda mu and xi: */
-		adjointx_input->GetParameterValue(&lambda,gauss);
-		adjointy_input->GetParameterValue(&mu    ,gauss);
-		adjointz_input->GetParameterValue(&xi    ,gauss);
-
-		/*recover vx vy and vz: */
-		vx_input->GetParameterValue(&vx, gauss);
-		vy_input->GetParameterValue(&vy, gauss);
-		vz_input->GetParameterValue(&vz, gauss);
-
-		/*Get normal vector to the bed */
-		SurfaceNormal(&surface_normal[0],xyz_list_tria);
-
-		bed_normal[0]=-surface_normal[0]; //Function is for upper surface, so the normal to the bed is the opposite of the result
-		bed_normal[1]=-surface_normal[1];
-		bed_normal[2]=-surface_normal[2];
-
-		/* Get Jacobian determinant: */
-		GetTriaJacobianDeterminant(&Jdet,&xyz_list_tria[0][0],gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		/*Get k derivative: dk/dx */
-		drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
-
-		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
-		for (i=0;i<NUMVERTICES;i++){
-			//standard gradient dJ/dki
-			grade_g_gaussian[i]=(
-						-lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
-						-mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
-						-xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
-						)*Jdet*gauss->weight*basis[i]; 
-		}
-
-		/*Add gradje_g_gaussian vector to gradje_g: */
-		for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i];
-	}
-
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	delete friction;
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Penta::GradjBbarMacAyeal {{{1*/
-void  Penta::GradjBbarMacAyeal(Vec gradient){
-
-	/*This element should be collapsed into a tria element at its base*/
-	if (!IsOnBed()) return; 
-
-	/*Depth Average B*/
-	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
-
-	/*Collapse element to the base*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-	tria->GradjBMacAyeal(gradient);
-	delete tria->matice; delete tria;
-
-	/*delete Average B*/
-	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
-
-} /*}}}*/
-/*FUNCTION Penta::GradjBbarPattyn {{{1*/
-void  Penta::GradjBbarPattyn(Vec gradient){
-
-	/*Gradient is computed on bed only (Bbar)*/
-	if (!IsOnBed()) return;
-
-	/*Depth Average B*/
-	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
-
-	/*Collapse element to the base*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2);
-	tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
-	delete tria->matice; delete tria;
-
-	/*delete Average B*/
-	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
-} /*}}}*/
-/*FUNCTION Penta::GradjBbarStokes {{{1*/
-void  Penta::GradjBbarStokes(Vec gradient){
-
-	/*Gradient is computed on bed only (Bbar)*/
-	if (!IsOnBed()) return;
-
-	/*Depth Average B*/
-	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
-
-	/*Collapse element to the base*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2);
-	tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
-	delete tria->matice; delete tria;
-
-	/*delete Average B*/
-	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
-} /*}}}*/
-/*FUNCTION Penta::InputControlUpdate{{{1*/
-void  Penta::InputControlUpdate(double scalar,bool save_parameter){
-
-	/*Intermediary*/
-	int    num_controls;
-	int*   control_type=NULL;
-	Input* input=NULL;
-
-	/*retrieve some parameters: */
-	this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
-	this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum);
-
-	for(int i=0;i<num_controls;i++){
-
-		if(control_type[i]==MaterialsRheologyBbarEnum){
-			if (!IsOnBed()) goto cleanup_and_return;
-			input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum); _assert_(input);
-		}
-		else{
-			input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input);
-		}
-
-		if (input->Enum()!=ControlInputEnum) _error_("input %s is not a ControlInput",EnumToStringx(control_type[i]));
-
-		((ControlInput*)input)->UpdateValue(scalar);
-		((ControlInput*)input)->Constrain();
-		if (save_parameter) ((ControlInput*)input)->SaveValue();
-
-		if(control_type[i]==MaterialsRheologyBbarEnum){
-			this->InputExtrude(MaterialsRheologyBEnum,MaterialsEnum);
-		}
-	}
-
-	/*Clean up and return*/
-cleanup_and_return:
-	xfree((void**)&control_type);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/
-void  Penta::InputUpdateFromSolutionAdjointStokes(double* solution){
-
-	const int    numdof=NDOF4*NUMVERTICES;
-
-	int    i;
-	double values[numdof];
-	double lambdax[NUMVERTICES];
-	double lambday[NUMVERTICES];
-	double lambdaz[NUMVERTICES];
-	double lambdap[NUMVERTICES];
-	int*   doflist=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(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(i=0;i<NUMVERTICES;i++){
-		lambdax[i]=values[i*NDOF4+0];
-		lambday[i]=values[i*NDOF4+1];
-		lambdaz[i]=values[i*NDOF4+2];
-		lambdap[i]=values[i*NDOF4+3];
-
-		/*Check solution*/
-		if(isnan(lambdax[i])) _error_("NaN found in solution vector");
-		if(isnan(lambday[i])) _error_("NaN found in solution vector");
-		if(isnan(lambdaz[i])) _error_("NaN found in solution vector");
-		if(isnan(lambdap[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
-	this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
-	this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz));
-	this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/
-void  Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){
-
-	const int numdof=NDOF2*NUMVERTICES;
-
-	int    i;
-	double values[numdof];
-	double lambdax[NUMVERTICES];
-	double lambday[NUMVERTICES];
-	int*   doflist=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(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(i=0;i<NUMVERTICES;i++){
-		lambdax[i]=values[i*NDOF2+0];
-		lambday[i]=values[i*NDOF2+1];
-
-		/*Check solution*/
-		if(isnan(lambdax[i]))       _error_("NaN found in solution vector");
-		if(isnan(lambday[i]))       _error_("NaN found in solution vector");
-	}
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
-	this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/
-double Penta::SurfaceAverageVelMisfit(bool process_units,int weight_index){
-
-	int    approximation;
-	double J;
-	Tria*  tria=NULL;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Bail out if this element if:
-	 * -> Non MacAyeal and not on the surface
-	 * -> MacAyeal (2d model) and not on bed) */
-	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
-		return 0;
-	}
-	else if (approximation==MacAyealApproximationEnum){
-
-		/*This element should be collapsed into a tria element at its base. Create this tria element, 
-		 * and compute SurfaceAverageVelMisfit*/
-		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-		J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-	else{
-
-		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-		J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/
-double Penta::SurfaceAbsVelMisfit(bool process_units,int weight_index){
-
-	int    approximation;
-	double J;
-	Tria*  tria=NULL;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Bail out if this element if:
-	 * -> Non MacAyeal and not on the surface
-	 * -> MacAyeal (2d model) and not on bed) */
-	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
-		return 0;
-	}
-	else if (approximation==MacAyealApproximationEnum){
-
-		/*This element should be collapsed into a tria element at its base. Create this tria element, 
-		 * and compute SurfaceAbsVelMisfit*/
-		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-		J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-	else{
-
-		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-		J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/
-double Penta::SurfaceLogVelMisfit(bool process_units,int weight_index){
-
-	int    approximation;
-	double J;
-	Tria*  tria=NULL;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Bail out if this element if:
-	 * -> Non MacAyeal and not on the surface
-	 * -> MacAyeal (2d model) and not on bed) */
-	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
-		return 0;
-	}
-	else if (approximation==MacAyealApproximationEnum){
-
-		/*This element should be collapsed into a tria element at its base. Create this tria element, 
-		 * and compute SurfaceLogVelMisfit*/
-		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-		J=tria->SurfaceLogVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-	else{
-
-		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-		J=tria->SurfaceLogVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/
-double Penta::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
-
-	double J;
-	Tria* tria=NULL;
-
-	/*inputs: */
-	int  approximation;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Bail out if this element if:
-	 * -> Non MacAyeal and not on the surface
-	 * -> MacAyeal (2d model) and not on bed) */
-	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
-		return 0;
-	}
-	else if (approximation==MacAyealApproximationEnum){
-
-		/*This element should be collapsed into a tria element at its base. Create this tria element, 
-		 * and compute SurfaceLogVxVyMisfit*/
-		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-		J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-	else{
-
-		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-		J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/
-double Penta::SurfaceRelVelMisfit(bool process_units,int weight_index){
-
-	int    approximation;
-	double J;
-	Tria*  tria=NULL;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Bail out if this element if:
-	 * -> Non MacAyeal and not on the surface
-	 * -> MacAyeal (2d model) and not on bed) */
-	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
-		return 0;
-	}
-	else if (approximation==MacAyealApproximationEnum){
-
-		/*This element should be collapsed into a tria element at its base. Create this tria element, 
-		 * and compute SurfaceRelVelMisfit*/
-		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
-		J=tria->SurfaceRelVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-	else{
-
-		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
-		J=tria->SurfaceRelVelMisfit(process_units,weight_index);
-		delete tria->matice; delete tria;
-		return J;
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::ThicknessAbsGradient{{{1*/
-double Penta::ThicknessAbsGradient(bool process_units,int weight_index){
-
-	_error_("Not implemented yet");
-}
-/*}}}*/
-/*FUNCTION Penta::ThicknessAbsMisfit {{{1*/
-double Penta::ThicknessAbsMisfit(bool process_units,int weight_index){
-
-	int    approximation;
-	double J;
-	Tria*  tria=NULL;
-
-	/*retrieve inputs :*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-	_error_("Not implemented yet");
-
-	tria=(Tria*)SpawnTria(0,1,2);
-	J=tria->ThicknessAbsMisfit(process_units,weight_index);
-	delete tria->matice; delete tria;
-	return J;
-}
-/*}}}*/
-/*FUNCTION Penta::DragCoefficientAbsGradient{{{1*/
-double Penta::DragCoefficientAbsGradient(bool process_units,int weight_index){
-
-	double J;
-	Tria*  tria=NULL;
-
-	/*If on water, on shelf or not on bed, skip: */
-	if(IsOnWater()|| IsOnShelf() || !IsOnBed()) return 0;
-
-	tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
-	J=tria->DragCoefficientAbsGradient(process_units,weight_index);
-	delete tria->matice; delete tria;
-	return J;
-}
-/*}}}*/
-/*FUNCTION Penta::RheologyBbarAbsGradient{{{1*/
-double Penta::RheologyBbarAbsGradient(bool process_units,int weight_index){
-
-	double J;
-	Tria*  tria=NULL;
-
-	/*If on water, on shelf or not on bed, skip: */
-	if(IsOnWater() || !IsOnBed()) return 0;
-
-	tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
-	J=tria->RheologyBbarAbsGradient(process_units,weight_index);
-	delete tria->matice; delete tria;
-	return J;
-}
-/*}}}*/
-
-#endif
-
-
-#ifdef _HAVE_DAKOTA_
-/*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/
-void  Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){
-	
-	int i,j;
-
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-
-	switch(type){
-
-		case VertexEnum:
-
-			/*New PentaVertexInput*/
-			double values[6];
-
-			/*Get values on the 6 vertices*/
-			for (i=0;i<6;i++){
-				values[i]=vector[this->nodes[i]->GetSidList()]; //careful, vector of values here is not parallel distributed, but serial distributed (from a serial Dakota core!)
-			}
-
-			/*Branch on the specified type of update: */
-			switch(name){
-				case ThicknessEnum:
-					/*Update thickness + surface: assume bed is constant. On ice shelves, takes hydrostatic equilibrium {{{2*/
-					double  thickness[6];
-					double  thickness_init[6];
-					double  hydrostatic_ratio[6];
-					double  surface[6];
-					double  bed[6];
-					
-					/*retrieve inputs: */
-					GetParameterListOnVertices(&thickness_init[0],ThicknessEnum);
-					GetParameterListOnVertices(&hydrostatic_ratio[0],GeometryHydrostaticRatioEnum);
-					GetParameterListOnVertices(&bed[0],BedEnum);
-					GetParameterListOnVertices(&surface[0],SurfaceEnum);
-
-					/*build new thickness: */
-//					for(j=0;j<6;j++)thickness[j]=values[j];
-
-					/*build new bed and surface: */
-					if (this->IsOnShelf()){
-						/*hydrostatic equilibrium: */
-						double rho_ice,rho_water,di;
-						rho_ice=this->matpar->GetRhoIce();
-						rho_water=this->matpar->GetRhoWater();
-
-						di=rho_ice/rho_water;
-
-						/*build new thickness: */
-						for (j=0; j<6; j++) {
-						/*  for observed/interpolated/hydrostatic thickness, remove scaling from any hydrostatic thickness  */
-							if     (hydrostatic_ratio[j] >= 0.)
-								thickness[j]=values[j]-(values[j]/thickness_init[j]-1.)*hydrostatic_ratio[j]*surface[j]/(1.-di);
-						/*  for minimum thickness, don't scale  */
-							else
-								thickness[j]=thickness_init[j];
-
-						/*  check the computed thickness and update bed  */
-							if (thickness[j] < 0.)
-								thickness[j]=1./(1.-di);
-							bed[j]=surface[j]-thickness[j];
-						}
-
-//						for(j=0;j<6;j++){
-//							surface[j]=(1-di)*thickness[j];
-//							bed[j]=-di*thickness[j];
-//						}
-					}
-					else{
-						/*build new thickness: */
-						for (j=0; j<6; j++) {
-						/*  for observed thickness, use scaled value  */
-							if(hydrostatic_ratio[j] >= 0.)
-								thickness[j]=values[j];
-						/*  for minimum thickness, don't scale  */
-							else
-								thickness[j]=thickness_init[j];
-						}
-
-						/*update bed on grounded ice: */
-//						for(j=0;j<6;j++)surface[j]=bed[j]+thickness[j];
-						for(j=0;j<6;j++)bed[j]=surface[j]-thickness[j];
-					}
-
-					/*Add new inputs: */
-					this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,thickness));
-					this->inputs->AddInput(new PentaVertexInput(BedEnum,bed));
-					this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,surface));
-
-					/*}}}*/
-					break;
-				default:
-					this->inputs->AddInput(new PentaVertexInput(name,values));
-			}
-			break;
-
-		default:
-			_error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
-	}
-
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/
-void  Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){
-	_error_(" not supported yet!");
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/
-void  Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){
-	_error_(" not supported yet!");
-}
-/*}}}*/
-#endif
-
 /*FUNCTION Penta::CreatePVector {{{1*/
 void  Penta::CreatePVector(Vec pf){
@@ -3860,12 +642,8 @@
 	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
 	switch(analysis_type){
+		#ifdef _HAVE_DIAGNOSTIC_
 		case DiagnosticHorizAnalysisEnum:
 			pe=CreatePVectorDiagnosticHoriz();
 			break;
-		#ifdef _HAVE_CONTROL_
-		case AdjointHorizAnalysisEnum:
-			pe=CreatePVectorAdjointHoriz();
-			break;
-		#endif
 		case DiagnosticHutterAnalysisEnum:
 			pe=CreatePVectorDiagnosticHutter();
@@ -3874,13 +652,10 @@
 			pe=CreatePVectorDiagnosticVert();
 			break;
-		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
-			pe=CreatePVectorSlope();
+		#endif
+	 	#ifdef _HAVE_CONTROL_
+		case AdjointHorizAnalysisEnum:
+			pe=CreatePVectorAdjointHoriz();
 			break;
-		case PrognosticAnalysisEnum:
-			pe=CreatePVectorPrognostic();
-			break;
-		case BalancethicknessAnalysisEnum:
-			pe=CreatePVectorBalancethickness();
-			break;
+		#endif
 		#ifdef _HAVE_THERMAL_
 		case ThermalAnalysisEnum:
@@ -3894,4 +669,15 @@
 			break;
 		#endif
+		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
+			pe=CreatePVectorSlope();
+			break;
+		case PrognosticAnalysisEnum:
+			pe=CreatePVectorPrognostic();
+			break;
+		#ifdef _HAVE_BALANCED_
+		case BalancethicknessAnalysisEnum:
+			pe=CreatePVectorBalancethickness();
+			break;
+		#endif
 		default:
 			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
@@ -3903,830 +689,4 @@
 		delete pe;
 	}
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorBalancethickness {{{1*/
-ElementVector* Penta::CreatePVectorBalancethickness(void){
-
-	if (!IsOnBed()) return NULL;
-
-	/*Depth Averaging Vx and Vy*/
-	this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
-	this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementVector* pe=tria->CreatePVectorBalancethickness();
-	delete tria->matice; delete tria;
-
-	/*Delete Vx and Vy averaged*/
-	this->inputs->DeleteInput(VxAverageEnum);
-	this->inputs->DeleteInput(VyAverageEnum);
-
-	/*Clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokes {{{1*/
-ElementVector* Penta::CreatePVectorCouplingMacAyealStokes(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorCouplingMacAyealStokesViscous();
-	ElementVector* pe2=CreatePVectorCouplingMacAyealStokesFriction();
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesViscous {{{1*/
-ElementVector* Penta::CreatePVectorCouplingMacAyealStokesViscous(void){
-
-	/*Constants*/
-	const int   numdof=NUMVERTICES*NDOF4;
-
-	/*Intermediaries */
-	int         i,j,ig;
-	int         approximation;
-	double      viscosity,Jdet;
-	double      stokesreconditioning;
-	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double      dw[3];
-	double      xyz_list[NUMVERTICES][3];
-	double      basis[6]; //for the six nodes of the penta
-	double      dbasis[3][6]; //for the six nodes of the penta
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=MacAyealStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
-	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-		GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-		vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		for(i=0;i<NUMVERTICES;i++){
-			pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
-			pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
-			pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
-			pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesFriction{{{1*/
-ElementVector* Penta::CreatePVectorCouplingMacAyealStokesFriction(void){
-
-	/*Constants*/
-	const int numdof=NUMVERTICES*NDOF4;
-
-	/*Intermediaries*/
-	int         i,j,ig;
-	int         approximation,analysis_type;
-	double      Jdet,Jdet2d;
-	double      stokesreconditioning;
-	double	   bed_normal[3];
-	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double      viscosity, w, alpha2_gauss;
-	double      dw[3];
-	double	   xyz_list_tria[NUMVERTICES2D][3];
-	double      xyz_list[NUMVERTICES][3];
-	double      basis[6]; //for the six nodes of the penta
-	Tria*       tria=NULL;
-	Friction*   friction=NULL;
-	GaussPenta  *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	if(!IsOnBed() || IsOnShelf()) return NULL;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=MacAyealStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
-	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
-
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/*build friction object, used later on: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		vzmacayeal_input->GetParameterValue(&w, gauss);
-		vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
-
-		BedNormal(&bed_normal[0],xyz_list_tria);
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
-
-		for(i=0;i<NUMVERTICES2D;i++){
-			pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
-			pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
-			pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/
-ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous();
-	ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction();
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/
-ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){
-
-	/*Constants*/
-	const int   numdof=NUMVERTICES*NDOF4;
-
-	/*Intermediaries */
-	int         i,j,ig;
-	int         approximation;
-	double      viscosity,Jdet;
-	double      stokesreconditioning;
-	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double      dw[3];
-	double      xyz_list[NUMVERTICES][3];
-	double      basis[6]; //for the six nodes of the penta
-	double      dbasis[3][6]; //for the six nodes of the penta
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=PattynStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
-	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-		GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
-
-		vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		for(i=0;i<NUMVERTICES;i++){
-			pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
-			pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
-			pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
-			pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/
-ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){
-
-	/*Constants*/
-	const int numdof=NUMVERTICES*NDOF4;
-
-	/*Intermediaries*/
-	int         i,j,ig;
-	int         approximation,analysis_type;
-	double      Jdet,Jdet2d;
-	double      stokesreconditioning;
-	double	   bed_normal[3];
-	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double      viscosity, w, alpha2_gauss;
-	double      dw[3];
-	double	   xyz_list_tria[NUMVERTICES2D][3];
-	double      xyz_list[NUMVERTICES][3];
-	double      basis[6]; //for the six nodes of the penta
-	Tria*       tria=NULL;
-	Friction*   friction=NULL;
-	GaussPenta  *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	if(!IsOnBed() || IsOnShelf()) return NULL;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=PattynStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
-	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
-
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/*build friction object, used later on: */
-	friction=new Friction("3d",inputs,matpar,analysis_type);
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		vzpattyn_input->GetParameterValue(&w, gauss);
-		vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
-
-		BedNormal(&bed_normal[0],xyz_list_tria);
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
-
-		for(i=0;i<NUMVERTICES2D;i++){
-			pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
-			pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
-			pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){
-
-	int approximation;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	switch(approximation){
-		case MacAyealApproximationEnum:
-			return CreatePVectorDiagnosticMacAyeal();
-		case PattynApproximationEnum:
-			return CreatePVectorDiagnosticPattyn();
-		case HutterApproximationEnum:
-			return NULL;
-		case NoneApproximationEnum:
-			return NULL;
-		case StokesApproximationEnum:
-			return CreatePVectorDiagnosticStokes();
-		case MacAyealPattynApproximationEnum:
-			return CreatePVectorDiagnosticMacAyealPattyn();
-		case MacAyealStokesApproximationEnum:
-			return CreatePVectorDiagnosticMacAyealStokes();
-		case PattynStokesApproximationEnum:
-			return CreatePVectorDiagnosticPattynStokes();
-		default:
-			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
-	ElementVector* pe2=CreatePVectorDiagnosticPattyn();
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealStokes{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticMacAyealStokes(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
-	ElementVector* pe2=CreatePVectorDiagnosticStokes();
-	ElementVector* pe3=CreatePVectorCouplingMacAyealStokes();
-	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	delete pe3;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorDiagnosticPattyn();
-	ElementVector* pe2=CreatePVectorDiagnosticStokes();
-	ElementVector* pe3=CreatePVectorCouplingPattynStokes();
-	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	delete pe3;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticHutter(void){
-
-	/*Constants*/
-	const int numdofs=NDOF2*NUMVERTICES;
-
-	/*Intermediaries*/
-	int          i,j,k,ig;
-	int          node0,node1;
-	int          connectivity[2];
-	double       Jdet;
-	double       xyz_list[NUMVERTICES][3];
-	double       xyz_list_segment[2][3];
-	double       z_list[NUMVERTICES];
-	double       z_segment[2],slope[2];
-	double       slope2,constant_part;
-	double       rho_ice,gravity,n,B;
-	double       ub,vb,z_g,surface,thickness;
-	GaussPenta*  gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	rho_ice=matpar->GetRhoIce();
-	gravity=matpar->GetG();
-	n=matice->GetN();
-	B=matice->GetB();
-	Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
-	Input* surface_input=inputs->GetInput(SurfaceEnum);      _assert_(surface_input);
-	Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
-	Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
-	for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2];
-
-	/*Loop on the three segments*/
-	for(i=0;i<3;i++){
-		node0=i;
-		node1=i+3;
-
-		for(j=0;j<3;j++){
-			xyz_list_segment[0][j]=xyz_list[node0][j];
-			xyz_list_segment[1][j]=xyz_list[node1][j];
-		}
-
-		connectivity[0]=nodes[node0]->GetConnectivity();
-		connectivity[1]=nodes[node1]->GetConnectivity();
-
-		/*Loop on the Gauss points: */
-		gauss=new GaussPenta(node0,node1,3);
-		for(ig=gauss->begin();ig<gauss->end();ig++){
-			gauss->GaussPoint(ig);
-
-			slopex_input->GetParameterValue(&slope[0],gauss);
-			slopey_input->GetParameterValue(&slope[1],gauss);
-			surface_input->GetParameterValue(&surface,gauss);
-			thickness_input->GetParameterValue(&thickness,gauss);
-
-			slope2=pow(slope[0],2)+pow(slope[1],2);
-			constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
-
-			PentaRef::GetParameterValue(&z_g,&z_list[0],gauss);
-			GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss);
-
-			if (IsOnSurface()){
-				for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1];
-			}
-			else{//connectivity is too large, should take only half on it
-				for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1];
-			}
-		}
-		delete gauss;
-
-		//Deal with lower surface
-		if (IsOnBed()){
-			constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness;
-			ub=constant_part*slope[0];
-			vb=constant_part*slope[1];
-
-			pe->values[2*node0]+=ub/(double)connectivity[0];
-			pe->values[2*node0+1]+=vb/(double)connectivity[0];
-		}
-	}
-
-	/*Clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){
-
-	if (!IsOnBed()) return NULL;
-
-	/*Call Tria function*/
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal();
-	delete tria->matice; delete tria;
-
-	/*Clean up and return*/
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){
-
-	/*Constants*/
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries*/
-	int         i,j,ig;
-	double      Jdet;
-	double      slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!
-	double      driving_stress_baseline,thickness;
-	double      xyz_list[NUMVERTICES][3];
-	double      basis[6];
-	GaussPenta  *gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
-	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,3);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		thickness_input->GetParameterValue(&thickness, gauss);
-		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-
-		driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();
-
-		for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticStokes(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorDiagnosticStokesViscous();
-	ElementVector* pe2=CreatePVectorDiagnosticStokesShelf();
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){
-
-	/*Constants*/
-	const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1;
-
-	/*Intermediaries*/
-	int        i,j,ig;
-	int        approximation;
-	double     Jdet,viscosity;
-	double     gravity,rho_ice,stokesreconditioning;
-	double     xyz_list[NUMVERTICES][3];
-	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
-	double     l1l7[7]; //for the six nodes and the bubble 
-	double     B[8][numdofbubble];
-	double     B_prime[8][numdofbubble];
-	double     B_prime_bubble[8][3];
-	double     D[8][8]={0.0};
-	double     D_scalar;
-	double     Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble 
-	double     Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble 
-	double     Ke_gaussian[numdofbubble][3];
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	rho_ice=matpar->GetRhoIce();
-	gravity=matpar->GetG();
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(5,5);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 
-		GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss); 
-		GetNodalFunctionsMINI(&l1l7[0], gauss);
-
-		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
-		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
-
-		for(i=0;i<NUMVERTICES+1;i++){
-			Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i];
-		}
-
-		/*Get bubble part of Bprime */
-		for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24];
-
-		D_scalar=gauss->weight*Jdet;
-		for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
-		for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
-
-		TripleMultiply(&B[0][0],8,numdofbubble,1,
-					&D[0][0],8,8,0,
-					&B_prime_bubble[0][0],8,3,0,
-					&Ke_gaussian[0][0],0);
-
-		for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
-	}
-
-	/*Condensation*/
-	ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]);
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){
-
-	/*Intermediaries*/
-	int         i,j,ig;
-	int         approximation,shelf_dampening;
-	double      gravity,rho_water,bed,water_pressure;
-	double      damper,normal_vel,vx,vy,vz,dt;
-	double		xyz_list_tria[NUMVERTICES2D][3];
-	double      xyz_list[NUMVERTICES][3];
-	double		bed_normal[3];
-	double      dz[3];
-	double      basis[6]; //for the six nodes of the penta
-	double      Jdet2d;
-	GaussPenta  *gauss=NULL;
-
-	/*Initialize Element vector and return if necessary*/
-	if(!IsOnBed() || !IsOnShelf()) return NULL;
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	this->parameters->FindParam(&shelf_dampening,DiagnosticShelfDampeningEnum);
-	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	rho_water=matpar->GetRhoWater();
-	gravity=matpar->GetG();
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* bed_input=inputs->GetInput(BedEnum); _assert_(bed_input);
-	Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
-
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-
-	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		BedNormal(&bed_normal[0],xyz_list_tria);
-		bed_input->GetParameterValue(&bed, gauss);
-		if(shelf_dampening){ //add dampening to avoid too high vertical velocities when not in hydrostatic equilibrium
-			bed_input->GetParameterDerivativeValue(&dz[0],&xyz_list[0][0],gauss);
-			vx_input->GetParameterValue(&vx, gauss);
-			vy_input->GetParameterValue(&vy, gauss);
-			vz_input->GetParameterValue(&vz, gauss);
-			dt=0;
-			normal_vel=bed_normal[0]*vx+bed_normal[1]*vy+bed_normal[2]*vz;
-			damper=gravity*rho_water*pow(1+pow(dz[0],2)+pow(dz[1],2),0.5)*normal_vel*dt;
-		}
-		else damper=0;
-		water_pressure=gravity*rho_water*bed;
-
-		for(i=0;i<NUMVERTICES;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=(water_pressure+damper)*gauss->weight*Jdet2d*basis[i]*bed_normal[j];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticVert(void){
-
-	/*compute all load vectors for this element*/
-	ElementVector* pe1=CreatePVectorDiagnosticVertVolume();
-	ElementVector* pe2=CreatePVectorDiagnosticVertBase();
-	ElementVector* pe =new ElementVector(pe1,pe2);
-
-	/*clean-up and return*/
-	delete pe1;
-	delete pe2;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){
-
-	/*Constants*/
-	const int  numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries*/
-	int        i,ig;
-	int        approximation;
-	double     Jdet;
-	double     xyz_list[NUMVERTICES][3];
-	double     dudx,dvdy,dwdz;
-	double     du[3],dv[3],dw[3];
-	double     basis[6];
-	GaussPenta *gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-	Input* vzstokes_input=NULL;
-	if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
-		vzstokes_input=inputs->GetInput(VzStokesEnum); _assert_(vzstokes_input);
-	}
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(2,2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctionsP1(basis, gauss);
-
-		vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss);
-		vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss);
-		if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
-			vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
-			dwdz=dw[2];
-		}
-		else dwdz=0;
-		dudx=du[0];
-		dvdy=dv[1];
-
-		for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/
-ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){
-
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	int        approximation;
-	double     xyz_list[NUMVERTICES][3];
-	double     xyz_list_tria[NUMVERTICES2D][3];
-	double     Jdet2d;
-	double     vx,vy,vz,dbdx,dbdy,basalmeltingvalue;
-	double     slope[3];
-	double     basis[NUMVERTICES];
-	GaussPenta* gauss=NULL;
-
-	if (!IsOnBed()) return NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	Input* bed_input=inputs->GetInput(BedEnum);                                _assert_(bed_input);
-	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
-	Input* vx_input=inputs->GetInput(VxEnum);                                  _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);                                  _assert_(vy_input);
-	Input* vzstokes_input=NULL;
-	if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
-		vzstokes_input=inputs->GetInput(VzStokesEnum);       _assert_(vzstokes_input);
-	}
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussPenta(0,1,2,2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		basal_melting_input->GetParameterValue(&basalmeltingvalue, gauss);
-		bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-		vx_input->GetParameterValue(&vx, gauss);
-		vy_input->GetParameterValue(&vy, gauss);
-		if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
-			vzstokes_input->GetParameterValue(&vz, gauss);
-		}
-		else vz=0;
-
-		dbdx=slope[0];
-		dbdy=slope[1];
-
-		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
-		GetNodalFunctionsP1(&basis[0], gauss);
-
-		for(i=0;i<numdof;i++) pe->values[i]+=-Jdet2d*gauss->weight*(vx*dbdx+vy*dbdy-vz-basalmeltingvalue)*basis[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
 }
 /*}}}*/
@@ -5029,5 +989,7 @@
 
 	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
-	if (analysis_type==DiagnosticHorizAnalysisEnum){
+	switch(analysis_type){
+	#ifdef _HAVE_DIAGNOSTIC_
+	case DiagnosticHorizAnalysisEnum:
 		int approximation;
 		inputs->GetParameterValue(&approximation,ApproximationEnum);
@@ -5041,178 +1003,23 @@
 			return; //the elements around will create the solution
 		}
-	}
-	else if(analysis_type==DiagnosticHutterAnalysisEnum){
+		break;
+	case DiagnosticHutterAnalysisEnum:
 		GetSolutionFromInputsDiagnosticHutter(solution);
-	}
-	else if(analysis_type==DiagnosticVertAnalysisEnum){
+		break;
+	case DiagnosticVertAnalysisEnum:
 		GetSolutionFromInputsDiagnosticVert(solution);
-	}
+		break;
+	#endif
 	#ifdef _HAVE_THERMAL_
-	else if(analysis_type==ThermalAnalysisEnum){
+	case ThermalAnalysisEnum:
 		GetSolutionFromInputsThermal(solution);
-	}
-	else if(analysis_type==EnthalpyAnalysisEnum){
+		break;
+	case EnthalpyAnalysisEnum:
 		GetSolutionFromInputsEnthalpy(solution);
-	}
+		break;
 	#endif
-	else{
+	default:
 		_error_("analysis: %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
 	}
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/
-void  Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int          i;
-	int          approximation;
-	int*         doflist=NULL;
-	double       vx,vy;
-	double       values[numdof];
-	GaussPenta*  gauss;
-
-	/*Get approximation enum and dof list: */
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-
-	/*If the element is a coupling, do nothing: every node is also on an other elements 
-	 * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/
-	GetDofList(&doflist,approximation,GsetEnum);
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	/*P1 element only for now*/
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-
-		/*Recover vx and vy*/
-		gauss->GaussVertex(i);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		values[i*NDOF2+0]=vx;
-		values[i*NDOF2+1]=vy;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/
-void  Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       vx,vy;
-	double       values[numdof];
-	GaussPenta*  gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	/*P1 element only for now*/
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-		/*Recover vx and vy*/
-		gauss->GaussVertex(i);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		values[i*NDOF2+0]=vx;
-		values[i*NDOF2+1]=vy;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/
-void  Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       vz;
-	double       values[numdof];
-	GaussPenta*  gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	/*P1 element only for now*/
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-		/*Recover vz */
-		gauss->GaussVertex(i);
-		vz_input->GetParameterValue(&vz,gauss);
-		values[i]=vz;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/
-void  Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){
-
-	const int    numdof=NDOF4*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       vx,vy,vz,p;
-	double       stokesreconditioning;
-	double       values[numdof];
-	GaussPenta   *gauss;
-
-	/*Get dof list: */
-	GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
-	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
-	Input* p_input =inputs->GetInput(PressureEnum); _assert_(p_input);
-
-	/*Recondition pressure: */
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-
-	/*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */
-	/*P1 element only for now*/
-	gauss=new GaussPenta();
-	for(i=0;i<NUMVERTICES;i++){
-		gauss->GaussVertex(i);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vz_input->GetParameterValue(&vz,gauss);
-		p_input ->GetParameterValue(&p ,gauss);
-		values[i*NDOF4+0]=vx;
-		values[i*NDOF4+1]=vy;
-		values[i*NDOF4+2]=vz;
-		values[i*NDOF4+3]=p/stokesreconditioning;
-	}
-
-	/*Add value to global vector*/
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
 }
 /*}}}*/
@@ -5851,15 +1658,18 @@
 
 	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
-	if (analysis_type==DiagnosticHorizAnalysisEnum){
+	switch(analysis_type){
+	#ifdef _HAVE_DIAGNOSTIC_
+	case DiagnosticHorizAnalysisEnum:
 		InputUpdateFromSolutionDiagnosticHoriz( solution);
-	}
-	else if (analysis_type==DiagnosticHutterAnalysisEnum){
+		break;
+	case DiagnosticHutterAnalysisEnum:
 		InputUpdateFromSolutionDiagnosticHutter( solution);
-	}
-	else if (analysis_type==DiagnosticVertAnalysisEnum){
+		break;
+	case DiagnosticVertAnalysisEnum:
 		InputUpdateFromSolutionDiagnosticVert( solution);
-	}
+		break;
+	#endif
 	#ifdef _HAVE_CONTROL_
-	else if (analysis_type==AdjointHorizAnalysisEnum){
+	case AdjointHorizAnalysisEnum:
 		int approximation;
 		inputs->GetParameterValue(&approximation,ApproximationEnum);
@@ -5870,770 +1680,40 @@
 			InputUpdateFromSolutionAdjointHoriz( solution);
 		}
-	}
+		break;
 	#endif
-	else if (analysis_type==BedSlopeXAnalysisEnum){
+	#ifdef _HAVE_THERMAL_
+	case ThermalAnalysisEnum:
+		InputUpdateFromSolutionThermal( solution);
+		break;
+	case EnthalpyAnalysisEnum:
+		InputUpdateFromSolutionEnthalpy( solution);
+		break;
+	case MeltingAnalysisEnum:
+		InputUpdateFromSolutionOneDof(solution,BasalforcingsMeltingRateEnum);
+		break;
+	#endif
+	case BedSlopeXAnalysisEnum:
 		InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum);
-	}
-	else if (analysis_type==BedSlopeYAnalysisEnum){
+		break;
+	case BedSlopeYAnalysisEnum:
 		InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeYEnum);
-	}
-	else if (analysis_type==SurfaceSlopeXAnalysisEnum){
+		break;
+	case SurfaceSlopeXAnalysisEnum:
 		InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeXEnum);
-	}
-	else if (analysis_type==SurfaceSlopeYAnalysisEnum){
+		break;
+	case SurfaceSlopeYAnalysisEnum:
 		InputUpdateFromSolutionOneDofCollapsed(solution,SurfaceSlopeYEnum);
-	}
-	else if (analysis_type==PrognosticAnalysisEnum){
+		break;
+	case PrognosticAnalysisEnum:
 		InputUpdateFromSolutionPrognostic(solution);
-	}
-	else if (analysis_type==BalancethicknessAnalysisEnum){
+		break;
+	#ifdef _HAVE_BALANCED_
+	case BalancethicknessAnalysisEnum:
 		InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum);
-	}
-	#ifdef _HAVE_THERMAL_
-	else if (analysis_type==ThermalAnalysisEnum){
-		InputUpdateFromSolutionThermal( solution);
-	}
-	else if (analysis_type==EnthalpyAnalysisEnum){
-		InputUpdateFromSolutionEnthalpy( solution);
-	}
-	else if (analysis_type==MeltingAnalysisEnum){
-		InputUpdateFromSolutionOneDof(solution,BasalforcingsMeltingRateEnum);
-	}
+		break;
 	#endif
-	else{
+	default: 
 		_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
 	}
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
-
-	int  approximation;
-
-	/*Recover inputs*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-
-	/*MacAyeal, everything is done by the element on bed*/
-	if (approximation==MacAyealApproximationEnum){
-		if (!IsOnBed()){
-			/*Do nothing. Element on bed will take care of it*/
-			return;
-		}
-		else{
-			InputUpdateFromSolutionDiagnosticMacAyeal(solution);
-			return;
-		}
-	}
-	else if (approximation==PattynApproximationEnum){
-		InputUpdateFromSolutionDiagnosticPattyn(solution);
-	}
-	else if (approximation==PattynStokesApproximationEnum){
-		InputUpdateFromSolutionDiagnosticPattynStokes(solution);
-	}
-	else if (approximation==MacAyealStokesApproximationEnum){
-		InputUpdateFromSolutionDiagnosticMacAyealStokes(solution);
-	}
-	else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
-		InputUpdateFromSolutionDiagnosticStokes(solution);
-	}
-	else if (approximation==MacAyealPattynApproximationEnum){
-		InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution);
-	}
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int     i,dummy;
-	double  rho_ice,g;
-	double  values[numdof];
-	double  vx[NUMVERTICES];
-	double  vy[NUMVERTICES];
-	double  vz[NUMVERTICES];
-	double  vel[NUMVERTICES];
-	double  pressure[NUMVERTICES];
-	double  surface[NUMVERTICES];
-	double  xyz_list[NUMVERTICES][3];
-	int    *doflist = NULL;
-	double *vz_ptr  = NULL;
-	Penta  *penta   = NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */
-	for(i=0;i<3;i++){
-		vx[i]  =values[i*NDOF2+0];
-		vy[i]  =values[i*NDOF2+1];
-		vx[i+3]=vx[i];
-		vy[i+3]=vy[i];
-
-		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get parameters fro pressure computation*/
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-
-	/*Start looping over all elements above current element and update all inputs*/
-	penta=this;
-	for(;;){
-
-		/*Get node data: */
-		GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES);
-
-		/*Now Compute vel*/
-		Input* vz_input=inputs->GetInput(VzEnum);
-		if (vz_input){
-			if (vz_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
-			vz_input->GetValuesPtr(&vz_ptr,&dummy);
-			for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
-		}
-		else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;}
-		for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-		/*Now compute pressure*/
-		GetParameterListOnVertices(&surface[0],SurfaceEnum);
-		for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
-
-		/*Now, we have to move the previous Vx and Vy inputs  to old 
-		 * status, otherwise, we'll wipe them off: */
-		penta->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-		penta->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-		penta->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-		/*Add vx and vy as inputs to the tria element: */
-		penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-		penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-		penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-		penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-		/*Stop if we have reached the surface*/
-		if (penta->IsOnSurface()) break;
-
-		/* get upper Penta*/
-		penta=penta->GetUpperElement(); _assert_(penta->Id()!=this->id);
-	}
-	
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-	const int    numdof2d=NDOF2*NUMVERTICES2D;
-
-	int     i,dummy;
-	double  rho_ice,g;
-	double  macayeal_values[numdof];
-	double  pattyn_values[numdof];
-	double  vx[NUMVERTICES];
-	double  vy[NUMVERTICES];
-	double  vz[NUMVERTICES];
-	double  vel[NUMVERTICES];
-	double  pressure[NUMVERTICES];
-	double  surface[NUMVERTICES];
-	double  xyz_list[NUMVERTICES][3];
-	int*    doflistp = NULL;
-	int*    doflistm = NULL;
-	double  *vz_ptr  = NULL;
-	Penta   *penta   = NULL;
-
-	/*OK, we have to add results of this element for pattyn 
-	 * and results from the penta at base for macayeal. Now recover results*/
-	penta=GetBasalElement();
-
-	/*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
-	GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
-	penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
-
-	/*Get node data: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof2d;i++){
-		pattyn_values[i]=solution[doflistp[i]];
-		macayeal_values[i]=solution[doflistm[i]];
-	}
-	for(i=numdof2d;i<numdof;i++){
-		pattyn_values[i]=solution[doflistp[i]];
-		macayeal_values[i]=macayeal_values[i-numdof2d];
-	}
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0];
-		vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1];
-
-		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	Input* vz_input=inputs->GetInput(VzEnum);
-	if (vz_input){
-		if (vz_input->Enum()!=PentaVertexInputEnum){
-			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
-		}
-		vz_input->GetValuesPtr(&vz_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
-	}
-	else{
-		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
-	 *so the pressure is just the pressure at the z elevation: */
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-	GetParameterListOnVertices(&surface[0],SurfaceEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflistp);
-	xfree((void**)&doflistm);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){
-
-	const int    numdofm=NDOF2*NUMVERTICES;
-	const int    numdofs=NDOF4*NUMVERTICES;
-	const int    numdof2d=NDOF2*NUMVERTICES2D;
-
-	int     i,dummy;
-	double  stokesreconditioning;
-	double  macayeal_values[numdofm];
-	double  stokes_values[numdofs];
-	double  vx[NUMVERTICES];
-	double  vy[NUMVERTICES];
-	double  vz[NUMVERTICES];
-	double  vzmacayeal[NUMVERTICES];
-	double  vzstokes[NUMVERTICES];
-	double  vel[NUMVERTICES];
-	double  pressure[NUMVERTICES];
-	double  xyz_list[NUMVERTICES][3];
-	int*    doflistm        = NULL;
-	int*    doflists        = NULL;
-	double  *vzmacayeal_ptr = NULL;
-	Penta   *penta          = NULL;
-
-	/*OK, we have to add results of this element for macayeal 
-	 * and results from the penta at base for macayeal. Now recover results*/
-	penta=GetBasalElement();
-
-	/*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */
-	penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
-	GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-
-	/*Get node data: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof2d;i++){
-		macayeal_values[i]=solution[doflistm[i]];
-		macayeal_values[i+numdof2d]=solution[doflistm[i]];
-	}
-	for(i=0;i<numdofs;i++){
-		stokes_values[i]=solution[doflists[i]];
-	}
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0];
-		vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1];
-		vzstokes[i]=stokes_values[i*NDOF4+2];
-		pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
-
-		/*Check solution*/
-		if(isnan(vx[i]))       _error_("NaN found in solution vector");
-		if(isnan(vy[i]))       _error_("NaN found in solution vector");
-		if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
-		if(isnan(pressure[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);
-	if (vzmacayeal_input){
-		if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){
-			_error_("Cannot compute Vel as VzMacAyeal is of type %s",EnumToStringx(vzmacayeal_input->Enum()));
-		}
-		vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i];
-	}
-	else{
-		_error_("Cannot update solution as VzMacAyeal is not present");
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) {
-		vz[i]=vzmacayeal[i]+vzstokes[i];
-		vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-	}
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
-	this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflistm);
-	xfree((void**)&doflists);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){
-	
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int    i,dummy;
-	double rho_ice,g;
-	double values[numdof];
-	double vx[NUMVERTICES];
-	double vy[NUMVERTICES];
-	double vz[NUMVERTICES];
-	double vel[NUMVERTICES];
-	double pressure[NUMVERTICES];
-	double surface[NUMVERTICES];
-	double xyz_list[NUMVERTICES][3];
-	int*   doflist = NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,PattynApproximationEnum,GsetEnum);
-
-	/*Get node data: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector: */
-	for(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(i=0;i<NUMVERTICES;i++){
-		vx[i]=values[i*NDOF2+0];
-		vy[i]=values[i*NDOF2+1];
-
-		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	Input* vz_input=inputs->GetInput(VzEnum);
-	if (vz_input){
-		GetParameterListOnVertices(&vz[0],VzEnum);
-	}
-	else{
-		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
-	 *so the pressure is just the pressure at the z elevation: */
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-	GetParameterListOnVertices(&surface[0],SurfaceEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){
-
-	const int    numdofp=NDOF2*NUMVERTICES;
-	const int    numdofs=NDOF4*NUMVERTICES;
-
-	int    i,dummy;
-	double pattyn_values[numdofp];
-	double stokes_values[numdofs];
-	double vx[NUMVERTICES];
-	double vy[NUMVERTICES];
-	double vz[NUMVERTICES];
-	double vzpattyn[NUMVERTICES];
-	double vzstokes[NUMVERTICES];
-	double vel[NUMVERTICES];
-	double pressure[NUMVERTICES];
-	double xyz_list[NUMVERTICES][3];
-	double stokesreconditioning;
-	int*   doflistp      = NULL;
-	int*   doflists      = NULL;
-	double *vzpattyn_ptr = NULL;
-	Penta  *penta        = NULL;
-
-	/*OK, we have to add results of this element for pattyn 
-	 * and results from the penta at base for macayeal. Now recover results*/
-	penta=GetBasalElement();
-
-	/*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
-	GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
-	GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-
-	/*Get node data: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]];
-	for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]];
-
-	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0];
-		vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1];
-		vzstokes[i]=stokes_values[i*NDOF4+2];
-		pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
-
-		/*Check solution*/
-		if(isnan(vx[i]))       _error_("NaN found in solution vector");
-		if(isnan(vy[i]))       _error_("NaN found in solution vector");
-		if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
-		if(isnan(pressure[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);
-	if (vzpattyn_input){
-		if (vzpattyn_input->Enum()!=PentaVertexInputEnum){
-			_error_("Cannot compute Vel as VzPattyn is of type %s",EnumToStringx(vzpattyn_input->Enum()));
-		}
-		vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i];
-	}
-	else{
-		_error_("Cannot update solution as VzPattyn is not present");
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) {
-		vz[i]=vzpattyn[i]+vzstokes[i];
-		vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-	}
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
-	this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflistp);
-	xfree((void**)&doflists);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){
-	
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int     i,dummy;
-	double  rho_ice,g;
-	double  values[numdof];
-	double  vx[NUMVERTICES];
-	double  vy[NUMVERTICES];
-	double  vz[NUMVERTICES];
-	double  vel[NUMVERTICES];
-	double  pressure[NUMVERTICES];
-	double  surface[NUMVERTICES];
-	double  xyz_list[NUMVERTICES][3];
-	int*    doflist = NULL;
-	double* vz_ptr  = NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Get node data: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector: */
-	for(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(i=0;i<NUMVERTICES;i++){
-		vx[i]=values[i*NDOF2+0];
-		vy[i]=values[i*NDOF2+1];
-
-		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	Input* vz_input=inputs->GetInput(VzEnum);
-	if (vz_input){
-		if (vz_input->Enum()!=PentaVertexInputEnum){
-			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
-		}
-		vz_input->GetValuesPtr(&vz_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
-	}
-	else{
-		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
-	 *so the pressure is just the pressure at the z elevation: */
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-	GetParameterListOnVertices(&surface[0],SurfaceEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){
-
-	const int numdof=NDOF1*NUMVERTICES;
-	
-	int      i,dummy;
-	int      approximation;
-	double   rho_ice,g;
-	double   values[numdof];
-	double   vx[NUMVERTICES];
-	double   vy[NUMVERTICES];
-	double   vz[NUMVERTICES];
-	double   vzmacayeal[NUMVERTICES];
-	double   vzpattyn[NUMVERTICES];
-	double   vzstokes[NUMVERTICES];
-	double   vel[NUMVERTICES];
-	double   pressure[NUMVERTICES];
-	double   surface[NUMVERTICES];
-	double   xyz_list[NUMVERTICES][3];
-	int*     doflist      = NULL;
-	double*  vx_ptr       = NULL;
-	double*  vy_ptr       = NULL;
-	double*  vzstokes_ptr = NULL;
-
-
-	/*Get the approximation and do nothing if the element in Stokes or None*/
-	inputs->GetParameterValue(&approximation,ApproximationEnum);
-	if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
-		return;
-	}
-
-	/*Get dof list and vertices coordinates: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Use the dof list to index into the solution vector vz: */
-	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
-	for(i=0;i<NUMVERTICES;i++){
-		vz[i]=values[i*NDOF1+0];
-
-		/*Check solution*/
-		if(isnan(vz[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vx and Vy*/
-	Input* vx_input=inputs->GetInput(VxEnum);
-	if (vx_input){
-		if (vx_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vx is of type %s",EnumToStringx(vx_input->Enum()));
-		vx_input->GetValuesPtr(&vx_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i];
-	}
-	else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0;
-
-	Input* vy_input=inputs->GetInput(VyEnum);
-	if (vy_input){
-		if (vy_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vy is of type %s",EnumToStringx(vy_input->Enum()));
-		vy_input->GetValuesPtr(&vy_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i];
-	}
-	else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0;
-
-	/*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/
-	if(approximation==PattynStokesApproximationEnum){
-		Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
-		if (vzstokes_input){
-			if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
-			vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
-			for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
-		}
-		else _error_("Cannot compute Vz as VzStokes in not present in PattynStokes element");
-		for(i=0;i<NUMVERTICES;i++){
-			vzpattyn[i]=vz[i];
-			vz[i]=vzpattyn[i]+vzstokes[i];
-		}
-	}
-	else if(approximation==MacAyealStokesApproximationEnum){
-		Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
-		if (vzstokes_input){
-			if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
-			vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
-			for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
-		}
-		else _error_("Cannot compute Vz as VzStokes in not present in MacAyealStokes element");
-		for(i=0;i<NUMVERTICES;i++){
-			vzmacayeal[i]=vz[i];
-			vz[i]=vzmacayeal[i]+vzstokes[i];
-		}
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
-	 *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */
-	if(approximation!=PattynStokesApproximationEnum &&  approximation!=MacAyealStokesApproximationEnum){
-		rho_ice=matpar->GetRhoIce();
-		g=matpar->GetG();
-		GetParameterListOnVertices(&surface[0],SurfaceEnum);
-		for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
-	}
-
-	/*Now, we have to move the previous Vz inputs to old 
-	 * status, otherwise, we'll wipe them off and add the new inputs: */
-	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
-
-	if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){
-		this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-		this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-	}
-	else if(approximation==PattynStokesApproximationEnum){
-		this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn));
-	}
-	else if(approximation==MacAyealStokesApproximationEnum){
-		this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzmacayeal));
-	}
-
-	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/
-void  Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){
-	
-	const int numdof=NDOF4*NUMVERTICES;
-
-	int     i;
-	double  values[numdof];
-	double  vx[NUMVERTICES];
-	double  vy[NUMVERTICES];
-	double  vz[NUMVERTICES];
-	double  vel[NUMVERTICES];
-	double  pressure[NUMVERTICES];
-	double  stokesreconditioning;
-	int*    doflist=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
-
-	/*Ok, we have vx and vy in values, fill in all arrays: */
-	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=values[i*NDOF4+0];
-		vy[i]=values[i*NDOF4+1];
-		vz[i]=values[i*NDOF4+2];
-		pressure[i]=values[i*NDOF4+3];
-
-		/*Check solution*/
-		if(isnan(vx[i]))       _error_("NaN found in solution vector");
-		if(isnan(vy[i]))       _error_("NaN found in solution vector");
-		if(isnan(vz[i]))       _error_("NaN found in solution vector");
-		if(isnan(pressure[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Recondition pressure and compute vel: */
-	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning;
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-	
-	/*Now, we have to move the previous inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
-
-	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
-	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
 }
 /*}}}*/
@@ -7738,2 +2818,4943 @@
 }
 /*}}}*/
+
+#ifdef _HAVE_THERMAL_
+/*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/
+ElementMatrix* Penta::CreateKMatrixEnthalpy(void){
+	
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixEnthalpyVolume();
+	ElementMatrix* Ke2=CreateKMatrixEnthalpyShelf();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+	
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixEnthalpyVolume {{{1*/
+ElementMatrix* Penta::CreateKMatrixEnthalpyVolume(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        stabilization;
+	int        i,j,ig,found=0;
+	double     Jdet,u,v,w,um,vm,wm;
+	double     gravity,rho_ice,rho_water;
+	double     epsvel=2.220446049250313e-16;
+	double     heatcapacity,thermalconductivity,dt;
+	double     pressure,enthalpy;
+	double     latentheat,kappa;
+	double     tau_parameter,diameter;
+	double     xyz_list[NUMVERTICES][3];
+	double     B[3][numdof];
+	double     Bprime[3][numdof];
+	double     B_conduct[3][numdof];
+	double     B_advec[3][numdof];
+	double     B_stab[2][numdof];
+	double     Bprime_advec[3][numdof];
+	double     L[numdof];
+	double     dbasis[3][6];
+	double     D_scalar_conduct,D_scalar_advec;
+	double     D_scalar_trans,D_scalar_stab;
+	double     D[3][3];
+	double     K[2][2]={0.0};
+	Tria*      tria=NULL;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	heatcapacity=matpar->GetHeatCapacity();
+	latentheat=matpar->GetLatentHeat();
+	thermalconductivity=matpar->GetThermalConductivity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
+	Input* pressure_input=inputs->GetInput(PressureEnum);      _assert_(pressure_input);
+	Input* enthalpy_input=inputs->GetInput(EnthalpyEnum);      _assert_(enthalpy_input);
+	Input* vx_input=inputs->GetInput(VxEnum);                  _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);                  _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);                  _assert_(vz_input);
+	Input* vxm_input=inputs->GetInput(VxMeshEnum);             _assert_(vxm_input);
+	Input* vym_input=inputs->GetInput(VyMeshEnum);             _assert_(vym_input);
+	Input* vzm_input=inputs->GetInput(VzMeshEnum);             _assert_(vzm_input);
+	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Conduction: */  
+		/*Need to change that depending on enthalpy value -> cold or temperate ice: */  
+
+		GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss); 
+
+		enthalpy_input->GetParameterValue(&enthalpy, gauss);
+		pressure_input->GetParameterValue(&pressure, gauss);
+		kappa=matpar->GetEnthalpyDiffusionParameter(enthalpy,pressure);
+		D_scalar_conduct=gauss->weight*Jdet*kappa;
+		if(dt) D_scalar_conduct=D_scalar_conduct*dt;
+
+		D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
+		D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
+		D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
+
+		TripleMultiply(&B_conduct[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&B_conduct[0][0],3,numdof,0,
+					&Ke->values[0],1);
+
+		/*Advection: */
+
+		GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss); 
+		GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss); 
+
+		vx_input->GetParameterValue(&u, gauss);
+		vy_input->GetParameterValue(&v, gauss);
+		vz_input->GetParameterValue(&w, gauss);
+		vxm_input->GetParameterValue(&um,gauss);
+		vym_input->GetParameterValue(&vm,gauss);
+		vzm_input->GetParameterValue(&wm,gauss);
+
+		D_scalar_advec=gauss->weight*Jdet;
+		if(dt) D_scalar_advec=D_scalar_advec*dt;
+
+		D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
+		D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
+		D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
+
+		TripleMultiply(&B_advec[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&Bprime_advec[0][0],3,numdof,0,
+					&Ke->values[0],1);
+
+		/*Transient: */
+
+		if(dt){
+			GetNodalFunctionsP1(&L[0], gauss);
+			D_scalar_trans=gauss->weight*Jdet;
+			D_scalar_trans=D_scalar_trans;
+
+			TripleMultiply(&L[0],numdof,1,0,
+						&D_scalar_trans,1,1,0,
+						&L[0],1,numdof,0,
+						&Ke->values[0],1);
+		}
+
+		/*Artifficial diffusivity*/
+
+		if(stabilization==1){
+			/*Build K: */
+			D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
+			if(dt) D_scalar_stab=D_scalar_stab*dt;
+			K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
+			K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
+
+			GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss); 
+
+			TripleMultiply(&B_stab[0][0],2,numdof,1,
+						&K[0][0],2,2,0,
+						&B_stab[0][0],2,numdof,0,
+						&Ke->values[0],1);
+		}
+		else if(stabilization==2){
+
+			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+			tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
+
+			for(i=0;i<numdof;i++){
+				for(j=0;j<numdof;j++){
+					Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
+					  ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
+				}
+			}
+			if(dt){
+				for(i=0;i<numdof;i++){
+					for(j=0;j<numdof;j++){
+						Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
+					}
+				}
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixEnthalpyShelf {{{1*/
+ElementMatrix* Penta::CreateKMatrixEnthalpyShelf(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int       i,j,ig;
+	double    mixed_layer_capacity,thermal_exchange_velocity;
+	double    rho_ice,rho_water,heatcapacity;
+	double    Jdet2d,dt;
+	double    xyz_list[NUMVERTICES][3];
+	double	 xyz_list_tria[NUMVERTICES2D][3];
+	double    basis[NUMVERTICES];
+	double    D_scalar;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if (!IsOnBed() || !IsOnShelf()) return NULL;
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/* Start looping on the number of gauss (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+				
+		D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(rho_ice*heatcapacity);
+		if(dt) D_scalar=dt*D_scalar;
+
+		TripleMultiply(&basis[0],numdof,1,0,
+					&D_scalar,1,1,0,
+					&basis[0],1,numdof,0,
+					&Ke->values[0],1);
+	}
+	
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixMelting {{{1*/
+ElementMatrix* Penta::CreateKMatrixMelting(void){
+
+	if (!IsOnBed()) return NULL;
+
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementMatrix* Ke=tria->CreateKMatrixMelting();
+
+	delete tria->matice; delete tria;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixThermal {{{1*/
+ElementMatrix* Penta::CreateKMatrixThermal(void){
+	
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixThermalVolume();
+	ElementMatrix* Ke2=CreateKMatrixThermalShelf();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+	
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixThermalVolume {{{1*/
+ElementMatrix* Penta::CreateKMatrixThermalVolume(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        stabilization;
+	int        i,j,ig,found=0;
+	double     Jdet,u,v,w,um,vm,wm;
+	double     epsvel=2.220446049250313e-16;
+	double     gravity,rho_ice,rho_water;
+	double     heatcapacity,thermalconductivity,dt;
+	double     tau_parameter,diameter;
+	double     xyz_list[NUMVERTICES][3];
+	double     B[3][numdof];
+	double     Bprime[3][numdof];
+	double     B_conduct[3][numdof];
+	double     B_advec[3][numdof];
+	double     B_stab[2][numdof];
+	double     Bprime_advec[3][numdof];
+	double     L[numdof];
+	double     dbasis[3][6];
+	double     D_scalar_conduct,D_scalar_advec;
+	double     D_scalar_trans,D_scalar_stab;
+	double     D[3][3];
+	double     K[2][2]={0.0};
+	Tria*      tria=NULL;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	heatcapacity=matpar->GetHeatCapacity();
+	thermalconductivity=matpar->GetThermalConductivity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);      _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);      _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);      _assert_(vz_input);
+	Input* vxm_input=inputs->GetInput(VxMeshEnum); _assert_(vxm_input);
+	Input* vym_input=inputs->GetInput(VyMeshEnum); _assert_(vym_input);
+	Input* vzm_input=inputs->GetInput(VzMeshEnum); _assert_(vzm_input);
+	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Conduction: */
+
+		GetBConduct(&B_conduct[0][0],&xyz_list[0][0],gauss); 
+
+		D_scalar_conduct=gauss->weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));
+		if(dt) D_scalar_conduct=D_scalar_conduct*dt;
+
+		D[0][0]=D_scalar_conduct; D[0][1]=0; D[0][2]=0;
+		D[1][0]=0; D[1][1]=D_scalar_conduct; D[1][2]=0;
+		D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar_conduct;
+
+		TripleMultiply(&B_conduct[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&B_conduct[0][0],3,numdof,0,
+					&Ke->values[0],1);
+
+		/*Advection: */
+
+		GetBAdvec(&B_advec[0][0],&xyz_list[0][0],gauss); 
+		GetBprimeAdvec(&Bprime_advec[0][0],&xyz_list[0][0],gauss); 
+
+		vx_input->GetParameterValue(&u, gauss);
+		vy_input->GetParameterValue(&v, gauss);
+		vz_input->GetParameterValue(&w, gauss);
+		vxm_input->GetParameterValue(&um,gauss);
+		vym_input->GetParameterValue(&vm,gauss);
+		vzm_input->GetParameterValue(&wm,gauss);
+
+		D_scalar_advec=gauss->weight*Jdet;
+		if(dt) D_scalar_advec=D_scalar_advec*dt;
+
+		D[0][0]=D_scalar_advec*(u-um);D[0][1]=0;                    D[0][2]=0;
+		D[1][0]=0;                    D[1][1]=D_scalar_advec*(v-vm);D[1][2]=0;
+		D[2][0]=0;                    D[2][1]=0;                    D[2][2]=D_scalar_advec*(w-wm);
+
+		TripleMultiply(&B_advec[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&Bprime_advec[0][0],3,numdof,0,
+					&Ke->values[0],1);
+
+		/*Transient: */
+
+		if(dt){
+			GetNodalFunctionsP1(&L[0], gauss);
+			D_scalar_trans=gauss->weight*Jdet;
+			D_scalar_trans=D_scalar_trans;
+
+			TripleMultiply(&L[0],numdof,1,0,
+						&D_scalar_trans,1,1,0,
+						&L[0],1,numdof,0,
+						&Ke->values[0],1);
+		}
+
+		/*Artifficial diffusivity*/
+
+		if(stabilization==1){
+			/*Build K: */
+			D_scalar_stab=gauss->weight*Jdet/(pow(u-um,2)+pow(v-vm,2)+epsvel);
+			if(dt) D_scalar_stab=D_scalar_stab*dt;
+			K[0][0]=D_scalar_stab*pow(u,2);       K[0][1]=D_scalar_stab*fabs(u)*fabs(v);
+			K[1][0]=D_scalar_stab*fabs(u)*fabs(v);K[1][1]=D_scalar_stab*pow(v,2);
+
+			GetBArtdiff(&B_stab[0][0],&xyz_list[0][0],gauss); 
+
+			TripleMultiply(&B_stab[0][0],2,numdof,1,
+						&K[0][0],2,2,0,
+						&B_stab[0][0],2,numdof,0,
+						&Ke->values[0],1);
+		}
+		else if(stabilization==2){
+
+			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+			tau_parameter=GetStabilizationParameter(u-um,v-vm,w-wm,diameter,rho_ice,heatcapacity,thermalconductivity);
+
+			for(i=0;i<numdof;i++){
+				for(j=0;j<numdof;j++){
+					Ke->values[i*numdof+j]+=tau_parameter*D_scalar_advec*
+					  ((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i])*((u-um)*dbasis[0][j]+(v-vm)*dbasis[1][j]+(w-wm)*dbasis[2][j]);
+				}
+			}
+			if(dt){
+				for(i=0;i<numdof;i++){
+					for(j=0;j<numdof;j++){
+						Ke->values[i*numdof+j]+=tau_parameter*D_scalar_trans*L[j]*((u-um)*dbasis[0][i]+(v-vm)*dbasis[1][i]+(w-wm)*dbasis[2][i]);
+					}
+				}
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixThermalShelf {{{1*/
+ElementMatrix* Penta::CreateKMatrixThermalShelf(void){
+
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int       i,j,ig;
+	double    mixed_layer_capacity,thermal_exchange_velocity;
+	double    rho_ice,rho_water,heatcapacity;
+	double    Jdet2d,dt;
+	double    xyz_list[NUMVERTICES][3];
+	double	 xyz_list_tria[NUMVERTICES2D][3];
+	double    basis[NUMVERTICES];
+	double    D_scalar;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if (!IsOnBed() || !IsOnShelf()) return NULL;
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/* Start looping on the number of gauss (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+				
+		D_scalar=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
+		if(dt) D_scalar=dt*D_scalar;
+
+		TripleMultiply(&basis[0],numdof,1,0,
+					&D_scalar,1,1,0,
+					&basis[0],1,numdof,0,
+					&Ke->values[0],1);
+	}
+	
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorEnthalpy {{{1*/
+ElementVector* Penta::CreatePVectorEnthalpy(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorEnthalpyVolume();
+	ElementVector* pe2=CreatePVectorEnthalpySheet();
+	ElementVector* pe3=CreatePVectorEnthalpyShelf();
+	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	delete pe3;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorEnthalpyVolume {{{1*/
+ElementVector* Penta::CreatePVectorEnthalpyVolume(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries*/
+	int    i,j,ig,found=0;
+	int    friction_type,stabilization;
+	double Jdet,phi,dt;
+	double rho_ice,heatcapacity;
+	double thermalconductivity;
+	double viscosity,temperature;
+	double tau_parameter,diameter;
+	double u,v,w;
+	double scalar_def,scalar_transient;
+	double temperature_list[NUMVERTICES];
+	double xyz_list[NUMVERTICES][3];
+	double L[numdof];
+	double dbasis[3][6];
+	double epsilon[6];
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	thermalconductivity=matpar->GetThermalConductivity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+	Input* temperature_input=NULL;
+	if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
+	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,3);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(&L[0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+		GetPhi(&phi, &epsilon[0], viscosity);
+
+		scalar_def=phi/(rho_ice)*Jdet*gauss->weight;
+		if(dt) scalar_def=scalar_def*dt;
+
+		for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
+
+		/* Build transient now */
+		if(dt){
+			temperature_input->GetParameterValue(&temperature, gauss);
+			scalar_transient=temperature*Jdet*gauss->weight;
+			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
+		}
+
+		if(stabilization==2){
+			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+			vx_input->GetParameterValue(&u, gauss);
+			vy_input->GetParameterValue(&v, gauss);
+			vz_input->GetParameterValue(&w, gauss);
+
+			tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
+
+			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
+			if(dt){
+				for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorEnthalpyShelf {{{1*/
+ElementVector* Penta::CreatePVectorEnthalpyShelf(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     Jdet2d;
+	double     heatcapacity,h_pmp;
+	double     mixed_layer_capacity,thermal_exchange_velocity;
+	double     rho_ice,rho_water,pressure,dt,scalar_ocean;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3];
+	double     basis[NUMVERTICES];
+	GaussPenta* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/* Ice/ocean heat exchange flux on ice shelf base */
+	if (!IsOnBed() || !IsOnShelf()) return NULL;
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		pressure_input->GetParameterValue(&pressure,gauss);
+		h_pmp=matpar->PureIceEnthalpy(pressure);
+
+		scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(h_pmp)/(rho_ice*heatcapacity);
+		if(dt) scalar_ocean=dt*scalar_ocean;
+
+		for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorEnthalpySheet {{{1*/
+ElementVector* Penta::CreatePVectorEnthalpySheet(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        analysis_type;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double     Jdet2d,dt;
+	double     rho_ice,heatcapacity,geothermalflux_value;
+	double     basalfriction,alpha2,vx,vy;
+	double     scalar;
+	double     basis[NUMVERTICES];
+	Friction*  friction=NULL;
+	GaussPenta* gauss=NULL;
+
+	/* Geothermal flux on ice sheet base and basal friction */
+	if (!IsOnBed() || IsOnShelf()) return NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
+	Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
+
+	/*Build frictoin element, needed later: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
+		friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
+		
+		scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(rho_ice);
+		if(dt) scalar=dt*scalar;
+
+		for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorMelting {{{1*/
+ElementVector* Penta::CreatePVectorMelting(void){
+	return NULL;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorThermal {{{1*/
+ElementVector* Penta::CreatePVectorThermal(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorThermalVolume();
+	ElementVector* pe2=CreatePVectorThermalSheet();
+	ElementVector* pe3=CreatePVectorThermalShelf();
+	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	delete pe3;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorThermalVolume {{{1*/
+ElementVector* Penta::CreatePVectorThermalVolume(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries*/
+	int    i,j,ig,found=0;
+	int    friction_type,stabilization;
+	double Jdet,phi,dt;
+	double rho_ice,heatcapacity;
+	double thermalconductivity;
+	double viscosity,temperature;
+	double tau_parameter,diameter;
+	double u,v,w;
+	double scalar_def,scalar_transient;
+	double temperature_list[NUMVERTICES];
+	double xyz_list[NUMVERTICES][3];
+	double L[numdof];
+	double dbasis[3][6];
+	double epsilon[6];
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	thermalconductivity=matpar->GetThermalConductivity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	this->parameters->FindParam(&stabilization,ThermalStabilizationEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+	Input* temperature_input=NULL;
+	if (dt) temperature_input=inputs->GetInput(TemperatureEnum); _assert_(inputs);
+	if (stabilization==2) diameter=MinEdgeLength(xyz_list);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,3);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(&L[0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+		GetPhi(&phi, &epsilon[0], viscosity);
+
+		scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss->weight;
+		if(dt) scalar_def=scalar_def*dt;
+
+		for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_def*L[i];
+
+		/* Build transient now */
+		if(dt){
+			temperature_input->GetParameterValue(&temperature, gauss);
+			scalar_transient=temperature*Jdet*gauss->weight;
+			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=scalar_transient*L[i];
+		}
+
+		if(stabilization==2){
+			GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+			vx_input->GetParameterValue(&u, gauss);
+			vy_input->GetParameterValue(&v, gauss);
+			vz_input->GetParameterValue(&w, gauss);
+
+			tau_parameter=GetStabilizationParameter(u,v,w,diameter,rho_ice,heatcapacity,thermalconductivity);
+
+			for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_def*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
+			if(dt){
+				for(i=0;i<NUMVERTICES;i++)  pe->values[i]+=tau_parameter*scalar_transient*(u*dbasis[0][i]+v*dbasis[1][i]+w*dbasis[2][i]);
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorThermalShelf {{{1*/
+ElementVector* Penta::CreatePVectorThermalShelf(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     Jdet2d;
+	double     mixed_layer_capacity,thermal_exchange_velocity;
+	double     rho_ice,rho_water,pressure,dt,scalar_ocean;
+	double     heatcapacity,t_pmp;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3];
+	double     basis[NUMVERTICES];
+	GaussPenta* gauss=NULL;
+
+	/* Ice/ocean heat exchange flux on ice shelf base */
+	if (!IsOnBed() || !IsOnShelf()) return NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* pressure_input=inputs->GetInput(PressureEnum); _assert_(pressure_input);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		pressure_input->GetParameterValue(&pressure,gauss);
+		t_pmp=matpar->TMeltingPoint(pressure);
+
+		scalar_ocean=gauss->weight*Jdet2d*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
+		if(dt) scalar_ocean=dt*scalar_ocean;
+
+		for(i=0;i<numdof;i++) pe->values[i]+=scalar_ocean*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorThermalSheet {{{1*/
+ElementVector* Penta::CreatePVectorThermalSheet(void){
+
+	/*Constants*/
+	const int  numdof=NUMVERTICES*NDOF1;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        analysis_type;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double     Jdet2d,dt;
+	double     rho_ice,heatcapacity,geothermalflux_value;
+	double     basalfriction,alpha2,vx,vy;
+	double     scalar;
+	double     basis[NUMVERTICES];
+	Friction*  friction=NULL;
+	GaussPenta* gauss=NULL;
+
+	/* Geothermal flux on ice sheet base and basal friction */
+	if (!IsOnBed() || IsOnShelf()) return NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);                         _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);                         _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);                         _assert_(vz_input);
+	Input* geothermalflux_input=inputs->GetInput(BasalforcingsGeothermalfluxEnum); _assert_(geothermalflux_input);
+
+	/*Build frictoin element, needed later: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		geothermalflux_input->GetParameterValue(&geothermalflux_value,gauss);
+		friction->GetAlpha2(&alpha2,gauss,VxEnum,VyEnum,VzEnum);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		basalfriction=alpha2*(pow(vx,2.0)+pow(vy,2.0));
+		
+		scalar=gauss->weight*Jdet2d*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
+		if(dt) scalar=dt*scalar;
+
+		for(i=0;i<numdof;i++) pe->values[i]+=scalar*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/
+void  Penta::GetSolutionFromInputsThermal(Vec solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       values[numdof];
+	double       temp;
+	GaussPenta   *gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	Input* t_input=inputs->GetInput(TemperatureEnum); _assert_(t_input);
+
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+		/*Recover temperature*/
+		gauss->GaussVertex(i);
+		t_input->GetParameterValue(&temp,gauss);
+		values[i]=temp;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsEnthalpy{{{1*/
+void  Penta::GetSolutionFromInputsEnthalpy(Vec solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       values[numdof];
+	double       enthalpy;
+	GaussPenta   *gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	Input* h_input=inputs->GetInput(EnthalpyEnum); _assert_(h_input);
+
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+		/*Recover temperature*/
+		gauss->GaussVertex(i);
+		h_input->GetParameterValue(&enthalpy,gauss);
+		values[i]=enthalpy;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionThermal {{{1*/
+void  Penta::InputUpdateFromSolutionThermal(double* solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	bool   converged;
+	int    i,rheology_law;
+	double xyz_list[NUMVERTICES][3];
+	double values[numdof];
+	double B[numdof];
+	double B_average,s_average;
+	int*   doflist=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+
+		/*Check solution*/
+		if(isnan(values[i])) _error_("NaN found in solution vector");
+		//if(values[i]<0)      printf("temperature < 0°K found in solution vector\n");
+		//if(values[i]>275)    printf("temperature > 275°K found in solution vector (Paterson's rheology associated is negative)\n");
+	}
+
+	/*Get all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+
+	this->inputs->GetParameterValue(&converged,ConvergedEnum);
+	if(converged){
+		this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,values));
+
+		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
+		 * otherwise the rheology could be negative*/
+		this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
+		switch(rheology_law){
+			case NoneEnum:
+				/*Do nothing: B is not temperature dependent*/
+				break;
+			case PatersonEnum:
+				B_average=Paterson((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0);
+				for(i=0;i<numdof;i++) B[i]=B_average;
+				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
+				break;
+			case ArrheniusEnum:
+				surface_input->GetParameterAverage(&s_average);
+				B_average=Arrhenius((values[0]+values[1]+values[2]+values[3]+values[4]+values[5])/6.0,
+							s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
+							matice->GetN());
+				for(i=0;i<numdof;i++) B[i]=B_average;
+				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
+				break;
+			default:
+				_error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
+
+		}
+	}
+	else{
+		this->inputs->AddInput(new PentaVertexInput(TemperaturePicardEnum,values));
+	}
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionEnthalpy {{{1*/
+void  Penta::InputUpdateFromSolutionEnthalpy(double* solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	bool   converged;
+	int    i,rheology_law;
+	double xyz_list[NUMVERTICES][3];
+	double values[numdof];
+	double pressure[NUMVERTICES];
+	double temperatures[numdof];
+	double waterfraction[numdof];
+	double B[numdof];
+	double B_average,s_average;
+	int*   doflist=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+
+		/*Check solution*/
+		if(isnan(values[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetParameterListOnVertices(&pressure[0],PressureEnum);
+	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	
+
+//	this->inputs->GetParameterValue(&converged,ConvergedEnum);
+//	if(converged){
+		/*Convert enthalpy into temperature and water fraction*/
+		for(i=0;i<numdof;i++) matpar->EnthalpyToThermal(&temperatures[i],&waterfraction[i],values[i],pressure[i]);
+			
+		this->inputs->AddInput(new PentaVertexInput(EnthalpyEnum,values));
+		this->inputs->AddInput(new PentaVertexInput(WaterfractionEnum,waterfraction));
+		this->inputs->AddInput(new PentaVertexInput(TemperatureEnum,temperatures));
+
+		/*Update Rheology only if converged (we must make sure that the temperature is below melting point
+		 * otherwise the rheology could be negative*/
+		this->parameters->FindParam(&rheology_law,MaterialsRheologyLawEnum);
+		switch(rheology_law){
+			case NoneEnum:
+				/*Do nothing: B is not temperature dependent*/
+				break;
+			case PatersonEnum:
+				B_average=Paterson((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0);
+				for(i=0;i<numdof;i++) B[i]=B_average;
+				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
+				break;
+			case ArrheniusEnum:
+				surface_input->GetParameterAverage(&s_average);
+				B_average=Arrhenius((temperatures[0]+temperatures[1]+temperatures[2]+temperatures[3]+temperatures[4]+temperatures[5])/6.0,
+							s_average-((xyz_list[0][2]+xyz_list[1][2]+xyz_list[2][2]+xyz_list[3][2]+xyz_list[4][2]+xyz_list[5][2])/6.0),
+							matice->GetN());
+				for(i=0;i<numdof;i++) B[i]=B_average;
+				this->matice->inputs->AddInput(new PentaVertexInput(MaterialsRheologyBEnum,B));
+				break;
+			default:
+				_error_("Rheology law %s not supported yet",EnumToStringx(rheology_law));
+
+		}
+//	}
+//	else{
+//		this->inputs->AddInput(new PentaVertexInput(EnthalpyPicardEnum,values));
+//	}
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+#endif
+
+#ifdef _HAVE_CONTROL_
+/*FUNCTION Penta::ControlInputGetGradient{{{1*/
+void Penta::ControlInputGetGradient(Vec gradient,int enum_type){
+
+	int doflist1[NUMVERTICES];
+	Input* input=NULL;
+
+	if(enum_type==MaterialsRheologyBbarEnum){
+		if(!IsOnBed()) return;
+		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
+	}
+	else{
+		input=inputs->GetInput(enum_type);
+	}
+	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
+	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
+
+	this->GetDofList1(&doflist1[0]);
+	((ControlInput*)input)->GetGradient(gradient,&doflist1[0]);
+
+}/*}}}*/
+/*FUNCTION Penta::ControlInputScaleGradient{{{1*/
+void Penta::ControlInputScaleGradient(int enum_type,double scale){
+
+	Input* input=NULL;
+
+	if(enum_type==MaterialsRheologyBbarEnum){
+		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
+	}
+	else{
+		input=inputs->GetInput(enum_type);
+	}
+	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
+	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
+
+	((ControlInput*)input)->ScaleGradient(scale);
+}/*}}}*/
+/*FUNCTION Penta::ControlInputSetGradient{{{1*/
+void Penta::ControlInputSetGradient(double* gradient,int enum_type){
+
+	int    doflist1[NUMVERTICES];
+	double grad_list[NUMVERTICES];
+	Input* grad_input=NULL;
+	Input* input=NULL;
+
+	if(enum_type==MaterialsRheologyBbarEnum){
+		input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum);
+	}
+	else{
+		input=inputs->GetInput(enum_type);
+	}
+	if (!input) _error_("Input %s not found",EnumToStringx(enum_type));
+	if (input->Enum()!=ControlInputEnum) _error_("Input %s is not a ControlInput",EnumToStringx(enum_type));
+
+	this->GetDofList1(&doflist1[0]);
+	for(int i=0;i<NUMVERTICES;i++) grad_list[i]=gradient[doflist1[i]];
+	grad_input=new PentaVertexInput(GradientEnum,grad_list);
+	((ControlInput*)input)->SetGradient(grad_input);
+
+}/*}}}*/
+/*FUNCTION Penta::CreatePVectorAdjointHoriz{{{1*/
+ElementVector* Penta::CreatePVectorAdjointHoriz(void){
+
+	int approximation;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	switch(approximation){
+		case MacAyealApproximationEnum:
+			return CreatePVectorAdjointMacAyeal();
+		case PattynApproximationEnum:
+			return CreatePVectorAdjointPattyn();
+		case NoneApproximationEnum:
+			return NULL;
+		case StokesApproximationEnum:
+			return CreatePVectorAdjointStokes();
+		default:
+			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorAdjointMacAyeal{{{1*/
+ElementVector* Penta::CreatePVectorAdjointMacAyeal(){
+
+	if (!IsOnBed()) return NULL;
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementVector* pe=tria->CreatePVectorAdjointHoriz();
+	delete tria->matice; delete tria;
+
+	/*clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorAdjointPattyn{{{1*/
+ElementVector* Penta::CreatePVectorAdjointPattyn(void){
+
+	if (!IsOnSurface()) return NULL;
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+	ElementVector* pe=tria->CreatePVectorAdjointHoriz();
+	delete tria->matice; delete tria;
+
+	/*clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorAdjointStokes{{{1*/
+ElementVector* Penta::CreatePVectorAdjointStokes(void){
+
+	if (!IsOnSurface()) return NULL;
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+	ElementVector* pe=tria->CreatePVectorAdjointStokes();
+	delete tria->matice; delete tria;
+
+	/*clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::Gradj {{{1*/
+void  Penta::Gradj(Vec gradient,int control_type){
+	/*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
+
+	int              i,approximation;
+	Tria*            tria=NULL;
+
+	/*If on water, skip grad (=0): */
+	if(IsOnWater())return;
+
+	/*First deal with ∂/∂alpha(KU-F)*/
+	switch(control_type){
+
+		case FrictionCoefficientEnum:
+			inputs->GetParameterValue(&approximation,ApproximationEnum);
+			switch(approximation){
+				case MacAyealApproximationEnum:
+					GradjDragMacAyeal(gradient);
+					break;
+				case PattynApproximationEnum:
+					GradjDragPattyn(gradient);
+					break;
+				case StokesApproximationEnum:
+					GradjDragStokes(gradient);
+					break;
+				case NoneApproximationEnum:
+					/*Gradient is 0*/
+					break;
+				default:
+					_error_("approximation %s not supported yet",EnumToStringx(approximation));
+			}
+			break;
+
+		case MaterialsRheologyBbarEnum:
+			inputs->GetParameterValue(&approximation,ApproximationEnum);
+			switch(approximation){
+				case MacAyealApproximationEnum:
+					GradjBbarMacAyeal(gradient);
+					break;
+				case PattynApproximationEnum:
+					GradjBbarPattyn(gradient);
+					break;
+				case StokesApproximationEnum:
+					GradjBbarStokes(gradient);
+					break;
+				case NoneApproximationEnum:
+					/*Gradient is 0*/
+					break;
+				default:
+					_error_("approximation %s not supported yet",EnumToStringx(approximation));
+			}
+			break;
+
+		default:
+			_error_("control type %s not supported yet: ",EnumToStringx(control_type));
+	}
+
+	/*Now deal with ∂J/∂alpha*/
+	int        *responses = NULL;
+	int         num_responses,resp;
+	this->parameters->FindParam(&num_responses,InversionNumCostFunctionsEnum);
+	this->parameters->FindParam(&responses,NULL,NULL,StepResponsesEnum);
+
+	for(resp=0;resp<num_responses;resp++) switch(responses[resp]){
+
+		case ThicknessAbsMisfitEnum:
+		case SurfaceAbsVelMisfitEnum:
+		case SurfaceRelVelMisfitEnum:
+		case SurfaceLogVelMisfitEnum:
+		case SurfaceLogVxVyMisfitEnum:
+		case SurfaceAverageVelMisfitEnum:
+			/*Nothing, J does not depends on the parameter being inverted for*/
+			break;
+		case DragCoefficientAbsGradientEnum:
+			if (!IsOnBed()) return;
+			tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+			tria->GradjDragGradient(gradient,resp);
+			delete tria->matice; delete tria;
+			break;
+		case RheologyBbarAbsGradientEnum:
+			if (!IsOnBed()) return;
+			tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+			tria->GradjBGradient(gradient,resp);
+			delete tria->matice; delete tria;
+			break;
+		default:
+			_error_("response %s not supported yet",EnumToStringx(responses[resp]));
+	}
+	xfree((void**)&responses);
+}
+/*}}}*/
+/*FUNCTION Penta::GradjDragMacAyeal {{{1*/
+void  Penta::GradjDragMacAyeal(Vec gradient){
+
+	/*Gradient is 0 if on shelf or not on bed*/
+	if(IsOnShelf() || !IsOnBed()) return;
+
+	/*Spawn tria*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	tria->GradjDragMacAyeal(gradient);
+	delete tria->matice; delete tria;
+
+} /*}}}*/
+/*FUNCTION Penta::GradjDragPattyn {{{1*/
+void  Penta::GradjDragPattyn(Vec gradient){
+
+	int        i,j,ig;
+	int        analysis_type;
+	int        doflist1[NUMVERTICES];
+	double     vx,vy,lambda,mu,alpha_complement,Jdet;
+	double     bed,thickness,Neff,drag;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double     dk[NDOF3]; 
+	double     grade_g[NUMVERTICES]={0.0};
+	double     grade_g_gaussian[NUMVERTICES];
+	double     basis[6];
+	Friction*  friction=NULL;
+	GaussPenta  *gauss=NULL;
+
+	/*Gradient is 0 if on shelf or not on bed*/
+	if(IsOnShelf() || !IsOnBed()) return;
+
+	/*Retrieve all inputs and parameters*/
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	GetDofList1(&doflist1[0]);
+	Input* adjointx_input=inputs->GetInput(AdjointxEnum);               _assert_(adjointx_input);
+	Input* adjointy_input=inputs->GetInput(AdjointyEnum);               _assert_(adjointy_input);
+	Input* vx_input=inputs->GetInput(VxEnum);                           _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);                           _assert_(vy_input);
+	Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
+
+	/*Build frictoin element, needed later: */
+	friction=new Friction("2d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		/*Build alpha_complement_list: */
+		friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
+
+		dragcoefficient_input->GetParameterValue(&drag, gauss);
+		adjointx_input->GetParameterValue(&lambda, gauss);
+		adjointy_input->GetParameterValue(&mu, gauss);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		dragcoefficient_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		for (i=0;i<NUMVERTICES;i++){
+			grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss->weight*basis[i]; /*basis are 0 for the 3 upper nodes*/
+		}
+
+		/*Add gradje_g_gaussian vector to gradje_g: */
+		for(i=0;i<NUMVERTICES;i++){
+			_assert_(!isnan(grade_g[i]));
+			grade_g[i]+=grade_g_gaussian[i];
+		}
+	}
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+}
+/*}}}*/
+/*FUNCTION Penta::GradjDragStokes {{{1*/
+void  Penta::GradjDragStokes(Vec gradient){
+
+	int        i,j,ig;
+	int        analysis_type;
+	int        doflist1[NUMVERTICES];
+	double     bed,thickness,Neff;
+	double     lambda,mu,xi,Jdet,vx,vy,vz;
+	double     alpha_complement,drag;
+	double     surface_normal[3],bed_normal[3];
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double     dk[NDOF3]; 
+	double     basis[6];
+	double     grade_g[NUMVERTICES]={0.0};
+	double     grade_g_gaussian[NUMVERTICES];
+	Friction*  friction=NULL;
+	GaussPenta* gauss=NULL;
+
+	/*Gradient is 0 if on shelf or not on bed*/
+	if(IsOnShelf() || !IsOnBed()) return;
+
+	/*Retrieve all inputs and parameters*/
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	GetDofList1(&doflist1[0]);
+	Input* drag_input    =inputs->GetInput(FrictionCoefficientEnum); _assert_(drag_input);
+	Input* vx_input      =inputs->GetInput(VxEnum);              _assert_(vx_input);
+	Input* vy_input      =inputs->GetInput(VyEnum);              _assert_(vy_input);
+	Input* vz_input      =inputs->GetInput(VzEnum);              _assert_(vz_input);
+	Input* adjointx_input=inputs->GetInput(AdjointxEnum);        _assert_(adjointx_input);
+	Input* adjointy_input=inputs->GetInput(AdjointyEnum);        _assert_(adjointy_input);
+	Input* adjointz_input=inputs->GetInput(AdjointzEnum);        _assert_(adjointz_input);
+
+	/*Build frictoin element, needed later: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,4);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/*Recover alpha_complement and drag: */
+		friction->GetAlphaComplement(&alpha_complement, gauss,VxEnum,VyEnum,VzEnum);
+		drag_input->GetParameterValue(&drag,gauss);
+
+		/*recover lambda mu and xi: */
+		adjointx_input->GetParameterValue(&lambda,gauss);
+		adjointy_input->GetParameterValue(&mu    ,gauss);
+		adjointz_input->GetParameterValue(&xi    ,gauss);
+
+		/*recover vx vy and vz: */
+		vx_input->GetParameterValue(&vx, gauss);
+		vy_input->GetParameterValue(&vy, gauss);
+		vz_input->GetParameterValue(&vz, gauss);
+
+		/*Get normal vector to the bed */
+		SurfaceNormal(&surface_normal[0],xyz_list_tria);
+
+		bed_normal[0]=-surface_normal[0]; //Function is for upper surface, so the normal to the bed is the opposite of the result
+		bed_normal[1]=-surface_normal[1];
+		bed_normal[2]=-surface_normal[2];
+
+		/* Get Jacobian determinant: */
+		GetTriaJacobianDeterminant(&Jdet,&xyz_list_tria[0][0],gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		/*Get k derivative: dk/dx */
+		drag_input->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],gauss);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		for (i=0;i<NUMVERTICES;i++){
+			//standard gradient dJ/dki
+			grade_g_gaussian[i]=(
+						-lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
+						-mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
+						-xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
+						)*Jdet*gauss->weight*basis[i]; 
+		}
+
+		/*Add gradje_g_gaussian vector to gradje_g: */
+		for( i=0; i<NUMVERTICES; i++)grade_g[i]+=grade_g_gaussian[i];
+	}
+
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	delete friction;
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Penta::GradjBbarMacAyeal {{{1*/
+void  Penta::GradjBbarMacAyeal(Vec gradient){
+
+	/*This element should be collapsed into a tria element at its base*/
+	if (!IsOnBed()) return; 
+
+	/*Depth Average B*/
+	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
+
+	/*Collapse element to the base*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+	tria->GradjBMacAyeal(gradient);
+	delete tria->matice; delete tria;
+
+	/*delete Average B*/
+	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
+
+} /*}}}*/
+/*FUNCTION Penta::GradjBbarPattyn {{{1*/
+void  Penta::GradjBbarPattyn(Vec gradient){
+
+	/*Gradient is computed on bed only (Bbar)*/
+	if (!IsOnBed()) return;
+
+	/*Depth Average B*/
+	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
+
+	/*Collapse element to the base*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2);
+	tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
+	delete tria->matice; delete tria;
+
+	/*delete Average B*/
+	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
+} /*}}}*/
+/*FUNCTION Penta::GradjBbarStokes {{{1*/
+void  Penta::GradjBbarStokes(Vec gradient){
+
+	/*Gradient is computed on bed only (Bbar)*/
+	if (!IsOnBed()) return;
+
+	/*Depth Average B*/
+	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
+
+	/*Collapse element to the base*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2);
+	tria->GradjBMacAyeal(gradient);    //We use MacAyeal as an estimate for now
+	delete tria->matice; delete tria;
+
+	/*delete Average B*/
+	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
+} /*}}}*/
+/*FUNCTION Penta::InputControlUpdate{{{1*/
+void  Penta::InputControlUpdate(double scalar,bool save_parameter){
+
+	/*Intermediary*/
+	int    num_controls;
+	int*   control_type=NULL;
+	Input* input=NULL;
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&num_controls,InversionNumControlParametersEnum);
+	this->parameters->FindParam(&control_type,NULL,InversionControlParametersEnum);
+
+	for(int i=0;i<num_controls;i++){
+
+		if(control_type[i]==MaterialsRheologyBbarEnum){
+			if (!IsOnBed()) goto cleanup_and_return;
+			input=(Input*)matice->inputs->GetInput(MaterialsRheologyBEnum); _assert_(input);
+		}
+		else{
+			input=(Input*)this->inputs->GetInput(control_type[i]); _assert_(input);
+		}
+
+		if (input->Enum()!=ControlInputEnum) _error_("input %s is not a ControlInput",EnumToStringx(control_type[i]));
+
+		((ControlInput*)input)->UpdateValue(scalar);
+		((ControlInput*)input)->Constrain();
+		if (save_parameter) ((ControlInput*)input)->SaveValue();
+
+		if(control_type[i]==MaterialsRheologyBbarEnum){
+			this->InputExtrude(MaterialsRheologyBEnum,MaterialsEnum);
+		}
+	}
+
+	/*Clean up and return*/
+cleanup_and_return:
+	xfree((void**)&control_type);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionAdjointStokes {{{1*/
+void  Penta::InputUpdateFromSolutionAdjointStokes(double* solution){
+
+	const int    numdof=NDOF4*NUMVERTICES;
+
+	int    i;
+	double values[numdof];
+	double lambdax[NUMVERTICES];
+	double lambday[NUMVERTICES];
+	double lambdaz[NUMVERTICES];
+	double lambdap[NUMVERTICES];
+	int*   doflist=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
+		lambdax[i]=values[i*NDOF4+0];
+		lambday[i]=values[i*NDOF4+1];
+		lambdaz[i]=values[i*NDOF4+2];
+		lambdap[i]=values[i*NDOF4+3];
+
+		/*Check solution*/
+		if(isnan(lambdax[i])) _error_("NaN found in solution vector");
+		if(isnan(lambday[i])) _error_("NaN found in solution vector");
+		if(isnan(lambdaz[i])) _error_("NaN found in solution vector");
+		if(isnan(lambdap[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
+	this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
+	this->inputs->AddInput(new PentaVertexInput(AdjointzEnum,lambdaz));
+	this->inputs->AddInput(new PentaVertexInput(AdjointpEnum,lambdap));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionAdjointHoriz {{{1*/
+void  Penta::InputUpdateFromSolutionAdjointHoriz(double* solution){
+
+	const int numdof=NDOF2*NUMVERTICES;
+
+	int    i;
+	double values[numdof];
+	double lambdax[NUMVERTICES];
+	double lambday[NUMVERTICES];
+	int*   doflist=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
+		lambdax[i]=values[i*NDOF2+0];
+		lambday[i]=values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(lambdax[i]))       _error_("NaN found in solution vector");
+		if(isnan(lambday[i]))       _error_("NaN found in solution vector");
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(AdjointxEnum,lambdax));
+	this->inputs->AddInput(new PentaVertexInput(AdjointyEnum,lambday));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::SurfaceAverageVelMisfit {{{1*/
+double Penta::SurfaceAverageVelMisfit(bool process_units,int weight_index){
+
+	int    approximation;
+	double J;
+	Tria*  tria=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Bail out if this element if:
+	 * -> Non MacAyeal and not on the surface
+	 * -> MacAyeal (2d model) and not on bed) */
+	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
+		return 0;
+	}
+	else if (approximation==MacAyealApproximationEnum){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceAverageVelMisfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+		J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+		J=tria->SurfaceAverageVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::SurfaceAbsVelMisfit {{{1*/
+double Penta::SurfaceAbsVelMisfit(bool process_units,int weight_index){
+
+	int    approximation;
+	double J;
+	Tria*  tria=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Bail out if this element if:
+	 * -> Non MacAyeal and not on the surface
+	 * -> MacAyeal (2d model) and not on bed) */
+	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
+		return 0;
+	}
+	else if (approximation==MacAyealApproximationEnum){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceAbsVelMisfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+		J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+		J=tria->SurfaceAbsVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::SurfaceLogVelMisfit {{{1*/
+double Penta::SurfaceLogVelMisfit(bool process_units,int weight_index){
+
+	int    approximation;
+	double J;
+	Tria*  tria=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Bail out if this element if:
+	 * -> Non MacAyeal and not on the surface
+	 * -> MacAyeal (2d model) and not on bed) */
+	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
+		return 0;
+	}
+	else if (approximation==MacAyealApproximationEnum){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceLogVelMisfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+		J=tria->SurfaceLogVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+		J=tria->SurfaceLogVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::SurfaceLogVxVyMisfit {{{1*/
+double Penta::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
+
+	double J;
+	Tria* tria=NULL;
+
+	/*inputs: */
+	int  approximation;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Bail out if this element if:
+	 * -> Non MacAyeal and not on the surface
+	 * -> MacAyeal (2d model) and not on bed) */
+	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
+		return 0;
+	}
+	else if (approximation==MacAyealApproximationEnum){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceLogVxVyMisfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+		J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+		J=tria->SurfaceLogVxVyMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::SurfaceRelVelMisfit {{{1*/
+double Penta::SurfaceRelVelMisfit(bool process_units,int weight_index){
+
+	int    approximation;
+	double J;
+	Tria*  tria=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Bail out if this element if:
+	 * -> Non MacAyeal and not on the surface
+	 * -> MacAyeal (2d model) and not on bed) */
+	if ((approximation!=MacAyealApproximationEnum && !IsOnSurface()) || (approximation==MacAyealApproximationEnum && !IsOnBed())){
+		return 0;
+	}
+	else if (approximation==MacAyealApproximationEnum){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceRelVelMisfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria (lower face).
+		J=tria->SurfaceRelVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3, 4 and 5 make the new tria (upper face).
+		J=tria->SurfaceRelVelMisfit(process_units,weight_index);
+		delete tria->matice; delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::ThicknessAbsGradient{{{1*/
+double Penta::ThicknessAbsGradient(bool process_units,int weight_index){
+
+	_error_("Not implemented yet");
+}
+/*}}}*/
+/*FUNCTION Penta::ThicknessAbsMisfit {{{1*/
+double Penta::ThicknessAbsMisfit(bool process_units,int weight_index){
+
+	int    approximation;
+	double J;
+	Tria*  tria=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+	_error_("Not implemented yet");
+
+	tria=(Tria*)SpawnTria(0,1,2);
+	J=tria->ThicknessAbsMisfit(process_units,weight_index);
+	delete tria->matice; delete tria;
+	return J;
+}
+/*}}}*/
+/*FUNCTION Penta::DragCoefficientAbsGradient{{{1*/
+double Penta::DragCoefficientAbsGradient(bool process_units,int weight_index){
+
+	double J;
+	Tria*  tria=NULL;
+
+	/*If on water, on shelf or not on bed, skip: */
+	if(IsOnWater()|| IsOnShelf() || !IsOnBed()) return 0;
+
+	tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
+	J=tria->DragCoefficientAbsGradient(process_units,weight_index);
+	delete tria->matice; delete tria;
+	return J;
+}
+/*}}}*/
+/*FUNCTION Penta::RheologyBbarAbsGradient{{{1*/
+double Penta::RheologyBbarAbsGradient(bool process_units,int weight_index){
+
+	double J;
+	Tria*  tria=NULL;
+
+	/*If on water, on shelf or not on bed, skip: */
+	if(IsOnWater() || !IsOnBed()) return 0;
+
+	tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria
+	J=tria->RheologyBbarAbsGradient(process_units,weight_index);
+	delete tria->matice; delete tria;
+	return J;
+}
+/*}}}*/
+
+#endif
+
+#ifdef _HAVE_DAKOTA_
+/*FUNCTION Penta::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/
+void  Penta::InputUpdateFromVectorDakota(double* vector, int name, int type){
+	
+	int i,j;
+
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+
+	switch(type){
+
+		case VertexEnum:
+
+			/*New PentaVertexInput*/
+			double values[6];
+
+			/*Get values on the 6 vertices*/
+			for (i=0;i<6;i++){
+				values[i]=vector[this->nodes[i]->GetSidList()]; //careful, vector of values here is not parallel distributed, but serial distributed (from a serial Dakota core!)
+			}
+
+			/*Branch on the specified type of update: */
+			switch(name){
+				case ThicknessEnum:
+					/*Update thickness + surface: assume bed is constant. On ice shelves, takes hydrostatic equilibrium {{{2*/
+					double  thickness[6];
+					double  thickness_init[6];
+					double  hydrostatic_ratio[6];
+					double  surface[6];
+					double  bed[6];
+					
+					/*retrieve inputs: */
+					GetParameterListOnVertices(&thickness_init[0],ThicknessEnum);
+					GetParameterListOnVertices(&hydrostatic_ratio[0],GeometryHydrostaticRatioEnum);
+					GetParameterListOnVertices(&bed[0],BedEnum);
+					GetParameterListOnVertices(&surface[0],SurfaceEnum);
+
+					/*build new thickness: */
+//					for(j=0;j<6;j++)thickness[j]=values[j];
+
+					/*build new bed and surface: */
+					if (this->IsOnShelf()){
+						/*hydrostatic equilibrium: */
+						double rho_ice,rho_water,di;
+						rho_ice=this->matpar->GetRhoIce();
+						rho_water=this->matpar->GetRhoWater();
+
+						di=rho_ice/rho_water;
+
+						/*build new thickness: */
+						for (j=0; j<6; j++) {
+						/*  for observed/interpolated/hydrostatic thickness, remove scaling from any hydrostatic thickness  */
+							if     (hydrostatic_ratio[j] >= 0.)
+								thickness[j]=values[j]-(values[j]/thickness_init[j]-1.)*hydrostatic_ratio[j]*surface[j]/(1.-di);
+						/*  for minimum thickness, don't scale  */
+							else
+								thickness[j]=thickness_init[j];
+
+						/*  check the computed thickness and update bed  */
+							if (thickness[j] < 0.)
+								thickness[j]=1./(1.-di);
+							bed[j]=surface[j]-thickness[j];
+						}
+
+//						for(j=0;j<6;j++){
+//							surface[j]=(1-di)*thickness[j];
+//							bed[j]=-di*thickness[j];
+//						}
+					}
+					else{
+						/*build new thickness: */
+						for (j=0; j<6; j++) {
+						/*  for observed thickness, use scaled value  */
+							if(hydrostatic_ratio[j] >= 0.)
+								thickness[j]=values[j];
+						/*  for minimum thickness, don't scale  */
+							else
+								thickness[j]=thickness_init[j];
+						}
+
+						/*update bed on grounded ice: */
+//						for(j=0;j<6;j++)surface[j]=bed[j]+thickness[j];
+						for(j=0;j<6;j++)bed[j]=surface[j]-thickness[j];
+					}
+
+					/*Add new inputs: */
+					this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,thickness));
+					this->inputs->AddInput(new PentaVertexInput(BedEnum,bed));
+					this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,surface));
+
+					/*}}}*/
+					break;
+				default:
+					this->inputs->AddInput(new PentaVertexInput(name,values));
+			}
+			break;
+
+		default:
+			_error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
+	}
+
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromVectorDakota(int* vector, int name, int type);{{{1*/
+void  Penta::InputUpdateFromVectorDakota(int* vector, int name, int type){
+	_error_(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type);{{{1*/
+void  Penta::InputUpdateFromVectorDakota(bool* vector, int name, int type){
+	_error_(" not supported yet!");
+}
+/*}}}*/
+#endif
+
+#ifdef _HAVE_DIAGNOSTIC_
+/*FUNCTION Penta::CreateDVectorDiagnosticHoriz {{{1*/
+ElementVector* Penta::CreateDVectorDiagnosticHoriz(void){
+
+	int approximation;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	switch(approximation){
+		case StokesApproximationEnum:
+			return CreateDVectorDiagnosticStokes();
+		default:
+			return NULL; //no need for doftypes outside of stokes approximation
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::CreateDVectorDiagnosticStokes{{{1*/
+ElementVector* Penta::CreateDVectorDiagnosticStokes(void){
+
+	/*output: */
+	ElementVector* De=NULL;
+	/*intermediary: */
+	int approximation;
+	int i;
+
+	/*Initialize Element vector and return if necessary*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=StokesApproximationEnum) return NULL;
+
+	De=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	for (i=0;i<NUMVERTICES;i++){
+		De->values[i*4+0]=VelocityEnum;
+		De->values[i*4+1]=VelocityEnum;
+		De->values[i*4+2]=VelocityEnum;
+		De->values[i*4+3]=PressureEnum;
+	}
+
+	return De;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattyn{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattyn(void){
+	
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealPattynViscous();
+	ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealPattynFriction();
+	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
+	
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynViscous{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynViscous(void){
+
+	/*Constants*/
+	const int    numdofm=NDOF2*NUMVERTICES2D;
+	const int    numdofp=NDOF2*NUMVERTICES;
+	const int    numdoftotal=2*NDOF2*NUMVERTICES;
+
+	/*Intermediaries */
+	int         i,j,ig;
+	double      Jdet;
+	double      viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
+	double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	double      xyz_list[NUMVERTICES][3];
+	double      B[3][numdofp];
+	double      Bprime[3][numdofm];
+	double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
+	double      D_scalar;
+	double      Ke_gg[numdofp][numdofm]={0.0}; //local element stiffness matrix 
+	double      Ke_gg_gaussian[numdofp][numdofm]; //stiffness matrix evaluated at the gaussian point.
+	GaussPenta *gauss=NULL;
+	GaussTria  *gauss_tria=NULL;
+
+	/*Find penta on bed as pattyn must be coupled to the dofs on the bed: */
+	Penta* pentabase=GetBasalElement();
+	Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+	ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,PattynApproximationEnum);
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+	delete Ke1; delete Ke2;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
+	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	gauss_tria=new GaussTria();
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		gauss->SynchronizeGaussTria(gauss_tria);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBMacAyealPattyn(&B[0][0], &xyz_list[0][0], gauss);
+		tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
+
+		this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
+		this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
+		matice->GetViscosity3d(&viscosity, &epsilon[0]);
+		matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
+
+		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+		D_scalar=2*newviscosity*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],3,numdofp,1,
+					&D[0][0],3,3,0,
+					&Bprime[0][0],3,numdofm,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		for( i=0; i<numdofp; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+	} 
+	for(i=0;i<numdofp;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
+	for(i=0;i<numdofm;i++) for(j=0;j<numdofp;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg[j][i];
+
+	/*Clean-up and return*/
+	delete tria->matice; delete tria;
+	delete gauss;
+	delete gauss_tria;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealPattynFriction{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealPattynFriction(void){
+
+	/*Constants*/
+	const int numdof        = NDOF2 *NUMVERTICES;
+	const int numdoftotal   = NDOF4 *NUMVERTICES;
+	
+	/*Intermediaries */
+	int       i,j,ig,analysis_type;
+	double    Jdet2d,slope_magnitude,alpha2;
+	double    xyz_list[NUMVERTICES][3];
+	double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double    slope[3]={0.0,0.0,0.0};
+	double    MAXSLOPE=.06; // 6 %
+	double    MOUNTAINKEXPONENT=10;
+	double    L[2][numdof];
+	double    DL[2][2]                  ={{ 0,0 },{0,0}}; //for basal drag
+	double    DL_scalar;
+	double    Ke_gg[numdof][numdof]     ={0.0};
+	double    Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
+	Friction  *friction = NULL;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if(IsOnShelf() || !IsOnBed()) return NULL;
+	ElementMatrix* Ke1=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+	ElementMatrix* Ke2=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
+	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
+	delete Ke1; delete Ke2;
+
+	/*retrieve inputs :*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
+
+	/*build friction object, used later on: */
+	friction=new Friction("2d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/*Friction: */
+		friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
+
+		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
+		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
+		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
+
+		if (slope_magnitude>MAXSLOPE){
+			alpha2=pow((double)10,MOUNTAINKEXPONENT);
+		}
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
+		GetL(&L[0][0], gauss,NDOF2);
+
+		DL_scalar=alpha2*gauss->weight*Jdet2d;
+		for (i=0;i<2;i++) DL[i][i]=DL_scalar; 
+		
+		/*  Do the triple producte tL*D*L: */
+		TripleMultiply( &L[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&L[0][0],2,numdof,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+	}
+
+	for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[i*numdoftotal+(numdof+j)]+=Ke_gg[i][j];
+	for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke->values[(i+numdof)*numdoftotal+j]+=Ke_gg[i][j];
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokes{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokes(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixCouplingMacAyealStokesViscous();
+	ElementMatrix* Ke2=CreateKMatrixCouplingMacAyealStokesFriction();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesViscous{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesViscous(void){
+
+	/*Constants*/
+	const int    numdofm=NDOF2*NUMVERTICES2D;
+	const int    numdofs=NDOF4*NUMVERTICES;
+	const int    numdoftotal=2*numdofm+numdofs;
+
+	/*Intermediaries */
+	int         i,j,ig;
+	double      Jdet;
+	double      viscosity,stokesreconditioning; //viscosity
+	double      epsilon[6]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	double      xyz_list[NUMVERTICES][3];
+	double      B[4][numdofs+3];
+	double      Bprime[4][numdofm];
+	double      B2[3][numdofm];
+	double      Bprime2[3][numdofs+3];
+	double      D[4][4]={0.0};            // material matrix, simple scalar matrix.
+	double      D2[3][3]={0.0};            // material matrix, simple scalar matrix.
+	double      D_scalar;
+	double      Ke_gg[numdofs][numdofm]={0.0}; //local element stiffness matrix 
+	double      Ke_gg2[numdofm][numdofs]={0.0}; //local element stiffness matrix 
+	double      Ke_gg_gaussian[numdofs+3][numdofm]; //stiffness matrix evaluated at the gaussian point.
+	double      Ke_gg_gaussian2[numdofm][numdofs+3]; //stiffness matrix evaluated at the gaussian point.
+	GaussPenta *gauss=NULL;
+	GaussTria  *gauss_tria=NULL;
+
+	/*Find penta on bed as stokes must be coupled to the dofs on the bed: */
+	Penta* pentabase=GetBasalElement();
+	Tria* tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+
+	/*Initialize Element matrix and return if necessary*/
+	ElementMatrix* Ke1=new ElementMatrix(pentabase->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+	ElementMatrix* Ke2=new ElementMatrix(this->nodes     ,NUMVERTICES,this->parameters,StokesApproximationEnum);
+	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
+	delete Ke1; delete Ke2;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	gauss_tria=new GaussTria();
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		gauss->SynchronizeGaussTria(gauss_tria);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBMacAyealStokes(&B[0][0], &xyz_list[0][0], gauss);
+		tria->GetBprimeMacAyealStokes(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
+		tria->GetBMacAyealStokes(&B2[0][0], &xyz_list[0][0], gauss_tria);
+		GetBprimeMacAyealStokes(&Bprime2[0][0], &xyz_list[0][0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity, &epsilon[0]);
+
+		D_scalar=2*viscosity*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+		D[3][3]=-gauss->weight*Jdet*stokesreconditioning;
+		for (i=0;i<3;i++) D2[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],4,numdofs+3,1,
+					&D[0][0],4,4,0,
+					&Bprime[0][0],4,numdofm,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		TripleMultiply( &B2[0][0],3,numdofm,1,
+					&D2[0][0],3,3,0,
+					&Bprime2[0][0],3,numdofs+3,0,
+					&Ke_gg_gaussian2[0][0],0);
+
+		for( i=0; i<numdofs; i++) for(j=0;j<numdofm; j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+		for( i=0; i<numdofm; i++) for(j=0;j<numdofs; j++) Ke_gg2[i][j]+=Ke_gg_gaussian2[i][j];
+	} 
+	for(i=0;i<numdofs;i++) for(j=0;j<numdofm;j++) Ke->values[(i+2*numdofm)*numdoftotal+j]+=Ke_gg[i][j];
+	for(i=0;i<numdofm;i++) for(j=0;j<numdofs;j++) Ke->values[i*numdoftotal+(j+2*numdofm)]+=Ke_gg2[i][j];
+
+	/*Clean-up and return*/
+	delete tria->matice; delete tria;
+	delete gauss;
+	delete gauss_tria;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingMacAyealStokesFriction {{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingMacAyealStokesFriction(void){
+
+	/*Constants*/
+	const int numdof=NUMVERTICES*NDOF4;
+	const int numdofm=NUMVERTICES*NDOF2;
+	const int numdof2d=NUMVERTICES2D*NDOF4;
+	const int numdof2dm=NUMVERTICES2D*NDOF2;
+	const int numdoftot=numdof+numdofm;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        analysis_type,approximation;
+	double     stokesreconditioning;
+	double     viscosity,alpha2_gauss,Jdet2d;
+	double	  bed_normal[3];
+	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double     xyz_list[NUMVERTICES][3];
+	double	  xyz_list_tria[NUMVERTICES2D][3];
+	double     LMacAyealStokes[8][numdof2dm];
+	double     LprimeMacAyealStokes[8][numdof2d];
+	double     DLMacAyealStokes[8][8]={0.0};
+	double     LStokesMacAyeal[4][numdof2d];
+	double     LprimeStokesMacAyeal[4][numdof2dm];
+	double     DLStokesMacAyeal[4][4]={0.0};
+	double     Ke_drag_gaussian[numdof2dm][numdof2d];
+	double     Ke_drag_gaussian2[numdof2d][numdof2dm];
+	Friction*  friction=NULL;
+	GaussPenta *gauss=NULL;
+
+	/*If on water or not Stokes, skip stiffness: */
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(IsOnShelf() || !IsOnBed()) return NULL;
+	ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+	ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
+	delete Ke1; delete Ke2;
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/*build friction object, used later on: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
+		GetLMacAyealStokes(&LMacAyealStokes[0][0], gauss);
+		GetLprimeMacAyealStokes(&LprimeMacAyealStokes[0][0], &xyz_list[0][0], gauss);
+		GetLStokesMacAyeal(&LStokesMacAyeal[0][0], gauss);
+		GetLprimeStokesMacAyeal(&LprimeStokesMacAyeal[0][0], &xyz_list[0][0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		BedNormal(&bed_normal[0],xyz_list_tria);
+		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
+
+		DLMacAyealStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLMacAyealStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLMacAyealStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
+		DLMacAyealStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
+		DLMacAyealStokes[4][4]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
+		DLMacAyealStokes[5][5]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
+		DLMacAyealStokes[6][6]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
+		DLMacAyealStokes[7][7]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
+
+		DLStokesMacAyeal[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLStokesMacAyeal[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLStokesMacAyeal[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
+		DLStokesMacAyeal[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
+		
+		TripleMultiply( &LMacAyealStokes[0][0],8,numdof2dm,1,
+					&DLMacAyealStokes[0][0],8,8,0,
+					&LprimeMacAyealStokes[0][0],8,numdof2d,0,
+					&Ke_drag_gaussian[0][0],0);
+
+		TripleMultiply( &LStokesMacAyeal[0][0],4,numdof2d,1,
+					&DLStokesMacAyeal[0][0],4,4,0,
+					&LprimeStokesMacAyeal[0][0],4,numdof2dm,0,
+					&Ke_drag_gaussian2[0][0],0);
+
+		for(i=0;i<numdof2dm;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdoftot+j+numdofm]+=Ke_drag_gaussian[i][j];
+		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2dm;j++) Ke->values[(i+numdofm)*numdoftot+j]+=Ke_drag_gaussian2[i][j];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixCouplingPattynStokes{{{1*/
+ElementMatrix* Penta::CreateKMatrixCouplingPattynStokes(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
+	ElementMatrix* Ke2=new ElementMatrix(this->nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+	ElementMatrix* Ke=new ElementMatrix(Ke1,Ke2);
+	delete Ke1;
+	delete Ke2;
+	Ke1=CreateKMatrixDiagnosticPattyn();
+	Ke2=CreateKMatrixDiagnosticStokes();
+
+	/*Constants*/
+	const int    numdofp=NDOF2*NUMVERTICES;
+	const int    numdofs=NDOF4*NUMVERTICES;
+	const int    numdoftotal=(NDOF2+NDOF4)*NUMVERTICES;
+	int          i,j;
+
+	for(i=0;i<numdofs;i++) for(j=0;j<NUMVERTICES;j++){
+		Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+0]+=Ke2->values[i*numdofs+NDOF4*j+0];
+		Ke->values[(i+numdofp)*numdoftotal+NDOF2*j+1]+=Ke2->values[i*numdofs+NDOF4*j+1];
+	}
+	for(i=0;i<numdofp;i++) for(j=0;j<NUMVERTICES;j++){
+		Ke->values[i*numdoftotal+numdofp+NDOF4*j+0]+=Ke1->values[i*numdofp+NDOF2*j+0];
+		Ke->values[i*numdoftotal+numdofp+NDOF4*j+1]+=Ke1->values[i*numdofp+NDOF2*j+1];
+	}
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticHoriz {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticHoriz(void){
+
+	int approximation;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	switch(approximation){
+		case MacAyealApproximationEnum:
+			return CreateKMatrixDiagnosticMacAyeal2d();
+		case PattynApproximationEnum:
+			return CreateKMatrixDiagnosticPattyn();
+		case StokesApproximationEnum:
+			return CreateKMatrixDiagnosticStokes();
+		case HutterApproximationEnum:
+			return NULL;
+		case NoneApproximationEnum:
+			return NULL;
+		case MacAyealPattynApproximationEnum:
+			return CreateKMatrixDiagnosticMacAyealPattyn();
+		case MacAyealStokesApproximationEnum:
+			return CreateKMatrixDiagnosticMacAyealStokes();
+		case PattynStokesApproximationEnum:
+			return CreateKMatrixDiagnosticPattynStokes();
+		default:
+			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticHutter{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticHutter(void){
+
+	/*Constants*/
+	const int numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries*/
+	int       connectivity[2];
+	int       i,i0,i1,j0,j1;
+	double    one0,one1;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Spawn 3 beam elements: */
+	for(i=0;i<3;i++){
+		/*2 dofs of first node*/
+		i0=2*i;
+		i1=2*i+1;
+		/*2 dofs of second node*/
+		j0=2*(i+3);
+		j1=2*(i+3)+1;
+
+		/*Find connectivity for the two nodes*/
+		connectivity[0]=nodes[i]->GetConnectivity();
+		connectivity[1]=nodes[i+3]->GetConnectivity();
+		one0=1/(double)connectivity[0];
+		one1=1/(double)connectivity[1];
+
+		/*Create matrix for these two nodes*/
+		if (IsOnBed() && IsOnSurface()){
+			Ke->values[i0*numdof+i0]=one0;
+			Ke->values[i1*numdof+i1]=one0;
+			Ke->values[j0*numdof+i0]=-one1;
+			Ke->values[j0*numdof+j0]=one1;
+			Ke->values[j1*numdof+i1]=-one1;
+			Ke->values[j1*numdof+j1]=one1;
+		}
+		else if (IsOnBed()){
+			Ke->values[i0*numdof+i0]=one0;
+			Ke->values[i1*numdof+i1]=one0;
+			Ke->values[j0*numdof+i0]=-2*one1;
+			Ke->values[j0*numdof+j0]=2*one1;
+			Ke->values[j1*numdof+i1]=-2*one1;
+			Ke->values[j1*numdof+j1]=2*one1;
+		}
+		else if (IsOnSurface()){
+			Ke->values[j0*numdof+i0]=-one1;
+			Ke->values[j0*numdof+j0]=one1;
+			Ke->values[j1*numdof+i1]=-one1;
+			Ke->values[j1*numdof+j1]=one1;
+		}
+		else{ //node is on two horizontal layers and beams include the values only once, so the have to use half of the connectivity
+			Ke->values[j0*numdof+i0]=-2*one1;
+			Ke->values[j0*numdof+j0]=2*one1;
+			Ke->values[j1*numdof+i1]=-2*one1;
+			Ke->values[j1*numdof+j1]=2*one1;
+		}
+	}
+
+	/*Clean up and return*/
+	return Ke;
+}
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal2d{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal2d(void){
+
+	/*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 
+	  bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build 
+	  the stiffness matrix. */
+	if (!IsOnBed()) return NULL;
+
+	/*Depth Averaging B*/
+	this->InputDepthAverageAtBase(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum,MaterialsEnum);
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyeal();
+	delete tria->matice; delete tria;
+
+	/*Delete B averaged*/
+	this->matice->inputs->DeleteInput(MaterialsRheologyBbarEnum);
+
+	/*clean up and return*/
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3d{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3d(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3dViscous();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyeal3dFriction();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dViscous{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dViscous(void){
+
+	/*Constants*/
+	const int    numdof2d=2*NUMVERTICES2D;
+
+	/*Intermediaries */
+	int         i,j,ig,approximation;
+	double      Jdet;
+	double      viscosity, oldviscosity, newviscosity, viscosity_overshoot;
+	double      epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	double      epsilons[6]; //6 for stokes
+	double      xyz_list[NUMVERTICES][3];
+	double      B[3][numdof2d];
+	double      Bprime[3][numdof2d];
+	double      D[3][3]={0.0};            // material matrix, simple scalar matrix.
+	double      D_scalar;
+	double      Ke_gg_gaussian[numdof2d][numdof2d]; //stiffness matrix evaluated at the gaussian point.
+	Tria*       tria=NULL;
+	Penta*      pentabase=NULL;
+	GaussPenta *gauss=NULL;
+	GaussTria  *gauss_tria=NULL;
+
+	/*Find penta on bed as this is a macayeal elements: */
+	pentabase=GetBasalElement();
+	tria=pentabase->SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(tria->nodes,NUMVERTICES2D,this->parameters,MacAyealApproximationEnum);
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes,NUMVERTICES);
+	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
+	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
+	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	gauss_tria=new GaussTria();
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+		gauss->SynchronizeGaussTria(gauss_tria);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		tria->GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss_tria);
+		tria->GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss_tria);
+
+		if(approximation==MacAyealPattynApproximationEnum){
+			this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
+			this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
+			matice->GetViscosity3d(&viscosity, &epsilon[0]);
+			matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
+
+			newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+		}
+		else if (approximation==MacAyealStokesApproximationEnum){
+			this->GetStrainRate3d(&epsilons[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+			matice->GetViscosity3dStokes(&newviscosity,&epsilons[0]);
+		}
+		else _error_("approximation %i (%s) not supported yet",approximation,EnumToStringx(approximation));
+
+		D_scalar=2*newviscosity*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],3,numdof2d,1,
+					&D[0][0],3,3,0,
+					&Bprime[0][0],3,numdof2d,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof2d+j]+=Ke_gg_gaussian[i][j];
+	}
+
+	/*Clean up and return*/
+	delete tria->matice;
+	delete tria;
+	delete gauss_tria;
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyeal3dFriction{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyeal3dFriction(void){
+
+	/*Initialize Element matrix and return if necessary*/
+	if(IsOnShelf() || !IsOnBed()) return NULL;
+
+	/*Build a tria element using the 3 nodes of the base of the penta. Then use 
+	 * the tria functionality to build a friction stiffness matrix on these 3
+	 * nodes: */
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementMatrix* Ke=tria->CreateKMatrixDiagnosticMacAyealFriction();
+	delete tria->matice; delete tria;
+
+	/*clean-up and return*/
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealPattyn{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealPattyn(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticPattyn();
+	ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealPattyn();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	delete Ke3;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticMacAyealStokes{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticMacAyealStokes(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyeal3d();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
+	ElementMatrix* Ke3=CreateKMatrixCouplingMacAyealStokes();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	delete Ke3;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticPattyn{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticPattyn(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticPattynViscous();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticPattynFriction();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticPattynViscous{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticPattynViscous(void){
+
+	/*Constants*/
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        approximation;
+	double     xyz_list[NUMVERTICES][3];
+	double     Jdet;
+	double     viscosity,oldviscosity,newviscosity,viscosity_overshoot; //viscosity
+	double     epsilon[5],oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	double     D_scalar;
+	double     D[5][5]={0.0};            // material matrix, simple scalar matrix.
+	double     B[5][numdof];
+	double     Bprime[5][numdof];
+	Tria*      tria=NULL;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vxold_input=inputs->GetInput(VxPicardEnum); _assert_(vxold_input);
+	Input* vyold_input=inputs->GetInput(VyPicardEnum); _assert_(vyold_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBPattyn(&B[0][0], &xyz_list[0][0], gauss);
+		GetBprimePattyn(&Bprime[0][0], &xyz_list[0][0], gauss);
+
+		this->GetStrainRate3dPattyn(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
+		this->GetStrainRate3dPattyn(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
+		matice->GetViscosity3d(&viscosity, &epsilon[0]);
+		matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
+		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+
+		D_scalar=2*newviscosity*gauss->weight*Jdet;
+		for (i=0;i<5;i++) D[i][i]=D_scalar;
+
+		TripleMultiply( &B[0][0],5,numdof,1,
+					&D[0][0],5,5,0,
+					&Bprime[0][0],5,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticPattynFriction{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticPattynFriction(void){
+
+	/*Constants*/
+	const int numdof   = NDOF2*NUMVERTICES;
+	
+	/*Intermediaries */
+	int       i,j,ig;
+	int       analysis_type;
+	double    xyz_list[NUMVERTICES][3];
+	double    xyz_list_tria[NUMVERTICES2D][3]={0.0};
+	double    slope_magnitude,alpha2,Jdet;
+	double    slope[3]={0.0,0.0,0.0};
+	double    MAXSLOPE=.06; // 6 %
+	double    MOUNTAINKEXPONENT=10;
+	double    L[2][numdof];
+	double    DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
+	double    DL_scalar;
+	Friction  *friction = NULL;
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if(IsOnShelf() || !IsOnBed()) return NULL;
+
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<2;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
+
+	/*build friction object, used later on: */
+	friction=new Friction("2d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet, &xyz_list_tria[0][0],gauss);
+		GetL(&L[0][0], gauss,NDOF2);
+
+		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+		friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum); 
+		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
+
+		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
+		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
+		if (slope_magnitude>MAXSLOPE){
+			alpha2=pow((double)10,MOUNTAINKEXPONENT);
+		}
+		
+		DL_scalar=alpha2*gauss->weight*Jdet;
+		for (i=0;i<2;i++) DL[i][i]=DL_scalar;
+		
+		TripleMultiply( &L[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&L[0][0],2,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticPattynStokes{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticPattynStokes(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticPattyn();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokes();
+	ElementMatrix* Ke3=CreateKMatrixCouplingPattynStokes();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2,Ke3);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	delete Ke3;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticStokes{{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticStokes(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticStokesViscous();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticStokesFriction();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticStokesViscous {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticStokesViscous(void){
+
+	/*Intermediaries */
+	int        i,j,ig,approximation;
+	double     Jdet,viscosity,stokesreconditioning;
+	double     xyz_list[NUMVERTICES][3];
+	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double     B[8][27];
+	double     B_prime[8][27];
+	double     D_scalar;
+	double     D[8][8]={0.0};
+	double     Ke_temp[27][27]={0.0}; //for the six nodes and the bubble 
+	double     Ke_gaussian[27][27];
+	GaussPenta *gauss=NULL;
+
+	/*If on water or not Stokes, skip stiffness: */
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 
+		GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0],gauss); 
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		D_scalar=gauss->weight*Jdet;
+		for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
+		for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
+
+		TripleMultiply( &B[0][0],8,27,1,
+					&D[0][0],8,8,0,
+					&B_prime[0][0],8,27,0,
+					&Ke_gaussian[0][0],0);
+
+		for(i=0;i<27;i++) for(j=0;j<27;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
+	}
+
+	/*Condensation*/
+	ReduceMatrixStokes(Ke->values, &Ke_temp[0][0]);
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticStokesFriction {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticStokesFriction(void){
+
+	/*Constants*/
+	const int numdof=NUMVERTICES*NDOF4;
+	const int numdof2d=NUMVERTICES2D*NDOF4;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        analysis_type,approximation;
+	double     stokesreconditioning;
+	double     viscosity,alpha2_gauss,Jdet2d;
+	double	  bed_normal[3];
+	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double     xyz_list[NUMVERTICES][3];
+	double	  xyz_list_tria[NUMVERTICES2D][3];
+	double     LStokes[14][numdof2d];
+	double     LprimeStokes[14][numdof2d];
+	double     DLStokes[14][14]={0.0};
+	double     Ke_drag_gaussian[numdof2d][numdof2d];
+	Friction*  friction=NULL;
+	GaussPenta *gauss=NULL;
+
+	/*If on water or not Stokes, skip stiffness: */
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(IsOnShelf() || !IsOnBed() || (approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum &&  approximation!=PattynStokesApproximationEnum)) return NULL;
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/*build friction object, used later on: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
+		GetLStokes(&LStokes[0][0], gauss);
+		GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		BedNormal(&bed_normal[0],xyz_list_tria);
+		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
+
+		DLStokes[0][0]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLStokes[1][1]=alpha2_gauss*gauss->weight*Jdet2d;
+		DLStokes[2][2]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
+		DLStokes[3][3]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
+		DLStokes[4][4]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[0]*bed_normal[2];
+		DLStokes[5][5]=-alpha2_gauss*gauss->weight*Jdet2d*bed_normal[1]*bed_normal[2];
+		DLStokes[6][6]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0];
+		DLStokes[7][7]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1];
+		DLStokes[8][8]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[2];
+		DLStokes[9][9]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[0]/2.0;
+		DLStokes[10][10]=-2*viscosity*gauss->weight*Jdet2d*bed_normal[1]/2.0;
+		DLStokes[11][11]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[0];
+		DLStokes[12][12]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[1];
+		DLStokes[13][13]=stokesreconditioning*gauss->weight*Jdet2d*bed_normal[2];
+
+		TripleMultiply( &LStokes[0][0],14,numdof2d,1,
+					&DLStokes[0][0],14,14,0,
+					&LprimeStokes[0][0],14,numdof2d,0,
+					&Ke_drag_gaussian[0][0],0);
+
+		for(i=0;i<numdof2d;i++) for(j=0;j<numdof2d;j++) Ke->values[i*numdof+j]+=Ke_drag_gaussian[i][j];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticVert {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticVert(void){
+	
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticVertVolume();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticVertSurface();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticVertVolume {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticVertVolume(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int         i,j,ig;
+	double      Jdet;
+	double      xyz_list[NUMVERTICES][3];
+	double      B[NDOF1][NUMVERTICES];
+	double      Bprime[NDOF1][NUMVERTICES];
+	double      DL_scalar;
+	GaussPenta  *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBVert(&B[0][0], &xyz_list[0][0], gauss);
+		GetBprimeVert(&Bprime[0][0], &xyz_list[0][0], gauss);
+
+		DL_scalar=gauss->weight*Jdet;
+
+		TripleMultiply( &B[0][0],1,NUMVERTICES,1,
+					&DL_scalar,1,1,0,
+					&Bprime[0][0],1,NUMVERTICES,0,
+					&Ke->values[0],1);
+	} 
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreateKMatrixDiagnosticVertSurface {{{1*/
+ElementMatrix* Penta::CreateKMatrixDiagnosticVertSurface(void){
+
+	if (!IsOnSurface()) return NULL;
+
+	/*Constants*/
+	const int numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int       i,j,ig;
+	double    xyz_list[NUMVERTICES][3];
+	double    xyz_list_tria[NUMVERTICES2D][3];
+	double    surface_normal[3];
+	double    Jdet2d,DL_scalar;
+	double    basis[NUMVERTICES];
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i+3][j];
+	SurfaceNormal(&surface_normal[0],xyz_list_tria);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(3,4,5,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		DL_scalar= - gauss->weight*Jdet2d*surface_normal[2]; 
+
+		TripleMultiply( basis,1,numdof,1,
+					&DL_scalar,1,1,0,
+					basis,1,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokes {{{1*/
+ElementVector* Penta::CreatePVectorCouplingMacAyealStokes(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorCouplingMacAyealStokesViscous();
+	ElementVector* pe2=CreatePVectorCouplingMacAyealStokesFriction();
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesViscous {{{1*/
+ElementVector* Penta::CreatePVectorCouplingMacAyealStokesViscous(void){
+
+	/*Constants*/
+	const int   numdof=NUMVERTICES*NDOF4;
+
+	/*Intermediaries */
+	int         i,j,ig;
+	int         approximation;
+	double      viscosity,Jdet;
+	double      stokesreconditioning;
+	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double      dw[3];
+	double      xyz_list[NUMVERTICES][3];
+	double      basis[6]; //for the six nodes of the penta
+	double      dbasis[3][6]; //for the six nodes of the penta
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=MacAyealStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
+	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+		GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+		vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		for(i=0;i<NUMVERTICES;i++){
+			pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
+			pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
+			pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
+			pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingMacAyealStokesFriction{{{1*/
+ElementVector* Penta::CreatePVectorCouplingMacAyealStokesFriction(void){
+
+	/*Constants*/
+	const int numdof=NUMVERTICES*NDOF4;
+
+	/*Intermediaries*/
+	int         i,j,ig;
+	int         approximation,analysis_type;
+	double      Jdet,Jdet2d;
+	double      stokesreconditioning;
+	double	   bed_normal[3];
+	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double      viscosity, w, alpha2_gauss;
+	double      dw[3];
+	double	   xyz_list_tria[NUMVERTICES2D][3];
+	double      xyz_list[NUMVERTICES][3];
+	double      basis[6]; //for the six nodes of the penta
+	Tria*       tria=NULL;
+	Friction*   friction=NULL;
+	GaussPenta  *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	if(!IsOnBed() || IsOnShelf()) return NULL;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=MacAyealStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
+	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);   _assert_(vzmacayeal_input);
+
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/*build friction object, used later on: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		vzmacayeal_input->GetParameterValue(&w, gauss);
+		vzmacayeal_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
+
+		BedNormal(&bed_normal[0],xyz_list_tria);
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
+
+		for(i=0;i<NUMVERTICES2D;i++){
+			pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
+			pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
+			pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingPattynStokes {{{1*/
+ElementVector* Penta::CreatePVectorCouplingPattynStokes(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorCouplingPattynStokesViscous();
+	ElementVector* pe2=CreatePVectorCouplingPattynStokesFriction();
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingPattynStokesViscous {{{1*/
+ElementVector* Penta::CreatePVectorCouplingPattynStokesViscous(void){
+
+	/*Constants*/
+	const int   numdof=NUMVERTICES*NDOF4;
+
+	/*Intermediaries */
+	int         i,j,ig;
+	int         approximation;
+	double      viscosity,Jdet;
+	double      stokesreconditioning;
+	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double      dw[3];
+	double      xyz_list[NUMVERTICES][3];
+	double      basis[6]; //for the six nodes of the penta
+	double      dbasis[3][6]; //for the six nodes of the penta
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=PattynStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
+	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+		GetNodalFunctionsP1Derivatives(&dbasis[0][0],&xyz_list[0][0], gauss);
+
+		vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		for(i=0;i<NUMVERTICES;i++){
+			pe->values[i*NDOF4+0]+=-Jdet*gauss->weight*viscosity*dw[0]*dbasis[2][i];
+			pe->values[i*NDOF4+1]+=-Jdet*gauss->weight*viscosity*dw[1]*dbasis[2][i];
+			pe->values[i*NDOF4+2]+=-Jdet*gauss->weight*viscosity*(dw[0]*dbasis[0][i]+dw[1]*dbasis[1][i]+2*dw[2]*dbasis[2][i]);
+			pe->values[i*NDOF4+3]+=Jdet*gauss->weight*stokesreconditioning*dw[2]*basis[i];
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorCouplingPattynStokesFriction{{{1*/
+ElementVector* Penta::CreatePVectorCouplingPattynStokesFriction(void){
+
+	/*Constants*/
+	const int numdof=NUMVERTICES*NDOF4;
+
+	/*Intermediaries*/
+	int         i,j,ig;
+	int         approximation,analysis_type;
+	double      Jdet,Jdet2d;
+	double      stokesreconditioning;
+	double	   bed_normal[3];
+	double      epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double      viscosity, w, alpha2_gauss;
+	double      dw[3];
+	double	   xyz_list_tria[NUMVERTICES2D][3];
+	double      xyz_list[NUMVERTICES][3];
+	double      basis[6]; //for the six nodes of the penta
+	Tria*       tria=NULL;
+	Friction*   friction=NULL;
+	GaussPenta  *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	if(!IsOnBed() || IsOnShelf()) return NULL;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=PattynStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);               _assert_(vz_input);
+	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);   _assert_(vzpattyn_input);
+
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/*build friction object, used later on: */
+	friction=new Friction("3d",inputs,matpar,analysis_type);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		vzpattyn_input->GetParameterValue(&w, gauss);
+		vzpattyn_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
+
+		BedNormal(&bed_normal[0],xyz_list_tria);
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+		friction->GetAlpha2(&alpha2_gauss, gauss,VxEnum,VyEnum,VzEnum);
+
+		for(i=0;i<NUMVERTICES2D;i++){
+			pe->values[i*NDOF4+0]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[0]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[0])*basis[i];
+			pe->values[i*NDOF4+1]+=Jdet2d*gauss->weight*(alpha2_gauss*w*bed_normal[1]*bed_normal[2]+2*viscosity*dw[2]*bed_normal[1])*basis[i];
+			pe->values[i*NDOF4+2]+=Jdet2d*gauss->weight*2*viscosity*(dw[0]*bed_normal[0]+dw[1]*bed_normal[1]+dw[2]*bed_normal[2])*basis[i];
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticHoriz{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticHoriz(void){
+
+	int approximation;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	switch(approximation){
+		case MacAyealApproximationEnum:
+			return CreatePVectorDiagnosticMacAyeal();
+		case PattynApproximationEnum:
+			return CreatePVectorDiagnosticPattyn();
+		case HutterApproximationEnum:
+			return NULL;
+		case NoneApproximationEnum:
+			return NULL;
+		case StokesApproximationEnum:
+			return CreatePVectorDiagnosticStokes();
+		case MacAyealPattynApproximationEnum:
+			return CreatePVectorDiagnosticMacAyealPattyn();
+		case MacAyealStokesApproximationEnum:
+			return CreatePVectorDiagnosticMacAyealStokes();
+		case PattynStokesApproximationEnum:
+			return CreatePVectorDiagnosticPattynStokes();
+		default:
+			_error_("Approximation %s not supported yet",EnumToStringx(approximation));
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealPattyn{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticMacAyealPattyn(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
+	ElementVector* pe2=CreatePVectorDiagnosticPattyn();
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticMacAyealStokes{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticMacAyealStokes(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorDiagnosticMacAyeal();
+	ElementVector* pe2=CreatePVectorDiagnosticStokes();
+	ElementVector* pe3=CreatePVectorCouplingMacAyealStokes();
+	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	delete pe3;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticPattynStokes{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticPattynStokes(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorDiagnosticPattyn();
+	ElementVector* pe2=CreatePVectorDiagnosticStokes();
+	ElementVector* pe3=CreatePVectorCouplingPattynStokes();
+	ElementVector* pe =new ElementVector(pe1,pe2,pe3);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	delete pe3;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticHutter{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticHutter(void){
+
+	/*Constants*/
+	const int numdofs=NDOF2*NUMVERTICES;
+
+	/*Intermediaries*/
+	int          i,j,k,ig;
+	int          node0,node1;
+	int          connectivity[2];
+	double       Jdet;
+	double       xyz_list[NUMVERTICES][3];
+	double       xyz_list_segment[2][3];
+	double       z_list[NUMVERTICES];
+	double       z_segment[2],slope[2];
+	double       slope2,constant_part;
+	double       rho_ice,gravity,n,B;
+	double       ub,vb,z_g,surface,thickness;
+	GaussPenta*  gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	n=matice->GetN();
+	B=matice->GetB();
+	Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
+	Input* surface_input=inputs->GetInput(SurfaceEnum);      _assert_(surface_input);
+	Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
+	Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
+	for(i=0;i<NUMVERTICES;i++)z_list[i]=xyz_list[i][2];
+
+	/*Loop on the three segments*/
+	for(i=0;i<3;i++){
+		node0=i;
+		node1=i+3;
+
+		for(j=0;j<3;j++){
+			xyz_list_segment[0][j]=xyz_list[node0][j];
+			xyz_list_segment[1][j]=xyz_list[node1][j];
+		}
+
+		connectivity[0]=nodes[node0]->GetConnectivity();
+		connectivity[1]=nodes[node1]->GetConnectivity();
+
+		/*Loop on the Gauss points: */
+		gauss=new GaussPenta(node0,node1,3);
+		for(ig=gauss->begin();ig<gauss->end();ig++){
+			gauss->GaussPoint(ig);
+
+			slopex_input->GetParameterValue(&slope[0],gauss);
+			slopey_input->GetParameterValue(&slope[1],gauss);
+			surface_input->GetParameterValue(&surface,gauss);
+			thickness_input->GetParameterValue(&thickness,gauss);
+
+			slope2=pow(slope[0],2)+pow(slope[1],2);
+			constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
+
+			PentaRef::GetParameterValue(&z_g,&z_list[0],gauss);
+			GetSegmentJacobianDeterminant(&Jdet,&xyz_list_segment[0][0],gauss);
+
+			if (IsOnSurface()){
+				for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight/(double)connectivity[1];
+			}
+			else{//connectivity is too large, should take only half on it
+				for(j=0;j<NDOF2;j++) pe->values[2*node1+j]+=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss->weight*2/(double)connectivity[1];
+			}
+		}
+		delete gauss;
+
+		//Deal with lower surface
+		if (IsOnBed()){
+			constant_part=-1.58*pow((double)10.0,-(double)10.0)*rho_ice*gravity*thickness;
+			ub=constant_part*slope[0];
+			vb=constant_part*slope[1];
+
+			pe->values[2*node0]+=ub/(double)connectivity[0];
+			pe->values[2*node0+1]+=vb/(double)connectivity[0];
+		}
+	}
+
+	/*Clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticMacAyeal{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticMacAyeal(void){
+
+	if (!IsOnBed()) return NULL;
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementVector* pe=tria->CreatePVectorDiagnosticMacAyeal();
+	delete tria->matice; delete tria;
+
+	/*Clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticPattyn{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticPattyn(void){
+
+	/*Constants*/
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries*/
+	int         i,j,ig;
+	double      Jdet;
+	double      slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!
+	double      driving_stress_baseline,thickness;
+	double      xyz_list[NUMVERTICES][3];
+	double      basis[6];
+	GaussPenta  *gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,PattynApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,3);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		thickness_input->GetParameterValue(&thickness, gauss);
+		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+
+		driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();
+
+		for(i=0;i<NUMVERTICES;i++) for(j=0;j<NDOF2;j++) pe->values[i*NDOF2+j]+= -driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticStokes {{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticStokes(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorDiagnosticStokesViscous();
+	ElementVector* pe2=CreatePVectorDiagnosticStokesShelf();
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticStokesViscous {{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticStokesViscous(void){
+
+	/*Constants*/
+	const int numdofbubble=NDOF4*NUMVERTICES+NDOF3*1;
+
+	/*Intermediaries*/
+	int        i,j,ig;
+	int        approximation;
+	double     Jdet,viscosity;
+	double     gravity,rho_ice,stokesreconditioning;
+	double     xyz_list[NUMVERTICES][3];
+	double     epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double     l1l7[7]; //for the six nodes and the bubble 
+	double     B[8][numdofbubble];
+	double     B_prime[8][numdofbubble];
+	double     B_prime_bubble[8][3];
+	double     D[8][8]={0.0};
+	double     D_scalar;
+	double     Pe_gaussian[numdofbubble]={0.0}; //for the six nodes and the bubble 
+	double     Ke_temp[numdofbubble][3]={0.0}; //for the six nodes and the bubble 
+	double     Ke_gaussian[numdofbubble][3];
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(5,5);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetBStokes(&B[0][0],&xyz_list[0][0],gauss); 
+		GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss); 
+		GetNodalFunctionsMINI(&l1l7[0], gauss);
+
+		this->GetStrainRate3d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input,vz_input);
+		matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+		for(i=0;i<NUMVERTICES+1;i++){
+			Pe_gaussian[i*NDOF4+2]+=-rho_ice*gravity*Jdet*gauss->weight*l1l7[i];
+		}
+
+		/*Get bubble part of Bprime */
+		for(i=0;i<8;i++) for(j=0;j<3;j++) B_prime_bubble[i][j]=B_prime[i][j+24];
+
+		D_scalar=gauss->weight*Jdet;
+		for (i=0;i<6;i++) D[i][i]=D_scalar*2*viscosity;
+		for (i=6;i<8;i++) D[i][i]=-D_scalar*stokesreconditioning;
+
+		TripleMultiply(&B[0][0],8,numdofbubble,1,
+					&D[0][0],8,8,0,
+					&B_prime_bubble[0][0],8,3,0,
+					&Ke_gaussian[0][0],0);
+
+		for(i=0;i<numdofbubble;i++) for(j=0;j<NDOF3;j++) Ke_temp[i][j]+=Ke_gaussian[i][j];
+	}
+
+	/*Condensation*/
+	ReduceVectorStokes(pe->values, &Ke_temp[0][0], &Pe_gaussian[0]);
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticStokesShelf{{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticStokesShelf(void){
+
+	/*Intermediaries*/
+	int         i,j,ig;
+	int         approximation,shelf_dampening;
+	double      gravity,rho_water,bed,water_pressure;
+	double      damper,normal_vel,vx,vy,vz,dt;
+	double		xyz_list_tria[NUMVERTICES2D][3];
+	double      xyz_list[NUMVERTICES][3];
+	double		bed_normal[3];
+	double      dz[3];
+	double      basis[6]; //for the six nodes of the penta
+	double      Jdet2d;
+	GaussPenta  *gauss=NULL;
+
+	/*Initialize Element vector and return if necessary*/
+	if(!IsOnBed() || !IsOnShelf()) return NULL;
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	this->parameters->FindParam(&shelf_dampening,DiagnosticShelfDampeningEnum);
+	if(approximation!=StokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum && approximation!=PattynStokesApproximationEnum) return NULL;
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,StokesApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	rho_water=matpar->GetRhoWater();
+	gravity=matpar->GetG();
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* bed_input=inputs->GetInput(BedEnum); _assert_(bed_input);
+	Input* vx_input=inputs->GetInput(VxEnum);   _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);   _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);   _assert_(vz_input);
+
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0], gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		BedNormal(&bed_normal[0],xyz_list_tria);
+		bed_input->GetParameterValue(&bed, gauss);
+		if(shelf_dampening){ //add dampening to avoid too high vertical velocities when not in hydrostatic equilibrium
+			bed_input->GetParameterDerivativeValue(&dz[0],&xyz_list[0][0],gauss);
+			vx_input->GetParameterValue(&vx, gauss);
+			vy_input->GetParameterValue(&vy, gauss);
+			vz_input->GetParameterValue(&vz, gauss);
+			dt=0;
+			normal_vel=bed_normal[0]*vx+bed_normal[1]*vy+bed_normal[2]*vz;
+			damper=gravity*rho_water*pow(1+pow(dz[0],2)+pow(dz[1],2),0.5)*normal_vel*dt;
+		}
+		else damper=0;
+		water_pressure=gravity*rho_water*bed;
+
+		for(i=0;i<NUMVERTICES;i++) for(j=0;j<3;j++) pe->values[i*NDOF4+j]+=(water_pressure+damper)*gauss->weight*Jdet2d*basis[i]*bed_normal[j];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticVert {{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticVert(void){
+
+	/*compute all load vectors for this element*/
+	ElementVector* pe1=CreatePVectorDiagnosticVertVolume();
+	ElementVector* pe2=CreatePVectorDiagnosticVertBase();
+	ElementVector* pe =new ElementVector(pe1,pe2);
+
+	/*clean-up and return*/
+	delete pe1;
+	delete pe2;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticVertVolume {{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticVertVolume(void){
+
+	/*Constants*/
+	const int  numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries*/
+	int        i,ig;
+	int        approximation;
+	double     Jdet;
+	double     xyz_list[NUMVERTICES][3];
+	double     dudx,dvdy,dwdz;
+	double     du[3],dv[3],dw[3];
+	double     basis[6];
+	GaussPenta *gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+	Input* vzstokes_input=NULL;
+	if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
+		vzstokes_input=inputs->GetInput(VzStokesEnum); _assert_(vzstokes_input);
+	}
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(2,2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctionsP1(basis, gauss);
+
+		vx_input->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss);
+		vy_input->GetParameterDerivativeValue(&dv[0],&xyz_list[0][0],gauss);
+		if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
+			vzstokes_input->GetParameterDerivativeValue(&dw[0],&xyz_list[0][0],gauss);
+			dwdz=dw[2];
+		}
+		else dwdz=0;
+		dudx=du[0];
+		dvdy=dv[1];
+
+		for (i=0;i<numdof;i++) pe->values[i] += (dudx+dvdy+dwdz)*Jdet*gauss->weight*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorDiagnosticVertBase {{{1*/
+ElementVector* Penta::CreatePVectorDiagnosticVertBase(void){
+
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	int        approximation;
+	double     xyz_list[NUMVERTICES][3];
+	double     xyz_list_tria[NUMVERTICES2D][3];
+	double     Jdet2d;
+	double     vx,vy,vz,dbdx,dbdy,basalmeltingvalue;
+	double     slope[3];
+	double     basis[NUMVERTICES];
+	GaussPenta* gauss=NULL;
+
+	if (!IsOnBed()) return NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES2D;i++) for(j=0;j<3;j++) xyz_list_tria[i][j]=xyz_list[i][j];
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	Input* bed_input=inputs->GetInput(BedEnum);                                _assert_(bed_input);
+	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
+	Input* vx_input=inputs->GetInput(VxEnum);                                  _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);                                  _assert_(vy_input);
+	Input* vzstokes_input=NULL;
+	if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
+		vzstokes_input=inputs->GetInput(VzStokesEnum);       _assert_(vzstokes_input);
+	}
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussPenta(0,1,2,2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		basal_melting_input->GetParameterValue(&basalmeltingvalue, gauss);
+		bed_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+		vx_input->GetParameterValue(&vx, gauss);
+		vy_input->GetParameterValue(&vy, gauss);
+		if(approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
+			vzstokes_input->GetParameterValue(&vz, gauss);
+		}
+		else vz=0;
+
+		dbdx=slope[0];
+		dbdy=slope[1];
+
+		GetTriaJacobianDeterminant(&Jdet2d, &xyz_list_tria[0][0],gauss);
+		GetNodalFunctionsP1(&basis[0], gauss);
+
+		for(i=0;i<numdof;i++) pe->values[i]+=-Jdet2d*gauss->weight*(vx*dbdx+vy*dbdy-vz-basalmeltingvalue)*basis[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHoriz{{{1*/
+void  Penta::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int          i;
+	int          approximation;
+	int*         doflist=NULL;
+	double       vx,vy;
+	double       values[numdof];
+	GaussPenta*  gauss;
+
+	/*Get approximation enum and dof list: */
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+
+	/*If the element is a coupling, do nothing: every node is also on an other elements 
+	 * (as coupling is between MacAyeal and Pattyn) so the other element will take care of it*/
+	GetDofList(&doflist,approximation,GsetEnum);
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	/*P1 element only for now*/
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+
+		/*Recover vx and vy*/
+		gauss->GaussVertex(i);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		values[i*NDOF2+0]=vx;
+		values[i*NDOF2+1]=vy;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsDiagnosticHutter{{{1*/
+void  Penta::GetSolutionFromInputsDiagnosticHutter(Vec solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       vx,vy;
+	double       values[numdof];
+	GaussPenta*  gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	/*P1 element only for now*/
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+		/*Recover vx and vy*/
+		gauss->GaussVertex(i);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		values[i*NDOF2+0]=vx;
+		values[i*NDOF2+1]=vy;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsDiagnosticVert{{{1*/
+void  Penta::GetSolutionFromInputsDiagnosticVert(Vec solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       vz;
+	double       values[numdof];
+	GaussPenta*  gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	Input* vz_input=inputs->GetInput(VzEnum); _assert_(vz_input);
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	/*P1 element only for now*/
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+		/*Recover vz */
+		gauss->GaussVertex(i);
+		vz_input->GetParameterValue(&vz,gauss);
+		values[i]=vz;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputsDiagnosticStokes{{{1*/
+void  Penta::GetSolutionFromInputsDiagnosticStokes(Vec solution){
+
+	const int    numdof=NDOF4*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       vx,vy,vz,p;
+	double       stokesreconditioning;
+	double       values[numdof];
+	GaussPenta   *gauss;
+
+	/*Get dof list: */
+	GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
+	Input* vx_input=inputs->GetInput(VxEnum);       _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);       _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);       _assert_(vz_input);
+	Input* p_input =inputs->GetInput(PressureEnum); _assert_(p_input);
+
+	/*Recondition pressure: */
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+
+	/*Ok, we have vx vy vz and P in values, fill in vx vy vz P arrays: */
+	/*P1 element only for now*/
+	gauss=new GaussPenta();
+	for(i=0;i<NUMVERTICES;i++){
+		gauss->GaussVertex(i);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vz_input->GetParameterValue(&vz,gauss);
+		p_input ->GetParameterValue(&p ,gauss);
+		values[i*NDOF4+0]=vx;
+		values[i*NDOF4+1]=vy;
+		values[i*NDOF4+2]=vz;
+		values[i*NDOF4+3]=p/stokesreconditioning;
+	}
+
+	/*Add value to global vector*/
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
+
+	int  approximation;
+
+	/*Recover inputs*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+
+	/*MacAyeal, everything is done by the element on bed*/
+	if (approximation==MacAyealApproximationEnum){
+		if (!IsOnBed()){
+			/*Do nothing. Element on bed will take care of it*/
+			return;
+		}
+		else{
+			InputUpdateFromSolutionDiagnosticMacAyeal(solution);
+			return;
+		}
+	}
+	else if (approximation==PattynApproximationEnum){
+		InputUpdateFromSolutionDiagnosticPattyn(solution);
+	}
+	else if (approximation==PattynStokesApproximationEnum){
+		InputUpdateFromSolutionDiagnosticPattynStokes(solution);
+	}
+	else if (approximation==MacAyealStokesApproximationEnum){
+		InputUpdateFromSolutionDiagnosticMacAyealStokes(solution);
+	}
+	else if (approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
+		InputUpdateFromSolutionDiagnosticStokes(solution);
+	}
+	else if (approximation==MacAyealPattynApproximationEnum){
+		InputUpdateFromSolutionDiagnosticMacAyealPattyn(solution);
+	}
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyeal {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticMacAyeal(double* solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int     i,dummy;
+	double  rho_ice,g;
+	double  values[numdof];
+	double  vx[NUMVERTICES];
+	double  vy[NUMVERTICES];
+	double  vz[NUMVERTICES];
+	double  vel[NUMVERTICES];
+	double  pressure[NUMVERTICES];
+	double  surface[NUMVERTICES];
+	double  xyz_list[NUMVERTICES][3];
+	int    *doflist = NULL;
+	double *vz_ptr  = NULL;
+	Penta  *penta   = NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,MacAyealApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays and extrude */
+	for(i=0;i<3;i++){
+		vx[i]  =values[i*NDOF2+0];
+		vy[i]  =values[i*NDOF2+1];
+		vx[i+3]=vx[i];
+		vy[i+3]=vy[i];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get parameters fro pressure computation*/
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+
+	/*Start looping over all elements above current element and update all inputs*/
+	penta=this;
+	for(;;){
+
+		/*Get node data: */
+		GetVerticesCoordinates(&xyz_list[0][0],penta->nodes,NUMVERTICES);
+
+		/*Now Compute vel*/
+		Input* vz_input=inputs->GetInput(VzEnum);
+		if (vz_input){
+			if (vz_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
+			vz_input->GetValuesPtr(&vz_ptr,&dummy);
+			for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
+		}
+		else{for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;}
+		for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+		/*Now compute pressure*/
+		GetParameterListOnVertices(&surface[0],SurfaceEnum);
+		for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+
+		/*Now, we have to move the previous Vx and Vy inputs  to old 
+		 * status, otherwise, we'll wipe them off: */
+		penta->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+		penta->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+		penta->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+		/*Add vx and vy as inputs to the tria element: */
+		penta->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+		penta->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+		penta->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+		penta->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+		/*Stop if we have reached the surface*/
+		if (penta->IsOnSurface()) break;
+
+		/* get upper Penta*/
+		penta=penta->GetUpperElement(); _assert_(penta->Id()!=this->id);
+	}
+	
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticMacAyealPattyn(double* solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+	const int    numdof2d=NDOF2*NUMVERTICES2D;
+
+	int     i,dummy;
+	double  rho_ice,g;
+	double  macayeal_values[numdof];
+	double  pattyn_values[numdof];
+	double  vx[NUMVERTICES];
+	double  vy[NUMVERTICES];
+	double  vz[NUMVERTICES];
+	double  vel[NUMVERTICES];
+	double  pressure[NUMVERTICES];
+	double  surface[NUMVERTICES];
+	double  xyz_list[NUMVERTICES][3];
+	int*    doflistp = NULL;
+	int*    doflistm = NULL;
+	double  *vz_ptr  = NULL;
+	Penta   *penta   = NULL;
+
+	/*OK, we have to add results of this element for pattyn 
+	 * and results from the penta at base for macayeal. Now recover results*/
+	penta=GetBasalElement();
+
+	/*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
+	GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
+	penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof2d;i++){
+		pattyn_values[i]=solution[doflistp[i]];
+		macayeal_values[i]=solution[doflistm[i]];
+	}
+	for(i=numdof2d;i<numdof;i++){
+		pattyn_values[i]=solution[doflistp[i]];
+		macayeal_values[i]=macayeal_values[i-numdof2d];
+	}
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<NUMVERTICES;i++){
+		vx[i]=macayeal_values[i*NDOF2+0]+pattyn_values[i*NDOF2+0];
+		vy[i]=macayeal_values[i*NDOF2+1]+pattyn_values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	Input* vz_input=inputs->GetInput(VzEnum);
+	if (vz_input){
+		if (vz_input->Enum()!=PentaVertexInputEnum){
+			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
+		}
+		vz_input->GetValuesPtr(&vz_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
+	}
+	else{
+		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
+	 *so the pressure is just the pressure at the z elevation: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	GetParameterListOnVertices(&surface[0],SurfaceEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflistp);
+	xfree((void**)&doflistm);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticMacAyealStokes(double* solution){
+
+	const int    numdofm=NDOF2*NUMVERTICES;
+	const int    numdofs=NDOF4*NUMVERTICES;
+	const int    numdof2d=NDOF2*NUMVERTICES2D;
+
+	int     i,dummy;
+	double  stokesreconditioning;
+	double  macayeal_values[numdofm];
+	double  stokes_values[numdofs];
+	double  vx[NUMVERTICES];
+	double  vy[NUMVERTICES];
+	double  vz[NUMVERTICES];
+	double  vzmacayeal[NUMVERTICES];
+	double  vzstokes[NUMVERTICES];
+	double  vel[NUMVERTICES];
+	double  pressure[NUMVERTICES];
+	double  xyz_list[NUMVERTICES][3];
+	int*    doflistm        = NULL;
+	int*    doflists        = NULL;
+	double  *vzmacayeal_ptr = NULL;
+	Penta   *penta          = NULL;
+
+	/*OK, we have to add results of this element for macayeal 
+	 * and results from the penta at base for macayeal. Now recover results*/
+	penta=GetBasalElement();
+
+	/*Get dof listof this element (macayeal dofs) and of the penta at base (macayeal dofs): */
+	penta->GetDofList(&doflistm,MacAyealApproximationEnum,GsetEnum);
+	GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof2d;i++){
+		macayeal_values[i]=solution[doflistm[i]];
+		macayeal_values[i+numdof2d]=solution[doflistm[i]];
+	}
+	for(i=0;i<numdofs;i++){
+		stokes_values[i]=solution[doflists[i]];
+	}
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<NUMVERTICES;i++){
+		vx[i]=stokes_values[i*NDOF4+0]+macayeal_values[i*NDOF2+0];
+		vy[i]=stokes_values[i*NDOF4+1]+macayeal_values[i*NDOF2+1];
+		vzstokes[i]=stokes_values[i*NDOF4+2];
+		pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
+
+		/*Check solution*/
+		if(isnan(vx[i]))       _error_("NaN found in solution vector");
+		if(isnan(vy[i]))       _error_("NaN found in solution vector");
+		if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
+		if(isnan(pressure[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	Input* vzmacayeal_input=inputs->GetInput(VzMacAyealEnum);
+	if (vzmacayeal_input){
+		if (vzmacayeal_input->Enum()!=PentaVertexInputEnum){
+			_error_("Cannot compute Vel as VzMacAyeal is of type %s",EnumToStringx(vzmacayeal_input->Enum()));
+		}
+		vzmacayeal_input->GetValuesPtr(&vzmacayeal_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vzmacayeal[i]=vzmacayeal_ptr[i];
+	}
+	else{
+		_error_("Cannot update solution as VzMacAyeal is not present");
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) {
+		vz[i]=vzmacayeal[i]+vzstokes[i];
+		vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+	}
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
+	this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflistm);
+	xfree((void**)&doflists);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattyn {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticPattyn(double* solution){
+	
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int    i,dummy;
+	double rho_ice,g;
+	double values[numdof];
+	double vx[NUMVERTICES];
+	double vy[NUMVERTICES];
+	double vz[NUMVERTICES];
+	double vel[NUMVERTICES];
+	double pressure[NUMVERTICES];
+	double surface[NUMVERTICES];
+	double xyz_list[NUMVERTICES][3];
+	int*   doflist = NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,PattynApproximationEnum,GsetEnum);
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
+		vx[i]=values[i*NDOF2+0];
+		vy[i]=values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	Input* vz_input=inputs->GetInput(VzEnum);
+	if (vz_input){
+		GetParameterListOnVertices(&vz[0],VzEnum);
+	}
+	else{
+		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
+	 *so the pressure is just the pressure at the z elevation: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	GetParameterListOnVertices(&surface[0],SurfaceEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticPattynStokes {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticPattynStokes(double* solution){
+
+	const int    numdofp=NDOF2*NUMVERTICES;
+	const int    numdofs=NDOF4*NUMVERTICES;
+
+	int    i,dummy;
+	double pattyn_values[numdofp];
+	double stokes_values[numdofs];
+	double vx[NUMVERTICES];
+	double vy[NUMVERTICES];
+	double vz[NUMVERTICES];
+	double vzpattyn[NUMVERTICES];
+	double vzstokes[NUMVERTICES];
+	double vel[NUMVERTICES];
+	double pressure[NUMVERTICES];
+	double xyz_list[NUMVERTICES][3];
+	double stokesreconditioning;
+	int*   doflistp      = NULL;
+	int*   doflists      = NULL;
+	double *vzpattyn_ptr = NULL;
+	Penta  *penta        = NULL;
+
+	/*OK, we have to add results of this element for pattyn 
+	 * and results from the penta at base for macayeal. Now recover results*/
+	penta=GetBasalElement();
+
+	/*Get dof listof this element (pattyn dofs) and of the penta at base (macayeal dofs): */
+	GetDofList(&doflistp,PattynApproximationEnum,GsetEnum);
+	GetDofList(&doflists,StokesApproximationEnum,GsetEnum);
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdofp;i++) pattyn_values[i]=solution[doflistp[i]];
+	for(i=0;i<numdofs;i++) stokes_values[i]=solution[doflists[i]];
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<NUMVERTICES;i++){
+		vx[i]=stokes_values[i*NDOF4+0]+pattyn_values[i*NDOF2+0];
+		vy[i]=stokes_values[i*NDOF4+1]+pattyn_values[i*NDOF2+1];
+		vzstokes[i]=stokes_values[i*NDOF4+2];
+		pressure[i]=stokes_values[i*NDOF4+3]*stokesreconditioning;
+
+		/*Check solution*/
+		if(isnan(vx[i]))       _error_("NaN found in solution vector");
+		if(isnan(vy[i]))       _error_("NaN found in solution vector");
+		if(isnan(vzstokes[i])) _error_("NaN found in solution vector");
+		if(isnan(pressure[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	Input* vzpattyn_input=inputs->GetInput(VzPattynEnum);
+	if (vzpattyn_input){
+		if (vzpattyn_input->Enum()!=PentaVertexInputEnum){
+			_error_("Cannot compute Vel as VzPattyn is of type %s",EnumToStringx(vzpattyn_input->Enum()));
+		}
+		vzpattyn_input->GetValuesPtr(&vzpattyn_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vzpattyn[i]=vzpattyn_ptr[i];
+	}
+	else{
+		_error_("Cannot update solution as VzPattyn is not present");
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) {
+		vz[i]=vzpattyn[i]+vzstokes[i];
+		vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+	}
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
+	this->inputs->AddInput(new PentaVertexInput(VzStokesEnum,vzstokes));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflistp);
+	xfree((void**)&doflists);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticHutter {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticHutter(double* solution){
+	
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int     i,dummy;
+	double  rho_ice,g;
+	double  values[numdof];
+	double  vx[NUMVERTICES];
+	double  vy[NUMVERTICES];
+	double  vz[NUMVERTICES];
+	double  vel[NUMVERTICES];
+	double  pressure[NUMVERTICES];
+	double  surface[NUMVERTICES];
+	double  xyz_list[NUMVERTICES][3];
+	int*    doflist = NULL;
+	double* vz_ptr  = NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
+		vx[i]=values[i*NDOF2+0];
+		vy[i]=values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	Input* vz_input=inputs->GetInput(VzEnum);
+	if (vz_input){
+		if (vz_input->Enum()!=PentaVertexInputEnum){
+			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
+		}
+		vz_input->GetValuesPtr(&vz_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
+	}
+	else{
+		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
+	 *so the pressure is just the pressure at the z elevation: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	GetParameterListOnVertices(&surface[0],SurfaceEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticVert {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticVert(double* solution){
+
+	const int numdof=NDOF1*NUMVERTICES;
+	
+	int      i,dummy;
+	int      approximation;
+	double   rho_ice,g;
+	double   values[numdof];
+	double   vx[NUMVERTICES];
+	double   vy[NUMVERTICES];
+	double   vz[NUMVERTICES];
+	double   vzmacayeal[NUMVERTICES];
+	double   vzpattyn[NUMVERTICES];
+	double   vzstokes[NUMVERTICES];
+	double   vel[NUMVERTICES];
+	double   pressure[NUMVERTICES];
+	double   surface[NUMVERTICES];
+	double   xyz_list[NUMVERTICES][3];
+	int*     doflist      = NULL;
+	double*  vx_ptr       = NULL;
+	double*  vy_ptr       = NULL;
+	double*  vzstokes_ptr = NULL;
+
+
+	/*Get the approximation and do nothing if the element in Stokes or None*/
+	inputs->GetParameterValue(&approximation,ApproximationEnum);
+	if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
+		return;
+	}
+
+	/*Get dof list and vertices coordinates: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Use the dof list to index into the solution vector vz: */
+	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
+	for(i=0;i<NUMVERTICES;i++){
+		vz[i]=values[i*NDOF1+0];
+
+		/*Check solution*/
+		if(isnan(vz[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vx and Vy*/
+	Input* vx_input=inputs->GetInput(VxEnum);
+	if (vx_input){
+		if (vx_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vx is of type %s",EnumToStringx(vx_input->Enum()));
+		vx_input->GetValuesPtr(&vx_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vx[i]=vx_ptr[i];
+	}
+	else for(i=0;i<NUMVERTICES;i++) vx[i]=0.0;
+
+	Input* vy_input=inputs->GetInput(VyEnum);
+	if (vy_input){
+		if (vy_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as Vy is of type %s",EnumToStringx(vy_input->Enum()));
+		vy_input->GetValuesPtr(&vy_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vy[i]=vy_ptr[i];
+	}
+	else for(i=0;i<NUMVERTICES;i++) vy[i]=0.0;
+
+	/*Do some modifications if we actually have a PattynStokes or MacAyealStokes element*/
+	if(approximation==PattynStokesApproximationEnum){
+		Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
+		if (vzstokes_input){
+			if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
+			vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
+			for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
+		}
+		else _error_("Cannot compute Vz as VzStokes in not present in PattynStokes element");
+		for(i=0;i<NUMVERTICES;i++){
+			vzpattyn[i]=vz[i];
+			vz[i]=vzpattyn[i]+vzstokes[i];
+		}
+	}
+	else if(approximation==MacAyealStokesApproximationEnum){
+		Input* vzstokes_input=inputs->GetInput(VzStokesEnum);
+		if (vzstokes_input){
+			if (vzstokes_input->Enum()!=PentaVertexInputEnum) _error_("Cannot compute Vel as VzStokes is of type %s",EnumToStringx(vy_input->Enum()));
+			vzstokes_input->GetValuesPtr(&vzstokes_ptr,&dummy);
+			for(i=0;i<NUMVERTICES;i++) vzstokes[i]=vzstokes_ptr[i];
+		}
+		else _error_("Cannot compute Vz as VzStokes in not present in MacAyealStokes element");
+		for(i=0;i<NUMVERTICES;i++){
+			vzmacayeal[i]=vz[i];
+			vz[i]=vzmacayeal[i]+vzstokes[i];
+		}
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 3D, 
+	 *so the pressure is just the pressure at the z elevation: except it this is a PattynStokes element */
+	if(approximation!=PattynStokesApproximationEnum &&  approximation!=MacAyealStokesApproximationEnum){
+		rho_ice=matpar->GetRhoIce();
+		g=matpar->GetG();
+		GetParameterListOnVertices(&surface[0],SurfaceEnum);
+		for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+	}
+
+	/*Now, we have to move the previous Vz inputs to old 
+	 * status, otherwise, we'll wipe them off and add the new inputs: */
+	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
+
+	if(approximation!=PattynStokesApproximationEnum && approximation!=MacAyealStokesApproximationEnum){
+		this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+		this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+	}
+	else if(approximation==PattynStokesApproximationEnum){
+		this->inputs->AddInput(new PentaVertexInput(VzPattynEnum,vzpattyn));
+	}
+	else if(approximation==MacAyealStokesApproximationEnum){
+		this->inputs->AddInput(new PentaVertexInput(VzMacAyealEnum,vzmacayeal));
+	}
+
+	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Penta::InputUpdateFromSolutionDiagnosticStokes {{{1*/
+void  Penta::InputUpdateFromSolutionDiagnosticStokes(double* solution){
+	
+	const int numdof=NDOF4*NUMVERTICES;
+
+	int     i;
+	double  values[numdof];
+	double  vx[NUMVERTICES];
+	double  vy[NUMVERTICES];
+	double  vz[NUMVERTICES];
+	double  vel[NUMVERTICES];
+	double  pressure[NUMVERTICES];
+	double  stokesreconditioning;
+	int*    doflist=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,StokesApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++) values[i]=solution[doflist[i]];
+
+	/*Ok, we have vx and vy in values, fill in all arrays: */
+	for(i=0;i<NUMVERTICES;i++){
+		vx[i]=values[i*NDOF4+0];
+		vy[i]=values[i*NDOF4+1];
+		vz[i]=values[i*NDOF4+2];
+		pressure[i]=values[i*NDOF4+3];
+
+		/*Check solution*/
+		if(isnan(vx[i]))       _error_("NaN found in solution vector");
+		if(isnan(vy[i]))       _error_("NaN found in solution vector");
+		if(isnan(vz[i]))       _error_("NaN found in solution vector");
+		if(isnan(pressure[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Recondition pressure and compute vel: */
+	this->parameters->FindParam(&stokesreconditioning,DiagnosticStokesreconditioningEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=pressure[i]*stokesreconditioning;
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+	
+	/*Now, we have to move the previous inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(VzEnum,VzPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new PentaVertexInput(VzEnum,vz));
+	this->inputs->AddInput(new PentaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new PentaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+#endif
+
+#ifdef _HAVE_BALANCED_
+/*FUNCTION Penta::CreateKMatrixBalancethickness {{{1*/
+ElementMatrix* Penta::CreateKMatrixBalancethickness(void){
+
+	/*Figure out if this penta is collapsed. If so, then bailout, except if it is at the 
+	  bedrock, in which case we spawn a tria element using the 3 first nodes, and use it to build 
+	  the stiffness matrix. */
+	if (!IsOnBed()) return NULL;
+
+	/*Depth Averaging Vx and Vy*/
+	this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
+	this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
+
+	/*Spawn Tria element from the base of the Penta: */
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementMatrix* Ke=tria->CreateKMatrixBalancethickness();
+	delete tria->matice; delete tria;
+
+	/*Delete Vx and Vy averaged*/
+	this->inputs->DeleteInput(VxAverageEnum);
+	this->inputs->DeleteInput(VyAverageEnum);
+
+	/*clean up and return*/
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorBalancethickness {{{1*/
+ElementVector* Penta::CreatePVectorBalancethickness(void){
+
+	if (!IsOnBed()) return NULL;
+
+	/*Depth Averaging Vx and Vy*/
+	this->InputDepthAverageAtBase(VxEnum,VxAverageEnum);
+	this->InputDepthAverageAtBase(VyEnum,VyAverageEnum);
+
+	/*Call Tria function*/
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementVector* pe=tria->CreatePVectorBalancethickness();
+	delete tria->matice; delete tria;
+
+	/*Delete Vx and Vy averaged*/
+	this->inputs->DeleteInput(VxAverageEnum);
+	this->inputs->DeleteInput(VyAverageEnum);
+
+	/*Clean up and return*/
+	return pe;
+}
+/*}}}*/
+#endif
+
Index: /issm/trunk/src/c/objects/Elements/Penta.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.h	(revision 9774)
+++ /issm/trunk/src/c/objects/Elements/Penta.h	(revision 9775)
@@ -89,26 +89,5 @@
 		double GetZcoord(GaussPenta* gauss);
 		void   GetVectorFromInputs(Vec vector,int NameEnum);
-		#ifdef _HAVE_CONTROL_
-		double DragCoefficientAbsGradient(bool process_units,int weight_index);
-		void   Gradj(Vec gradient,int control_type);
-		void   GradjDragMacAyeal(Vec gradient);
-		void   GradjDragPattyn(Vec gradient);
-		void   GradjDragStokes(Vec gradient);
-		void   GradjBbarMacAyeal(Vec gradient);
-		void   GradjBbarPattyn(Vec gradient);
-		void   GradjBbarStokes(Vec gradient);
-		void   ControlInputGetGradient(Vec gradient,int enum_type);
-		void   ControlInputScaleGradient(int enum_type,double scale);
-		void   ControlInputSetGradient(double* gradient,int enum_type);
-		double RheologyBbarAbsGradient(bool process_units,int weight_index);
-		double ThicknessAbsMisfit(     bool process_units,int weight_index);
-		double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
-		double SurfaceRelVelMisfit(    bool process_units,int weight_index);
-		double SurfaceLogVelMisfit(    bool process_units,int weight_index);
-		double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
-		double SurfaceAverageVelMisfit(bool process_units,int weight_index);
-		double ThicknessAbsGradient(bool process_units,int weight_index);
-		void   InputControlUpdate(double scalar,bool save_parameter);
-		#endif
+		
 		int    Sid();
 		void   InputArtificialNoise(int enum_type,double min, double max);
@@ -152,8 +131,68 @@
 		void   ViscousHeatingCreateInput(void);
 		int    NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units);
+
+		#ifdef _HAVE_CONTROL_
+		double DragCoefficientAbsGradient(bool process_units,int weight_index);
+		void   Gradj(Vec gradient,int control_type);
+		void   GradjDragMacAyeal(Vec gradient);
+		void   GradjDragPattyn(Vec gradient);
+		void   GradjDragStokes(Vec gradient);
+		void   GradjBbarMacAyeal(Vec gradient);
+		void   GradjBbarPattyn(Vec gradient);
+		void   GradjBbarStokes(Vec gradient);
+		void   ControlInputGetGradient(Vec gradient,int enum_type);
+		void   ControlInputScaleGradient(int enum_type,double scale);
+		void   ControlInputSetGradient(double* gradient,int enum_type);
+		double RheologyBbarAbsGradient(bool process_units,int weight_index);
+		double ThicknessAbsMisfit(     bool process_units,int weight_index);
+		double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
+		double SurfaceRelVelMisfit(    bool process_units,int weight_index);
+		double SurfaceLogVelMisfit(    bool process_units,int weight_index);
+		double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
+		double SurfaceAverageVelMisfit(bool process_units,int weight_index);
+		double ThicknessAbsGradient(bool process_units,int weight_index);
+		void   InputControlUpdate(double scalar,bool save_parameter);
+		#endif
 		/*}}}*/
 		/*Penta specific routines:{{{1*/
 		void	  BedNormal(double* bed_normal, double xyz_list[3][3]);
-		ElementMatrix* CreateKMatrixBalancethickness(void);
+		ElementMatrix* CreateKMatrixPrognostic(void);
+		ElementMatrix* CreateKMatrixSlope(void);
+		ElementVector* CreatePVectorPrognostic(void);
+		ElementVector* CreatePVectorSlope(void);
+		void	  GetDofList(int** pdoflist,int approximation_enum,int setenum);
+		void	  GetDofList1(int* doflist);
+		void      GetSidList(int* sidlist);
+		int     GetElementType(void);
+		void    GetParameterListOnVertices(double* pvalue,int enumtype);
+		void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
+		void    GetParameterValue(double* pvalue,Node* node,int enumtype);
+		void	  GetPhi(double* phi, double*  epsilon, double viscosity);
+		void	  GetSolutionFromInputsEnthalpy(Vec solutiong);
+		double GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity);
+		void    GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input);
+		void    GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input);
+		Penta*  GetUpperElement(void);
+		Penta*  GetLowerElement(void);
+		Penta*  GetBasalElement(void);
+		void	  InputExtrude(int enum_type,int object_type);
+		void    InputUpdateFromSolutionPrognostic(double* solutiong);
+		void    InputUpdateFromSolutionOneDof(double* solutiong,int enum_type);
+		void    InputUpdateFromSolutionOneDofCollapsed(double* solutiong,int enum_type);
+		bool	  IsInput(int name);
+		bool	  IsOnSurface(void);
+		bool	  IsOnBed(void);
+		bool    IsOnShelf(void); 
+		bool    IsNodeOnShelf(void); 
+		bool    IsNodeOnShelfFromFlags(double* flags);
+		bool    IsOnWater(void); 
+		double  MinEdgeLength(double xyz_list[6][3]);
+		void	  ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp);
+		void	  ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp);
+		void	  SetClone(int* minranks);
+		Tria*	  SpawnTria(int g0, int g1, int g2);
+		void	  SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+
+		#ifdef _HAVE_DIAGNOSTIC_
 		ElementMatrix* CreateKMatrixCouplingMacAyealPattyn(void);
 		ElementMatrix* CreateKMatrixCouplingMacAyealPattynViscous(void);
@@ -183,17 +222,17 @@
 		ElementMatrix* CreateKMatrixDiagnosticVertVolume(void);
 		ElementMatrix* CreateKMatrixDiagnosticVertSurface(void);
-		ElementMatrix* CreateKMatrixEnthalpy(void);
-		ElementMatrix* CreateKMatrixEnthalpyVolume(void);
-		ElementMatrix* CreateKMatrixEnthalpyShelf(void);
-		ElementMatrix* CreateKMatrixMelting(void);
-		ElementMatrix* CreateKMatrixPrognostic(void);
-		ElementMatrix* CreateKMatrixSlope(void);
-		ElementMatrix* CreateKMatrixThermal(void);
-		ElementMatrix* CreateKMatrixThermalVolume(void);
-		ElementMatrix* CreateKMatrixThermalShelf(void);
-		ElementVector* CreatePVectorBalancethickness(void);
-		ElementVector* CreatePVectorAdjointHoriz(void);
-		ElementVector* CreatePVectorAdjointMacAyeal(void);
-		ElementVector* CreatePVectorAdjointPattyn(void);
+		void           InputUpdateFromSolutionDiagnosticHoriz( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticMacAyeal( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticMacAyealPattyn( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticMacAyealStokes( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticPattyn( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticPattynStokes( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticHutter( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticVert( double* solutiong);
+		void           InputUpdateFromSolutionDiagnosticStokes( double* solutiong);
+		void	       GetSolutionFromInputsDiagnosticHoriz(Vec solutiong);
+		void	       GetSolutionFromInputsDiagnosticHutter(Vec solutiong);
+		void	       GetSolutionFromInputsDiagnosticStokes(Vec solutiong);
+		void	       GetSolutionFromInputsDiagnosticVert(Vec solutiong);
 		ElementVector* CreatePVectorCouplingMacAyealStokes(void);
 		ElementVector* CreatePVectorCouplingMacAyealStokesViscous(void);
@@ -212,69 +251,46 @@
 		ElementVector* CreatePVectorDiagnosticStokesViscous(void);
 		ElementVector* CreatePVectorDiagnosticStokesShelf(void);
+		ElementVector* CreatePVectorDiagnosticVert(void);
+		ElementVector* CreatePVectorDiagnosticVertVolume(void);
+		ElementVector* CreatePVectorDiagnosticVertBase(void);
+		#endif
+
+		#ifdef _HAVE_CONTROL_
+		ElementVector* CreatePVectorAdjointHoriz(void);
+		ElementVector* CreatePVectorAdjointMacAyeal(void);
+		ElementVector* CreatePVectorAdjointPattyn(void);
+		ElementVector* CreatePVectorAdjointStokes(void);
+		void    InputUpdateFromSolutionAdjointHoriz( double* solutiong);
+		void    InputUpdateFromSolutionAdjointStokes( double* solutiong);
+		#endif
+
+		#ifdef _HAVE_HYDROLOGY_
+		void    CreateHydrologyWaterVelocityInput(void);
+		#endif
+		#ifdef _HAVE_THERMAL_
+		ElementMatrix* CreateKMatrixEnthalpy(void);
+		ElementMatrix* CreateKMatrixEnthalpyVolume(void);
+		ElementMatrix* CreateKMatrixEnthalpyShelf(void);
+		ElementMatrix* CreateKMatrixThermal(void);
+		ElementMatrix* CreateKMatrixMelting(void);
+		ElementMatrix* CreateKMatrixThermalVolume(void);
+		ElementMatrix* CreateKMatrixThermalShelf(void);
 		ElementVector* CreatePVectorEnthalpy(void);
 		ElementVector* CreatePVectorEnthalpyVolume(void);
 		ElementVector* CreatePVectorEnthalpyShelf(void);
 		ElementVector* CreatePVectorEnthalpySheet(void);
-		ElementVector* CreatePVectorAdjointStokes(void);
-		ElementVector* CreatePVectorDiagnosticVert(void);
-		ElementVector* CreatePVectorDiagnosticVertVolume(void);
-		ElementVector* CreatePVectorDiagnosticVertBase(void);
 		ElementVector* CreatePVectorMelting(void);
-		ElementVector* CreatePVectorPrognostic(void);
-		ElementVector* CreatePVectorSlope(void);
 		ElementVector* CreatePVectorThermal(void);
 		ElementVector* CreatePVectorThermalVolume(void);
 		ElementVector* CreatePVectorThermalShelf(void);
 		ElementVector* CreatePVectorThermalSheet(void);
-		void	  GetDofList(int** pdoflist,int approximation_enum,int setenum);
-		void	  GetDofList1(int* doflist);
-		void      GetSidList(int* sidlist);
-		int     GetElementType(void);
-		void    GetParameterListOnVertices(double* pvalue,int enumtype);
-		void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
-		void    GetParameterValue(double* pvalue,Node* node,int enumtype);
-		void	  GetPhi(double* phi, double*  epsilon, double viscosity);
-		void	  GetSolutionFromInputsDiagnosticHoriz(Vec solutiong);
-		void	  GetSolutionFromInputsDiagnosticHutter(Vec solutiong);
-		void	  GetSolutionFromInputsDiagnosticStokes(Vec solutiong);
-		void	  GetSolutionFromInputsDiagnosticVert(Vec solutiong);
-		void	  GetSolutionFromInputsThermal(Vec solutiong);
-		void	  GetSolutionFromInputsEnthalpy(Vec solutiong);
-		double GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity);
-		void    GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input);
-		void    GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input);
-		Penta*  GetUpperElement(void);
-		Penta*  GetLowerElement(void);
-		Penta*  GetBasalElement(void);
-		void	  InputExtrude(int enum_type,int object_type);
-		void    InputUpdateFromSolutionAdjointHoriz( double* solutiong);
-		void    InputUpdateFromSolutionAdjointStokes( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticHoriz( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticMacAyeal( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticMacAyealPattyn( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticMacAyealStokes( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticPattyn( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticPattynStokes( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticHutter( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticVert( double* solutiong);
-		void    InputUpdateFromSolutionDiagnosticStokes( double* solutiong);
-		void    InputUpdateFromSolutionPrognostic(double* solutiong);
-		void    InputUpdateFromSolutionThermal( double* solutiong);
-		void    InputUpdateFromSolutionEnthalpy( double* solutiong);
-		void    InputUpdateFromSolutionOneDof(double* solutiong,int enum_type);
-		void    InputUpdateFromSolutionOneDofCollapsed(double* solutiong,int enum_type);
-		bool	  IsInput(int name);
-		bool	  IsOnSurface(void);
-		bool	  IsOnBed(void);
-		bool    IsOnShelf(void); 
-		bool    IsNodeOnShelf(void); 
-		bool    IsNodeOnShelfFromFlags(double* flags);
-		bool    IsOnWater(void); 
-		double  MinEdgeLength(double xyz_list[6][3]);
-	   void	  ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp);
-		void	  ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp);
-		void	  SetClone(int* minranks);
-		Tria*	  SpawnTria(int g0, int g1, int g2);
-		void	  SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+		void	       GetSolutionFromInputsThermal(Vec solutiong);
+		void           InputUpdateFromSolutionThermal( double* solutiong);
+		void           InputUpdateFromSolutionEnthalpy( double* solutiong);
+		#endif
+		#ifdef _HAVE_BALANCED_
+		ElementMatrix* CreateKMatrixBalancethickness(void);
+		ElementVector* CreatePVectorBalancethickness(void);
+		#endif
 		/*}}}*/
 };
Index: /issm/trunk/src/c/objects/Elements/Tria.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 9774)
+++ /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 9775)
@@ -376,50 +376,4 @@
 }
 /*}}}*/
-/*FUNCTION Tria::CreateHydrologyWaterVelocityInput {{{1*/
-void Tria::CreateHydrologyWaterVelocityInput(void){
-
-	/*material parameters: */
-	double mu_water=0.001787;  //unit= [N s/m2]
-	double w;
-	double rho_ice, rho_water, g;
-	double dsdx,dsdy,dbdx,dbdy;
-	double vx[NUMVERTICES];
-	double vy[NUMVERTICES];
-	GaussTria *gauss = NULL;
-
-	/*Retrieve all inputs and parameters*/
-	rho_ice=matpar->GetRhoIce();
-	rho_water=matpar->GetRhoWater();
-	g=matpar->GetG();
-	Input* surfaceslopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
-	Input* surfaceslopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
-	Input* bedslopex_input=inputs->GetInput(BedSlopeXEnum);         _assert_(bedslopex_input);
-	Input* bedslopey_input=inputs->GetInput(BedSlopeYEnum);         _assert_(bedslopey_input);
-	Input* watercolumn_input=inputs->GetInput(WatercolumnEnum);     _assert_(watercolumn_input);
-
-	gauss=new GaussTria();
-	for (int iv=0;iv<NUMVERTICES;iv++){
-		gauss->GaussVertex(iv);
-		surfaceslopex_input->GetParameterValue(&dsdx,gauss);
-		surfaceslopey_input->GetParameterValue(&dsdy,gauss);
-		bedslopex_input->GetParameterValue(&dbdx,gauss);
-		bedslopey_input->GetParameterValue(&dbdy,gauss);
-		watercolumn_input->GetParameterValue(&w,gauss);
-
-		/* Water velocity x and y components */
-		vx[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
-		vy[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
-		//vx[iv]=0.001;
-		//vy[iv]=0;
-	}
-
-	/*clean-up*/
-	delete gauss;
-
-	/*Add to inputs*/
-	this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVxEnum,vx));
-	this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVyEnum,vy));
-}
-/*}}}*/
 /*FUNCTION Tria::CreateKMatrix {{{1*/
 void  Tria::CreateKMatrix(Mat Kff, Mat Kfs,Vec df){
@@ -439,4 +393,5 @@
 	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
 	switch(analysis_type){
+		#ifdef _HAVE_DIAGNOSTIC_
 		case DiagnosticHorizAnalysisEnum: case AdjointHorizAnalysisEnum:
 			Ke=CreateKMatrixDiagnosticMacAyeal();
@@ -445,4 +400,5 @@
 			Ke=CreateKMatrixDiagnosticHutter();
 			break;
+		 #endif
 		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
 			Ke=CreateKMatrixSlope();
@@ -451,13 +407,19 @@
 			Ke=CreateKMatrixPrognostic();
 			break;
+		#ifdef _HAVE_HYDROLOGY_
 		case HydrologyAnalysisEnum:
 			Ke=CreateKMatrixHydrology();
 			break;
+		#endif
+		#ifdef _HAVE_BALANCED_
 		case BalancethicknessAnalysisEnum:
 			Ke=CreateKMatrixBalancethickness();
 			break;
+		#endif
+		#ifdef _HAVE_CONTROL_
 		case AdjointBalancethicknessAnalysisEnum:
 			Ke=CreateKMatrixAdjointBalancethickness();
 			break;
+		#endif
 		default:
 			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
@@ -469,474 +431,4 @@
 		delete Ke;
 	}
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixAdjointBalancethickness {{{1*/
-ElementMatrix* Tria::CreateKMatrixAdjointBalancethickness(void){
-
-	ElementMatrix* Ke=NULL;
-
-	/*Get Element Matrix of the forward model*/
-	switch(GetElementType()){
-		case P1Enum:
-			Ke=CreateKMatrixBalancethickness_CG();
-			break;
-		case P1DGEnum:
-			Ke=CreateKMatrixBalancethickness_DG();
-			break;
-		default:
-			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
-	}
-
-	/*Transpose and return Ke*/
-	Ke->Transpose();
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixBalancethickness {{{1*/
-ElementMatrix* Tria::CreateKMatrixBalancethickness(void){
-
-	switch(GetElementType()){
-		case P1Enum:
-			return CreateKMatrixBalancethickness_CG();
-		case P1DGEnum:
-			return CreateKMatrixBalancethickness_DG();
-		default:
-			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
-	}
-
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixBalancethickness_CG {{{1*/
-ElementMatrix* Tria::CreateKMatrixBalancethickness_CG(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        stabilization;
-	int        i,j,ig,dim;
-	double     Jdettria,vx,vy,dvxdx,dvydy,vel,h;
-	double     dvx[2],dvy[2];
-	double     xyz_list[NUMVERTICES][3];
-	double     L[NUMVERTICES];
-	double     B[2][NUMVERTICES];
-	double     Bprime[2][NUMVERTICES];
-	double     K[2][2]                          = {0.0};
-	double     KDL[2][2]                        = {0.0};
-	double     DL[2][2]                         = {0.0};
-	double     DLprime[2][2]                    = {0.0};
-	double     DL_scalar;
-	GaussTria *gauss                            = NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all Inputs and parameters: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&stabilization,BalancethicknessStabilizationEnum);
-	this->parameters->FindParam(&dim,MeshDimensionEnum);
-	Input* vxaverage_input=NULL;
-	Input* vyaverage_input=NULL;
-	if(dim==2){
-		vxaverage_input=inputs->GetInput(VxEnum); _assert_(vxaverage_input);
-		vyaverage_input=inputs->GetInput(VyEnum); _assert_(vyaverage_input);
-	}
-	else{
-		vxaverage_input=inputs->GetInput(VxAverageEnum); _assert_(vxaverage_input);
-		vyaverage_input=inputs->GetInput(VyAverageEnum); _assert_(vyaverage_input);
-	}
-	h=sqrt(2*this->GetArea());
-
-	///*Create Artificial diffusivity once for all if requested*/
-	//if(stabilization){
-	//	gauss=new GaussTria();
-	//	gauss->GaussCenter();
-	//	GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-	//	delete gauss;
-
-	//	vxaverage_input->GetParameterAverage(&vx);
-	//	vyaverage_input->GetParameterAverage(&vy);
-	//	K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx);
-	//	K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy);
-	//}
-
-	/*Start looping on the number of gaussian points:*/
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
-		GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
-
-		vxaverage_input->GetParameterValue(&vx,gauss);
-		vyaverage_input->GetParameterValue(&vy,gauss);
-		vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
-		vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
-
-		dvxdx=dvx[0];
-		dvydy=dvy[1];
-		DL_scalar=gauss->weight*Jdettria;
-
-		DL[0][0]=DL_scalar*dvxdx;
-		DL[1][1]=DL_scalar*dvydy;
-
-		DLprime[0][0]=DL_scalar*vx;
-		DLprime[1][1]=DL_scalar*vy;
-
-		TripleMultiply( &B[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&B[0][0],2,numdof,0,
-					&Ke->values[0],1);
-
-		TripleMultiply( &B[0][0],2,numdof,1,
-					&DLprime[0][0],2,2,0,
-					&Bprime[0][0],2,numdof,0,
-					&Ke->values[0],1);
-
-		if(stabilization==1){
-			vel=sqrt(pow(vx,2.)+pow(vy,2.));
-			K[0][0]=h/(2*vel)*vx*vx;
-			K[1][0]=h/(2*vel)*vy*vx;
-			K[0][1]=h/(2*vel)*vx*vy;
-			K[1][1]=h/(2*vel)*vy*vy;
-			KDL[0][0]=DL_scalar*K[0][0];
-			KDL[1][0]=DL_scalar*K[1][0];
-			KDL[0][1]=DL_scalar*K[0][1];
-			KDL[1][1]=DL_scalar*K[1][1];
-
-			//KDL[0][0]=DL_scalar*K[0][0];
-			//KDL[1][1]=DL_scalar*K[1][1];
-
-			TripleMultiply( &Bprime[0][0],2,numdof,1,
-						&KDL[0][0],2,2,0,
-						&Bprime[0][0],2,numdof,0,
-						&Ke->values[0],1);
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixBalancethickness_DG {{{1*/
-ElementMatrix* Tria::CreateKMatrixBalancethickness_DG(void){
-
-	/*Constants*/
-	const int  numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries*/
-	int        i,j,ig,dim;
-	double     vx,vy,Jdettria;
-	double     xyz_list[NUMVERTICES][3];
-	double     B[2][NUMVERTICES];
-	double     Bprime[2][NUMVERTICES];
-	double     DL[2][2]={0.0};
-	double     DL_scalar;
-	GaussTria  *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&dim,MeshDimensionEnum);
-	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
-
-	/*Start looping on the number of gaussian points:*/
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		/*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
-		GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
-		GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);
-
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-
-		DL_scalar=-gauss->weight*Jdettria;
-		DL[0][0]=DL_scalar*vx;
-		DL[1][1]=DL_scalar*vy;
-
-		TripleMultiply( &B[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&Bprime[0][0],2,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/
-ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){
-
-	/*compute all stiffness matrices for this element*/
-	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous();
-	ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction();
-	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
-	
-	/*clean-up and return*/
-	delete Ke1;
-	delete Ke2;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/
-ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){
-
-	/*Constants*/
-	const int  numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries*/
-	int        i,j,ig;
-	double     xyz_list[NUMVERTICES][3];
-	double     viscosity,newviscosity,oldviscosity;
-	double     viscosity_overshoot,thickness,Jdet;
-	double     epsilon[3],oldepsilon[3];    /* epsilon=[exx,eyy,exy];    */
-	double     B[3][numdof];
-	double     Bprime[3][numdof];
-	double     D[3][3]   = {0.0};
-	double     D_scalar;
-	GaussTria *gauss = NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
-	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
-	Input* vxold_input=inputs->GetInput(VxPicardEnum);      _assert_(vxold_input);
-	Input* vyold_input=inputs->GetInput(VyPicardEnum);      _assert_(vyold_input);
-	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-		GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss);
-		GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss);
-
-		this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
-		this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
-		matice->GetViscosity2d(&viscosity, &epsilon[0]);
-		matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
-		thickness_input->GetParameterValue(&thickness, gauss);
-
-		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
-		D_scalar=2*newviscosity*thickness*gauss->weight*Jdet;
-		for (i=0;i<3;i++) D[i][i]=D_scalar;
-
-		TripleMultiply(&B[0][0],3,numdof,1,
-					&D[0][0],3,3,0,
-					&Bprime[0][0],3,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/
-ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){
-
-	/*Constants*/
-	const int  numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries*/
-	int        i,j,ig;
-	int        analysis_type;
-	double     MAXSLOPE  = .06; // 6 %
-	double     MOUNTAINKEXPONENT = 10;
-	double     slope_magnitude,alpha2;
-	double     Jdet;
-	double     L[2][numdof];
-	double     DL[2][2]  = {{ 0,0 },{0,0}};
-	double     DL_scalar;
-	double     slope[2]  = {0.0,0.0};
-	double     xyz_list[NUMVERTICES][3];
-	Friction  *friction = NULL;
-	GaussTria *gauss    = NULL;
-
-	/*Initialize Element matrix and return if necessary*/
-	if(IsOnShelf()) return NULL;
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
-	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-
-	/*build friction object, used later on: */
-	friction=new Friction("2d",inputs,matpar,analysis_type);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
-		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
-		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
-		if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT);
-		else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
-
-		GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-		DL_scalar=alpha2*gauss->weight*Jdet;
-		for (i=0;i<2;i++) DL[i][i]=DL_scalar;
-		
-		TripleMultiply( &L[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&L[0][0],2,numdof,0,
-					&Ke->values[0],1);
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
-ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){
-
-	/*Intermediaries*/
-	const int numdof=NUMVERTICES*NDOF2;
-	int    i,connectivity;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Create Element matrix*/
-	for(i=0;i<NUMVERTICES;i++){
-		connectivity=nodes[i]->GetConnectivity();
-		Ke->values[(2*i)*numdof  +(2*i)  ]=1/(double)connectivity;
-		Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity;
-	}
-
-	/*Clean up and return*/
-	return Ke;
-}
-/*}}}*/
-/*FUNCTION Tria::CreateKMatrixHydrology{{{1*/
-ElementMatrix* Tria::CreateKMatrixHydrology(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        artdiff;
-	int        i,j,ig;
-	double     Jdettria,DL_scalar,dt,h;
-	double     vx,vy,vel,dvxdx,dvydy;
-	double     dvx[2],dvy[2];
-	double     v_gauss[2]={0.0};
-	double     xyz_list[NUMVERTICES][3];
-	double     L[NUMVERTICES];
-	double     B[2][NUMVERTICES];
-	double     Bprime[2][NUMVERTICES];
-	double     K[2][2]                        ={0.0};
-	double     KDL[2][2]                      ={0.0};
-	double     DL[2][2]                        ={0.0};
-	double     DLprime[2][2]                   ={0.0};
-	GaussTria *gauss=NULL;
-
-	/*Initialize Element matrix*/
-	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
-
-	/*Create water velocity vx and vy from current inputs*/
-	CreateHydrologyWaterVelocityInput();
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	this->parameters->FindParam(&artdiff,HydrologyStabilizationEnum);
-	Input* vx_input=inputs->GetInput(HydrologyWaterVxEnum); _assert_(vx_input);
-	Input* vy_input=inputs->GetInput(HydrologyWaterVyEnum); _assert_(vy_input);
-	h=this->GetArea();
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
-
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
-		vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
-
-		DL_scalar=gauss->weight*Jdettria;
-
-		TripleMultiply( &L[0],1,numdof,1,
-					&DL_scalar,1,1,0,
-					&L[0],1,numdof,0,
-					&Ke->values[0],1);
-
-		GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
-		GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
-
-		dvxdx=dvx[0];
-		dvydy=dvy[1];
-		DL_scalar=dt*gauss->weight*Jdettria;
-
-		DL[0][0]=DL_scalar*dvxdx;
-		DL[1][1]=DL_scalar*dvydy;
-		DLprime[0][0]=DL_scalar*vx;
-		DLprime[1][1]=DL_scalar*vy;
-
-		TripleMultiply( &B[0][0],2,numdof,1,
-					&DL[0][0],2,2,0,
-					&B[0][0],2,numdof,0,
-					&Ke->values[0],1);
-
-		TripleMultiply( &B[0][0],2,numdof,1,
-					&DLprime[0][0],2,2,0,
-					&Bprime[0][0],2,numdof,0,
-					&Ke->values[0],1);
-
-		if(artdiff){
-			vel=sqrt(pow(vx,2.)+pow(vy,2.));
-			K[0][0]=h/(2*vel)*vx*vx;
-			K[1][0]=h/(2*vel)*vy*vx;
-			K[0][1]=h/(2*vel)*vx*vy;
-			K[1][1]=h/(2*vel)*vy*vy;
-			KDL[0][0]=DL_scalar*K[0][0];
-			KDL[1][0]=DL_scalar*K[1][0];
-			KDL[0][1]=DL_scalar*K[0][1];
-			KDL[1][1]=DL_scalar*K[1][1];
-
-			TripleMultiply( &Bprime[0][0],2,numdof,1,
-						&KDL[0][0],2,2,0,
-						&Bprime[0][0],2,numdof,0,
-						&Ke->values[0],1);
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Ke;
 }
 /*}}}*/
@@ -1247,4 +739,5 @@
 	/*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
 	switch(analysis_type){
+		#ifdef _HAVE_DIAGNOSTIC_
 		case DiagnosticHorizAnalysisEnum:
 			pe=CreatePVectorDiagnosticMacAyeal();
@@ -1253,4 +746,5 @@
 			pe=CreatePVectorDiagnosticHutter();
 			break;
+		#endif
 		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
 			pe=CreatePVectorSlope();
@@ -1259,10 +753,14 @@
 			pe=CreatePVectorPrognostic();
 			break;
+		#ifdef _HAVE_HYDROLOGY_
 		case HydrologyAnalysisEnum:
 			pe=CreatePVectorHydrology();
 			break;
+		#endif
+		#ifdef _HAVE_BALANCED_
 		case BalancethicknessAnalysisEnum:
 			pe=CreatePVectorBalancethickness();
 			break;
+		#endif
 		#ifdef _HAVE_CONTROL_
 		case AdjointBalancethicknessAnalysisEnum:
@@ -1284,205 +782,4 @@
 }
 /*}}}*/
-/*FUNCTION Tria::CreatePVectorBalancethickness{{{1*/
-ElementVector* Tria::CreatePVectorBalancethickness(void){
-
-	switch(GetElementType()){
-		case P1Enum:
-			return CreatePVectorBalancethickness_CG();
-			break;
-		case P1DGEnum:
-			return CreatePVectorBalancethickness_DG();
-		default:
-			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorBalancethickness_CG{{{1*/
-ElementVector* Tria::CreatePVectorBalancethickness_CG(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-	
-	/*Intermediaries */
-	int        i,j,ig;
-	double     xyz_list[NUMVERTICES][3];
-	double     dhdt_g,basal_melting_g,surface_mass_balance_g,Jdettria;
-	double     L[NUMVERTICES];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
-	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
-	Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);             _assert_(dhdt_input);
-	
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
-		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
-		dhdt_input->GetParameterValue(&dhdt_g,gauss);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
-
-		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorBalancethickness_DG {{{1*/
-ElementVector* Tria::CreatePVectorBalancethickness_DG(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     xyz_list[NUMVERTICES][3];
-	double     basal_melting_g,surface_mass_balance_g,dhdt_g,Jdettria;
-	double     L[NUMVERTICES];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
-	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
-	Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);                                       _assert_(dhdt_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
-		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
-		dhdt_input->GetParameterValue(&dhdt_g,gauss);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
-
-		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/
-ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){
-
-	/*Constants*/
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	/*Intermediaries */
-	int            i,j,ig;
-	double         driving_stress_baseline,thickness;
-	double         Jdet;
-	double         xyz_list[NUMVERTICES][3];
-	double         slope[2];
-	double         basis[3];
-	double         pe_g_gaussian[numdof];
-	GaussTria*     gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 
-	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
-	Input* drag_input=inputs->GetInput(FrictionCoefficientEnum);_assert_(drag_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctions(basis, gauss);
-
-		thickness_input->GetParameterValue(&thickness,gauss);
-		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-		driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
-
-		/*Build pe_g_gaussian vector: */
-		for (i=0;i<NUMVERTICES;i++){
-			for (j=0;j<NDOF2;j++){
-				pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
-			}
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
-ElementVector* Tria::CreatePVectorDiagnosticHutter(void){
-
-	/*Intermediaries */
-	int        i,connectivity;
-	double     constant_part,ub,vb;
-	double     rho_ice,gravity,n,B;
-	double     slope2,thickness;
-	double     slope[2];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	rho_ice=matpar->GetRhoIce();
-	gravity=matpar->GetG();
-	n=matice->GetN();
-	B=matice->GetBbar();
-	Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
-	Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
-
-	/*Spawn 3 sing elements: */
-	gauss=new GaussTria();
-	for(i=0;i<NUMVERTICES;i++){
-
-		gauss->GaussVertex(i);
-
-		connectivity=nodes[i]->GetConnectivity();
-
-		thickness_input->GetParameterValue(&thickness,gauss);
-		slopex_input->GetParameterValue(&slope[0],gauss);
-		slopey_input->GetParameterValue(&slope[1],gauss);
-		slope2=pow(slope[0],2)+pow(slope[1],2);
-
-		constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
-
-		ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0];
-		vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1];
-
-		pe->values[2*i]  =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity;
-		pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity;
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
 /*FUNCTION Tria::CreatePVectorPrognostic{{{1*/
 ElementVector* Tria::CreatePVectorPrognostic(void){
@@ -1496,50 +793,4 @@
 			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
 	}
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorHydrology {{{1*/
-ElementVector* Tria::CreatePVectorHydrology(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     Jdettria,dt;
-	double     basal_melting_g;
-	double     old_watercolumn_g;
-	double     xyz_list[NUMVERTICES][3];
-	double     basis[numdof];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
-	Input* old_watercolumn_input=inputs->GetInput(WaterColumnOldEnum);         _assert_(old_watercolumn_input);
-
-	/*Initialize basal_melting_correction_g to 0, do not forget!:*/
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for(ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
-		GetNodalFunctions(basis, gauss);
-
-		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
-		old_watercolumn_input->GetParameterValue(&old_watercolumn_g,gauss);
-
-		if(dt)for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(old_watercolumn_g+dt*basal_melting_g)*basis[i];
-		else  for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*basal_melting_g*basis[i];
-	}
-		
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
 }
 /*}}}*/
@@ -1993,13 +1244,1869 @@
 
 	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
-	if (analysis_type==DiagnosticHorizAnalysisEnum)
-	 GetSolutionFromInputsDiagnosticHoriz(solution);
-	else if (analysis_type==DiagnosticHutterAnalysisEnum)
-	 GetSolutionFromInputsDiagnosticHutter(solution);
-	else if (analysis_type==HydrologyAnalysisEnum)
-	 GetSolutionFromInputsHydrology(solution);
+	switch(analysis_type){
+	#ifdef _HAVE_DIAGNOSTIC_
+	case DiagnosticHorizAnalysisEnum:
+		GetSolutionFromInputsDiagnosticHoriz(solution);
+		break;
+	case DiagnosticHutterAnalysisEnum:
+		GetSolutionFromInputsDiagnosticHutter(solution);
+		break;
+	#endif
+	#ifdef _HAVE_HYDROLOGY_
+	case HydrologyAnalysisEnum:
+		GetSolutionFromInputsHydrology(solution);
+		break;
+	#endif
+	default:
+		_error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/
+void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){
+	/*Compute the 2d Strain Rate (3 components):
+	 * epsilon=[exx eyy exy] */
+
+	int i;
+	double epsilonvx[3];
+	double epsilonvy[3];
+
+	/*Check that both inputs have been found*/
+	if (!vx_input || !vy_input){
+		_error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);
+	}
+
+	/*Get strain rate assuming that epsilon has been allocated*/
+	vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss);
+	vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss);
+
+	/*Sum all contributions*/
+	for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
+}
+/*}}}*/
+/*FUNCTION Tria::GetVectorFromInputs{{{1*/
+void  Tria::GetVectorFromInputs(Vec vector,int input_enum){
+
+	int doflist1[NUMVERTICES];
+
+	/*Get out if this is not an element input*/
+	if (!IsInput(input_enum)) return;
+
+	/*Prepare index list*/
+	this->GetDofList1(&doflist1[0]);
+
+	/*Get input (either in element or material)*/
+	Input* input=inputs->GetInput(input_enum);
+	if(!input) _error_("Input %s not found in element",EnumToStringx(input_enum));
+
+	/*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
+	input->GetVectorFromInputs(vector,&doflist1[0]);
+}
+/*}}}*/
+/*FUNCTION Tria::Id {{{1*/
+int    Tria::Id(){
+	
+	return id;
+
+}
+/*}}}*/
+/*FUNCTION Tria::Sid {{{1*/
+int    Tria::Sid(){
+	
+	return sid;
+
+}
+/*}}}*/
+/*FUNCTION Tria::InputArtificialNoise{{{1*/
+void  Tria::InputArtificialNoise(int enum_type,double min,double max){
+
+	Input* input=NULL;
+
+	/*Make a copy of the original input: */
+	input=(Input*)this->inputs->GetInput(enum_type);
+	if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
+
+	/*ArtificialNoise: */
+	input->ArtificialNoise(min,max);
+}
+/*}}}*/
+/*FUNCTION Tria::InputConvergence{{{1*/
+bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
+
+	bool    converged=true;
+	int     i;
+	Input** new_inputs=NULL;
+	Input** old_inputs=NULL;
+
+	new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
+	old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
+
+	for(i=0;i<num_enums/2;i++){
+		new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
+		old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
+		if(!new_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
+		if(!old_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
+	}
+
+	/*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
+	for(i=0;i<num_criterionenums;i++){
+		IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
+		if(eps[i]>criterionvalues[i]) converged=false; 
+	}
+
+	/*clean up and return*/
+	xfree((void**)&new_inputs);
+	xfree((void**)&old_inputs);
+	return converged;
+}
+/*}}}*/
+/*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
+void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){
+
+	/*New input*/
+	Input* oldinput=NULL;
+	Input* newinput=NULL;
+
+	/*copy input of enum_type*/
+	if (object_enum==MeshElementsEnum)
+	 oldinput=(Input*)this->inputs->GetInput(enum_type);
+	else if (object_enum==MaterialsEnum)
+	 oldinput=(Input*)this->matice->inputs->GetInput(enum_type);
 	else
-	 _error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
-
+	 _error_("object %s not supported yet",EnumToStringx(object_enum));
+	if(!oldinput)_error_("%s%s"," could not find old input with enum: ",EnumToStringx(enum_type));
+	newinput=(Input*)oldinput->copy();
+
+	/*Assign new name (average)*/
+	newinput->ChangeEnum(average_enum_type);
+
+	/*Add new input to current element*/
+	if (object_enum==MeshElementsEnum)
+	 this->inputs->AddInput((Input*)newinput);
+	else if (object_enum==MaterialsEnum)
+	 this->matice->inputs->AddInput((Input*)newinput);
+	else
+	 _error_("object %s not supported yet",EnumToStringx(object_enum));
+}
+/*}}}*/
+/*FUNCTION Tria::InputDuplicate{{{1*/
+void  Tria::InputDuplicate(int original_enum,int new_enum){
+
+	/*Call inputs method*/
+	if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum);
+
+}
+/*}}}*/
+/*FUNCTION Tria::InputScale{{{1*/
+void  Tria::InputScale(int enum_type,double scale_factor){
+
+	Input* input=NULL;
+
+	/*Make a copy of the original input: */
+	input=(Input*)this->inputs->GetInput(enum_type);
+	if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
+
+	/*Scale: */
+	input->Scale(scale_factor);
+}
+/*}}}*/
+/*FUNCTION Tria::InputToResult{{{1*/
+void  Tria::InputToResult(int enum_type,int step,double time){
+
+	int    i;
+	Input *input = NULL;
+
+	/*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
+	if (enum_type==MaterialsRheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type);
+	else input=this->inputs->GetInput(enum_type);
+	if (!input) _error_("Input %s not found in tria->inputs",EnumToStringx(enum_type));
+
+	/*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result 
+	 * object out of the input, with the additional step and time information: */
+	this->results->AddObject((Object*)input->SpawnResult(step,time));
+	#ifdef _HAVE_CONTROL_
+	if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time));
+	#endif
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
+void  Tria::InputUpdateFromConstant(int constant, int name){
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+
+	/*update input*/
+	this->inputs->AddInput(new IntInput(name,constant));
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
+void  Tria::InputUpdateFromConstant(double constant, int name){
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+
+	/*update input*/
+	this->inputs->AddInput(new DoubleInput(name,constant));
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
+void  Tria::InputUpdateFromConstant(bool constant, int name){
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+
+	/*update input*/
+	this->inputs->AddInput(new BoolInput(name,constant));
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromIoModel{{{1*/
+void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index
+
+	/*Intermediaries*/
+	int    i,j;
+	int    tria_vertex_ids[3];
+	double nodeinputs[3];
+	double cmmininputs[3];
+	double cmmaxinputs[3];
+	bool   control_analysis=false;
+	int    num_control_type;
+	double yts;
+	int    num_cm_responses;
+   
+	/*Get parameters: */
+	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
+	iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);
+	iomodel->Constant(&yts,ConstantsYtsEnum); 
+	iomodel->Constant(&num_cm_responses,InversionNumCostFunctionsEnum);
+
+	/*Recover vertices ids needed to initialize inputs*/
+	for(i=0;i<3;i++){ 
+		tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
+	}
+
+	/*Control Inputs*/
+	#ifdef _HAVE_CONTROL_
+	if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
+		for(i=0;i<num_control_type;i++){
+			switch((int)iomodel->Data(InversionControlParametersEnum)[i]){
+				case BalancethicknessThickeningRateEnum:
+					if (iomodel->Data(BalancethicknessThickeningRateEnum)){
+						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(BalancethicknessThickeningRateEnum)[tria_vertex_ids[j]-1]/yts;
+						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						this->inputs->AddInput(new ControlInput(BalancethicknessThickeningRateEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
+					}
+					break;
+				case VxEnum:
+					if (iomodel->Data(VxEnum)){
+						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VxEnum)[tria_vertex_ids[j]-1]/yts;
+						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
+					}
+					break;
+				case VyEnum:
+					if (iomodel->Data(VyEnum)){
+						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VyEnum)[tria_vertex_ids[j]-1]/yts;
+						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
+						this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
+					}
+					break;
+				case FrictionCoefficientEnum:
+					if (iomodel->Data(FrictionCoefficientEnum)){
+						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(FrictionCoefficientEnum)[tria_vertex_ids[j]-1];
+						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
+						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
+						this->inputs->AddInput(new ControlInput(FrictionCoefficientEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
+					}
+					break;
+				case MaterialsRheologyBbarEnum:
+					/*Matice will take care of it*/ break;
+				default:
+					_error_("Control %s not implemented yet",EnumToStringx((int)iomodel->Data(InversionControlParametersEnum)[i]));
+			}
+		}
+	}
+	#endif
+
+	/*DatasetInputs*/
+	if (control_analysis && iomodel->Data(InversionCostFunctionsCoefficientsEnum)){
+
+		/*Create inputs and add to DataSetInput*/
+		DatasetInput* datasetinput=new DatasetInput(InversionCostFunctionsCoefficientsEnum);
+		for(i=0;i<num_cm_responses;i++){
+			for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(InversionCostFunctionsCoefficientsEnum)[(tria_vertex_ids[j]-1)*num_cm_responses+i];
+			datasetinput->inputs->AddObject(new TriaVertexInput(InversionCostFunctionsCoefficientsEnum,nodeinputs));
+		}
+
+		/*Add datasetinput to element inputs*/
+		this->inputs->AddInput(datasetinput);
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolution {{{1*/
+void  Tria::InputUpdateFromSolution(double* solution){
+
+	/*retrive parameters: */
+	int analysis_type;
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+
+	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
+	switch(analysis_type){
+		#ifdef _HAVE_DIAGNOSTIC_
+		case DiagnosticHorizAnalysisEnum:
+			InputUpdateFromSolutionDiagnosticHoriz( solution);
+			break;
+		case DiagnosticHutterAnalysisEnum:
+			InputUpdateFromSolutionDiagnosticHoriz( solution);
+			break;
+		#endif
+		#ifdef _HAVE_CONTROL_
+		case AdjointHorizAnalysisEnum:
+			InputUpdateFromSolutionAdjointHoriz( solution);
+			break;
+		case AdjointBalancethicknessAnalysisEnum:
+			InputUpdateFromSolutionAdjointBalancethickness( solution);
+			break;
+		#endif
+		#ifdef _HAVE_HYDROLOGY_ 
+		case HydrologyAnalysisEnum:
+			InputUpdateFromSolutionHydrology(solution);
+			break ;
+		#endif
+	 	#ifdef _HAVE_BALANCED_
+		case BalancethicknessAnalysisEnum:
+			InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
+			break;
+		#endif
+		case BedSlopeXAnalysisEnum:
+			InputUpdateFromSolutionOneDof(solution,BedSlopeXEnum);
+			break;
+		case BedSlopeYAnalysisEnum:
+			InputUpdateFromSolutionOneDof(solution,BedSlopeYEnum);
+			break;
+		case SurfaceSlopeXAnalysisEnum:
+			InputUpdateFromSolutionOneDof(solution,SurfaceSlopeXEnum);
+			break;
+		case SurfaceSlopeYAnalysisEnum:
+			InputUpdateFromSolutionOneDof(solution,SurfaceSlopeYEnum);
+			break;
+		case PrognosticAnalysisEnum:
+			InputUpdateFromSolutionPrognostic(solution);
+			break;
+		default:
+			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/
+void  Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){
+
+	const int numdof          = NDOF1*NUMVERTICES;
+
+	int*      doflist=NULL;
+	double    values[numdof];
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(int i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+		if(isnan(values[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Add input to the element: */
+	this->inputs->AddInput(new TriaVertexInput(enum_type,values));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolutionPrognostic{{{1*/
+void  Tria::InputUpdateFromSolutionPrognostic(double* solution){
+
+	/*Intermediaries*/
+	const int numdof = NDOF1*NUMVERTICES;
+
+	int       i,dummy,hydroadjustment;
+	int*      doflist=NULL;
+	double    rho_ice,rho_water;
+	double    values[numdof];
+	double    bed[numdof];
+	double    surface[numdof];
+	double    *bed_ptr = NULL;
+	double    *thickness_ptr = NULL;
+	double    *surface_ptr = NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+		if(isnan(values[i])) _error_("NaN found in solution vector");
+		/*Constrain thickness to be at least 1m*/
+		if(values[i]<1) values[i]=1;
+	}
+
+	/*Get previous bed, thickness and surface*/
+	Input* bed_input=inputs->GetInput(BedEnum);             _assert_(bed_input);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
+	bed_input->GetValuesPtr(&bed_ptr,&dummy);
+	thickness_input->GetValuesPtr(&thickness_ptr,&dummy);
+	surface_input->GetValuesPtr(&surface_ptr,&dummy);
+
+	/*Fing PrognosticHydrostaticAdjustment to figure out how to update the geometry:*/
+	this->parameters->FindParam(&hydroadjustment,PrognosticHydrostaticAdjustmentEnum);
+
+	/*recover material parameters: */
+	rho_ice=matpar->GetRhoIce();
+	rho_water=matpar->GetRhoWater();
+
+	for(i=0;i<numdof;i++) {
+		/*If shelf: hydrostatic equilibrium*/
+		if (this->nodes[i]->IsOnSheet()){
+			surface[i]=bed_ptr[i]+values[i]; //surface=oldbed+newthickness
+			bed[i]=bed_ptr[i]; //do nothing
+		}
+		else{ //this is an ice shelf
+
+			if(hydroadjustment==AbsoluteEnum){
+				surface[i]=values[i]*(1-rho_ice/rho_water);
+				bed[i]=values[i]*(-rho_ice/rho_water);
+			}
+			else if(hydroadjustment==IncrementalEnum){
+				surface[i]=surface_ptr[i]+(1.0-rho_ice/rho_water)*(values[i]-thickness_ptr[i]); //surface = oldsurface + (1-di) * dH 
+				bed[i]=bed_ptr[i]-rho_ice/rho_water*(values[i]-thickness_ptr[i]); //bed = oldbed + di * dH
+			}
+			else _error_("Hydrostatic adjustment %i (%s) not supported yet",hydroadjustment,EnumToStringx(hydroadjustment));
+		}
+	}
+
+	/*Add input to the element: */
+	this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
+	this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,surface));
+	this->inputs->AddInput(new TriaVertexInput(BedEnum,bed));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
+void  Tria::InputUpdateFromVector(double* vector, int name, int type){
+
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+
+	switch(type){
+
+		case VertexEnum:
+
+			/*New TriaVertexInput*/
+			double values[3];
+
+			/*Get values on the 3 vertices*/
+			for (int i=0;i<3;i++){
+				values[i]=vector[this->nodes[i]->GetVertexDof()];
+			}
+
+			/*update input*/
+			if (name==MaterialsRheologyBbarEnum || name==MaterialsRheologyBEnum){
+				matice->inputs->AddInput(new TriaVertexInput(name,values));
+			}
+			else{
+				this->inputs->AddInput(new TriaVertexInput(name,values));
+			}
+			return;
+
+		default:
+			_error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
+void  Tria::InputUpdateFromVector(int* vector, int name, int type){
+	_error_(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
+void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
+	_error_(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::InputCreate(double scalar,int enum,int code);{{{1*/
+void Tria::InputCreate(double scalar,int name,int code){
+
+	/*Check that name is an element input*/
+	if (!IsInput(name)) return;
+	
+	if ((code==5) || (code==1)){ //boolean
+		this->inputs->AddInput(new BoolInput(name,(bool)scalar));
+	}
+	else if ((code==6) || (code==2)){ //integer
+		this->inputs->AddInput(new IntInput(name,(int)scalar));
+	}
+	else if ((code==7) || (code==3)){ //double
+		this->inputs->AddInput(new DoubleInput(name,(int)scalar));
+	}
+	else _error_("%s%i"," could not recognize nature of vector from code ",code);
+
+}
+/*}}}*/
+/*FUNCTION Tria::InputCreate(double* vector,int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){{{1*/
+void Tria::InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){//index into elements
+
+	/*Intermediaries*/
+	int    i,j,t;
+	int    tria_vertex_ids[3];
+	int    row;
+	double nodeinputs[3];
+	double time;
+	TransientInput* transientinput=NULL;
+	int    numberofvertices;
+	int    numberofelements;
+	double yts;
+
+
+	/*Fetch parameters: */
+	iomodel->Constant(&numberofvertices,MeshNumberofverticesEnum);
+	iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
+	iomodel->Constant(&yts,ConstantsYtsEnum);
+
+	/*Branch on type of vector: nodal or elementary: */
+	if(vector_type==1){ //nodal vector
+
+		/*Recover vertices ids needed to initialize inputs*/
+		for(i=0;i<3;i++){ 
+			tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
+		}
+
+		/*Are we in transient or static? */
+		if(M==numberofvertices){
+
+			/*create input values: */
+			for(i=0;i<3;i++)nodeinputs[i]=(double)vector[tria_vertex_ids[i]-1];
+
+			/*process units: */
+			UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
+
+			/*create static input: */
+			this->inputs->AddInput(new TriaVertexInput(vector_enum,nodeinputs));
+		}
+		else if(M==numberofvertices+1){
+			/*create transient input: */
+			for(t=0;t<N;t++){ //N is the number of times
+
+				/*create input values: */
+				for(i=0;i<3;i++){
+					row=tria_vertex_ids[i]-1;
+					nodeinputs[i]=(double)vector[N*row+t];
+				}
+
+				/*process units: */
+				UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
+
+				/*time? :*/
+				time=(double)vector[(M-1)*N+t]*yts;
+
+				if(t==0) transientinput=new TransientInput(vector_enum);
+				transientinput->AddTimeInput(new TriaVertexInput(vector_enum,nodeinputs),time);
+			}
+			this->inputs->AddInput(transientinput);
+		}
+		else _error_("nodal vector is either numberofnodes (%i), or numberofnodes+1 long. Field provided is %i long",numberofvertices,M);
+	}
+	else if(vector_type==2){ //element vector
+		/*Are we in transient or static? */
+		if(M==numberofelements){
+
+			/*static mode: create an input out of the element value: */
+
+			if (code==5){ //boolean
+				this->inputs->AddInput(new BoolInput(vector_enum,(bool)vector[index]));
+			}
+			else if (code==6){ //integer
+				this->inputs->AddInput(new IntInput(vector_enum,(int)vector[index]));
+			}
+			else if (code==7){ //double
+				this->inputs->AddInput(new DoubleInput(vector_enum,(double)vector[index]));
+			}
+			else _error_("%s%i"," could not recognize nature of vector from code ",code);
+		}
+		else {
+			_error_("transient elementary inputs not supported yet!");
+		}
+	}
+	else{
+		_error_("Cannot add input for vector type %i (not supported)",vector_type);
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::IsInput{{{1*/
+bool Tria::IsInput(int name){
+	if (
+				name==ThicknessEnum ||
+				name==SurfaceEnum ||
+				name==BedEnum ||
+				name==SurfaceSlopeXEnum ||
+				name==SurfaceSlopeYEnum ||
+				name==BasalforcingsMeltingRateEnum ||
+				name==WatercolumnEnum || 
+				name==SurfaceforcingsMassBalanceEnum ||
+				name==SurfaceAreaEnum||
+				name==VxEnum ||
+				name==VyEnum ||
+				name==InversionVxObsEnum ||
+				name==InversionVyObsEnum ||
+				name==FrictionCoefficientEnum ||
+				name==GradientEnum ||
+				name==OldGradientEnum
+		){
+		return true;
+	}
+	else return false;
+}
+/*}}}*/
+/*FUNCTION Tria::IsOnBed {{{1*/
+bool Tria::IsOnBed(){
+	
+	bool onbed;
+	inputs->GetParameterValue(&onbed,MeshElementonbedEnum);
+	return onbed;
+}
+/*}}}*/
+/*FUNCTION Tria::IsOnShelf {{{1*/
+bool   Tria::IsOnShelf(){
+
+	bool shelf;
+	inputs->GetParameterValue(&shelf,MaskElementonfloatingiceEnum);
+	return shelf;
+}
+/*}}}*/
+/*FUNCTION Tria::IsNodeOnShelf {{{1*/
+bool   Tria::IsNodeOnShelf(){
+
+	int  i;
+	bool shelf=false;
+
+	for(i=0;i<3;i++){
+		if (nodes[i]->IsOnShelf()){
+			shelf=true;
+			break;
+		}
+	}
+	return shelf;
+}
+/*}}}*/
+/*FUNCTION Tria::IsNodeOnShelfFromFlags {{{1*/
+bool   Tria::IsNodeOnShelfFromFlags(double* flags){
+
+	int  i;
+	bool shelf=false;
+
+	for(i=0;i<3;i++){
+		if (flags[nodes[i]->Sid()]){
+			shelf=true;
+			break;
+		}
+	}
+	return shelf;
+}
+/*}}}*/
+/*FUNCTION Tria::IsOnWater {{{1*/
+bool   Tria::IsOnWater(){
+
+	bool water;
+	inputs->GetParameterValue(&water,MaskElementonwaterEnum);
+	return water;
+}
+/*}}}*/
+/*FUNCTION Tria::MassFlux {{{1*/
+double Tria::MassFlux( double* segment,bool process_units){
+
+	const int    numdofs=2;
+
+	int        i;
+	double     mass_flux=0;
+	double     xyz_list[NUMVERTICES][3];
+	double     normal[2];
+	double     length,rho_ice;
+	double     x1,y1,x2,y2,h1,h2;
+	double     vx1,vx2,vy1,vy2;
+	GaussTria* gauss_1=NULL;
+	GaussTria* gauss_2=NULL;
+
+	/*Get material parameters :*/
+	rho_ice=matpar->GetRhoIce();
+
+	/*First off, check that this segment belongs to this element: */
+	if ((int)*(segment+4)!=this->id)_error_("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id);
+
+	/*Recover segment node locations: */
+	x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3);
+
+	/*Get xyz list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*get area coordinates of 0 and 1 locations: */
+	gauss_1=new GaussTria();
+	gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]);
+	gauss_2=new GaussTria();
+	gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]);
+
+	normal[0]=cos(atan2(x1-x2,y2-y1));
+	normal[1]=sin(atan2(x1-x2,y2-y1));
+
+	length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2));
+
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
+
+	thickness_input->GetParameterValue(&h1, gauss_1);
+	thickness_input->GetParameterValue(&h2, gauss_2);
+	vx_input->GetParameterValue(&vx1,gauss_1);
+	vx_input->GetParameterValue(&vx2,gauss_2);
+	vy_input->GetParameterValue(&vy1,gauss_1);
+	vy_input->GetParameterValue(&vy2,gauss_2);
+
+	mass_flux= rho_ice*length*(  
+				(ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+
+				(ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1]
+				);
+
+	/*Process units: */
+	mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum);
+
+	/*clean up and return:*/
+	delete gauss_1;
+	delete gauss_2;
+	return mass_flux;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxAbsVx{{{1*/
+void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
+
+	/*Get maximum:*/
+	double maxabsvx=this->inputs->MaxAbs(VxEnum);
+
+	/*process units if requested: */
+	if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum);
+
+	/*Assign output pointers:*/
+	*pmaxabsvx=maxabsvx;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxAbsVy{{{1*/
+void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
+
+	/*Get maximum:*/
+	double maxabsvy=this->inputs->MaxAbs(VyEnum);
+
+	/*process units if requested: */
+	if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum);
+
+	/*Assign output pointers:*/
+	*pmaxabsvy=maxabsvy;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxAbsVz{{{1*/
+void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
+
+	/*Get maximum:*/
+	double maxabsvz=this->inputs->MaxAbs(VzEnum);
+
+	/*process units if requested: */
+	if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum);
+
+	/*Assign output pointers:*/
+	*pmaxabsvz=maxabsvz;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxVel{{{1*/
+void  Tria::MaxVel(double* pmaxvel, bool process_units){
+
+	/*Get maximum:*/
+	double maxvel=this->inputs->Max(VelEnum);
+
+	/*process units if requested: */
+	if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum);
+
+	/*Assign output pointers:*/
+	*pmaxvel=maxvel;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxVx{{{1*/
+void  Tria::MaxVx(double* pmaxvx, bool process_units){
+
+	/*Get maximum:*/
+	double maxvx=this->inputs->Max(VxEnum);
+
+	/*process units if requested: */
+	if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum);
+
+	/*Assign output pointers:*/
+	*pmaxvx=maxvx;
+}
+/*}}}*/
+/*FUNCTION Tria::MaxVy{{{1*/
+void  Tria::MaxVy(double* pmaxvy, bool process_units){
+
+	/*Get maximum:*/
+	double maxvy=this->inputs->Max(VyEnum);
+
+	/*process units if requested: */
+	if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum);
+
+	/*Assign output pointers:*/
+	*pmaxvy=maxvy;
+
+}
+/*}}}*/
+/*FUNCTION Tria::MaxVz{{{1*/
+void  Tria::MaxVz(double* pmaxvz, bool process_units){
+
+	/*Get maximum:*/
+	double maxvz=this->inputs->Max(VzEnum);
+
+	/*process units if requested: */
+	if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum);
+
+	/*Assign output pointers:*/
+	*pmaxvz=maxvz;
+}
+/*}}}*/
+/*FUNCTION Tria::MigrateGroundingLine{{{1*/
+void  Tria::MigrateGroundingLine(void){
+
+
+	double *values         = NULL;
+	double  h[3],s[3],b[3],ba[3];
+	double  bed_hydro;
+	double  rho_water,rho_ice,density;
+	int     isonshelf[3];
+	int     i;
+	bool    elementonshelf = false;
+
+
+	/*Recover info at the vertices: */
+	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
+	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+	for(i=0;i<3;i++){
+		isonshelf[i]=nodes[i]->IsOnShelf();
+		if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
+	}
+
+	/*material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	density=rho_ice/rho_water;
+
+	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
+	for(i=0;i<3;i++){
+		if (isonshelf[i]){
+			/*This node is on the shelf. See if its bed is going under the bathymetry: */
+			if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
+				/*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
+				b[i]=ba[i];
+				s[i]=b[i]+h[i];
+				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+			else{
+				/*do nothing, we are still floating.*/
+				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+		}
+		else{
+			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
+			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
+			bed_hydro=-density*h[i];
+			if (bed_hydro>ba[i]){
+				/*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
+				s[i]=(1-density)*h[i];
+				b[i]=-density*h[i];
+				printf("%i\n",nodes[i]->Sid()+1);
+				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+			else{
+				/*do nothing, we are still grounded.*/
+				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still grounded %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+		}
+	}
+
+	/*Surface and bed are updated. Update inputs:*/
+	surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
+	bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
+	
+	for(i=0;i<3;i++){
+		isonshelf[i]=nodes[i]->IsOnShelf();
+		if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i second shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::MinVel{{{1*/
+void  Tria::MinVel(double* pminvel, bool process_units){
+
+	/*Get minimum:*/
+	double minvel=this->inputs->Min(VelEnum);
+
+	/*process units if requested: */
+	if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum);
+
+	/*Assign output pointers:*/
+	*pminvel=minvel;
+}
+/*}}}*/
+/*FUNCTION Tria::MinVx{{{1*/
+void  Tria::MinVx(double* pminvx, bool process_units){
+
+	/*Get minimum:*/
+	double minvx=this->inputs->Min(VxEnum);
+
+	/*process units if requested: */
+	if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum);
+
+	/*Assign output pointers:*/
+	*pminvx=minvx;
+}
+/*}}}*/
+/*FUNCTION Tria::MinVy{{{1*/
+void  Tria::MinVy(double* pminvy, bool process_units){
+
+	/*Get minimum:*/
+	double minvy=this->inputs->Min(VyEnum);
+
+	/*process units if requested: */
+	if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum);
+
+	/*Assign output pointers:*/
+	*pminvy=minvy;
+}
+/*}}}*/
+/*FUNCTION Tria::MinVz{{{1*/
+void  Tria::MinVz(double* pminvz, bool process_units){
+
+	/*Get minimum:*/
+	double minvz=this->inputs->Min(VzEnum);
+
+	/*process units if requested: */
+	if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum);
+
+	/*Assign output pointers:*/
+	*pminvz=minvz;
+}
+/*}}}*/
+/*FUNCTION Tria::MyRank {{{1*/
+int    Tria::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Tria::NodalValue {{{1*/
+int    Tria::NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units){
+
+	int i;
+	int found=0;
+	double value;
+	Input* data=NULL;
+	GaussTria *gauss                            = NULL;
+
+	/*First, serarch the input: */
+	data=inputs->GetInput(natureofdataenum); 
+
+	/*figure out if we have the vertex id: */
+	found=0;
+	for(i=0;i<NUMVERTICES;i++){
+		if(index==nodes[i]->GetVertexId()){
+			/*Do we have natureofdataenum in our inputs? :*/
+			if(data){
+				/*ok, we are good. retrieve value of input at vertex :*/
+				gauss=new GaussTria(); gauss->GaussVertex(i);
+				data->GetParameterValue(&value,gauss);
+				found=1;
+				break;
+			}
+		}
+	}
+
+	if(found)*pvalue=value;
+	return found;
+}
+/*}}}*/
+/*FUNCTION Tria::PatchFill{{{1*/
+void  Tria::PatchFill(int* prow, Patch* patch){
+
+	int i,row;
+	int vertices_ids[3];
+
+	/*recover pointer: */
+	row=*prow;
+		
+	for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
+
+	for(i=0;i<this->results->Size();i++){
+		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
+
+		/*For this result,fill the information in the Patch object (element id + vertices ids), and then hand 
+		 *it to the result object, to fill the rest: */
+		patch->fillelementinfo(row,this->sid+1,vertices_ids,3);
+		elementresult->PatchFill(row,patch);
+
+		/*increment rower: */
+		row++;
+	}
+
+	/*Assign output pointers:*/
+	*prow=row;
+}
+/*}}}*/
+/*FUNCTION Tria::PatchSize{{{1*/
+void  Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
+
+	int     i;
+	int     numrows     = 0;
+	int     numnodes    = 0;
+	int     temp_numnodes    = 0;
+
+	/*Go through all the results objects, and update the counters: */
+	for (i=0;i<this->results->Size();i++){
+		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
+		/*first, we have one more result: */
+		numrows++;
+		/*now, how many vertices and how many nodal values for this result? :*/
+		temp_numnodes=elementresult->NumberOfNodalValues(); //ask result object.
+		if(temp_numnodes>numnodes)numnodes=temp_numnodes;
+	}
+
+	/*Assign output pointers:*/
+	*pnumrows=numrows;
+	*pnumvertices=NUMVERTICES;
+	*pnumnodes=numnodes;
+}
+/*}}}*/
+/*FUNCTION Tria::PotentialSheetUngrounding{{{1*/
+void  Tria::PotentialSheetUngrounding(Vec potential_sheet_ungrounding){
+
+
+	double *values         = NULL;
+	double  h[3],s[3],b[3],ba[3];
+	double  bed_hydro;
+	double  rho_water,rho_ice,density;
+	int     i;
+	bool    elementonshelf = false;
+
+	/*Recover info at the vertices: */
+	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
+	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+
+	/*material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	density=rho_ice/rho_water;
+
+	/*go through vertices, and figure out which ones are on the ice sheet, and want to unground: */
+	for(i=0;i<3;i++){
+		if (!nodes[i]->IsOnShelf()){
+			
+			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
+			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
+			bed_hydro=-density*h[i];
+			if (bed_hydro>ba[i]){
+				/*ok, this node wants to unground. flag it: */
+				VecSetValue(potential_sheet_ungrounding,nodes[i]->Sid(),1,INSERT_VALUES);
+			}
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::ProcessResultsUnits{{{1*/
+void  Tria::ProcessResultsUnits(void){
+
+	int i;
+
+	for(i=0;i<this->results->Size();i++){
+		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
+		elementresult->ProcessUnits(this->parameters);
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::RheologyBbarx{{{1*/
+double Tria::RheologyBbarx(void){
+
+	return this->matice->GetBbar();
+
+}
+/*}}}*/
+/*FUNCTION Tria::RequestedOutput{{{1*/
+void Tria::RequestedOutput(int output_enum,int step,double time){
+
+	if(IsInput(output_enum)){
+		/*just transfer this input to results, and we are done: */
+		InputToResult(output_enum,step,time);
+	}
+	else{
+		/*this input does not exist, compute it, and then transfer to results: */
+		switch(output_enum){
+			default:
+				/*do nothing, no need to derail the computation because one of the outputs requested cannot be found: */
+				break;
+		}
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::SetClone {{{1*/
+void  Tria::SetClone(int* minranks){
+
+	_error_("not implemented yet");
+}
+/*}}}1*/
+/*FUNCTION Tria::SetCurrentConfiguration {{{1*/
+void  Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
+	
+	/*go into parameters and get the analysis_counter: */
+	int analysis_counter;
+	parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
+
+	/*Get Element type*/
+	this->element_type=this->element_type_list[analysis_counter];
+
+	/*Pick up nodes*/
+	if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
+	else this->nodes=NULL;
+
+}
+/*}}}*/
+/*FUNCTION Tria::ShelfSync{{{1*/
+void  Tria::ShelfSync(void){
+
+
+	double *values         = NULL;
+	double  h[3],s[3],b[3],ba[3];
+	double  bed_hydro;
+	double  rho_water,rho_ice,density;
+	int     i;
+	bool    elementonshelf = false;
+
+	/*melting rate at the grounding line: */
+	double  yts;
+	int     swap;
+	double  gl_melting_rate;
+
+	/*recover parameters: */
+	parameters->FindParam(&yts,ConstantsYtsEnum);
+	parameters->FindParam(&gl_melting_rate,GroundinglineMeltingRateEnum);
+
+	/*Recover info at the vertices: */
+	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
+	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+
+	/*material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	density=rho_ice/rho_water;
+
+	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
+	for(i=0;i<3;i++){
+		if(b[i]==ba[i]){
+				
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
+		}
+		else{
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
+
+		}
+	}
+
+	/*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
+	swap=0;
+	elementonshelf=false;
+	for(i=0;i<3;i++){
+		if(nodes[i]->IsOnShelf()){
+			elementonshelf=true;
+			break;
+		}
+	}
+	if(!this->IsOnShelf() && elementonshelf==true)swap=1;
+    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
+	
+    /*If this element just  became ungrounded, set its basal melting rate at 50 m/yr:*/
+	if(swap){
+		Input* basal_melting_rate_input     =inputs->GetInput(BasalforcingsMeltingRateEnum);     _assert_(basal_melting_rate_input);
+		basal_melting_rate_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=gl_melting_rate/yts;
+	}
+
+
+}
+/*}}}*/
+/*FUNCTION Tria::SoftMigration{{{1*/
+void  Tria::SoftMigration(double* sheet_ungrounding){
+
+
+	double *values         = NULL;
+	double  h[3],s[3],b[3],ba[3];
+	double  bed_hydro;
+	double  rho_water,rho_ice,density;
+	int     i;
+	bool    elementonshelf = false;
+
+	/*Recover info at the vertices: */
+	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
+	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+
+	/*material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	density=rho_ice/rho_water;
+	
+	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
+	for(i=0;i<3;i++){
+		if (nodes[i]->IsOnShelf()){
+			/*This node is on the shelf. See if its bed is going under the bathymetry: */
+			if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
+				/*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
+				b[i]=ba[i];
+				s[i]=b[i]+h[i];
+			}
+			else{
+				/*do nothing, we are still floating.*/
+			}
+		}
+		else{
+			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
+			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
+			bed_hydro=-density*h[i];
+			if (bed_hydro>ba[i]){
+
+				/*Now, are we connected to the grounding line, if so, go forward, otherwise, bail out: */
+				if(sheet_ungrounding[nodes[i]->Sid()]){
+					/*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
+					s[i]=(1-density)*h[i];
+					b[i]=-density*h[i];
+				}
+			}
+			else{
+				/*do nothing, we are still grounded.*/
+			}
+		}
+	}
+
+	/*Surface and bed are updated. Update inputs:*/    
+	surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
+	bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
+
+	}
+/*}}}*/
+/*FUNCTION Tria::SurfaceArea {{{1*/
+double Tria::SurfaceArea(void){
+
+	int    i;
+	double S;
+	double normal[3];
+	double v13[3],v23[3];
+	double xyz_list[NUMVERTICES][3];
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	for (i=0;i<3;i++){
+		v13[i]=xyz_list[0][i]-xyz_list[2][i];
+		v23[i]=xyz_list[1][i]-xyz_list[2][i];
+	}
+
+	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
+	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
+	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
+
+	S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
+
+	/*Return: */
+	return S;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceNormal{{{1*/
+void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
+
+	int i;
+	double v13[3],v23[3];
+	double normal[3];
+	double normal_norm;
+
+	for (i=0;i<3;i++){
+		v13[i]=xyz_list[0][i]-xyz_list[2][i];
+		v23[i]=xyz_list[1][i]-xyz_list[2][i];
+	}
+
+	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
+	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
+	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
+
+	normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
+
+	*(surface_normal)=normal[0]/normal_norm;
+	*(surface_normal+1)=normal[1]/normal_norm;
+	*(surface_normal+2)=normal[2]/normal_norm;
+}
+/*}}}*/
+/*FUNCTION Tria::TimeAdapt{{{1*/
+double  Tria::TimeAdapt(void){
+
+	/*intermediary: */
+	int    i;
+	double C,dt;
+	double dx,dy;
+	double maxx,minx;
+	double maxy,miny;
+	double maxabsvx,maxabsvy;
+	double xyz_list[NUMVERTICES][3];
+
+	/*get CFL coefficient:*/
+	this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
+
+	/*Get for Vx and Vy, the max of abs value: */
+	this->MaxAbsVx(&maxabsvx,false);
+	this->MaxAbsVy(&maxabsvy,false);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES);
+
+	minx=xyz_list[0][0];
+	maxx=xyz_list[0][0];
+	miny=xyz_list[0][1];
+	maxy=xyz_list[0][1];
+
+	for(i=1;i<NUMVERTICES;i++){
+		if (xyz_list[i][0]<minx)minx=xyz_list[i][0];
+		if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0];
+		if (xyz_list[i][1]<miny)miny=xyz_list[i][1];
+		if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1];
+	}
+	dx=maxx-minx;
+	dy=maxy-miny;
+
+	/*CFL criterion: */
+	dt=C/(maxabsvy/dx+maxabsvy/dy);
+
+	return dt;
+}
+/*}}}*/
+/*FUNCTION Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
+void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
+
+	/*Intermediaries*/
+	int    i,j;
+	int    tria_node_ids[3];
+	int    tria_vertex_ids[3];
+	int    tria_type;
+	double nodeinputs[3];
+	double yts;
+	int    progstabilization,balancestabilization;
+	bool   dakota_analysis;
+
+	/*Checks if debuging*/
+	/*{{{2*/
+	_assert_(iomodel->Data(MeshElementsEnum));
+	/*}}}*/
+
+	/*Fetch parameters: */
+	iomodel->Constant(&yts,ConstantsYtsEnum);
+	iomodel->Constant(&progstabilization,PrognosticStabilizationEnum);
+	iomodel->Constant(&balancestabilization,BalancethicknessStabilizationEnum);
+	iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
+
+	/*Recover element type*/
+	if ((analysis_type==PrognosticAnalysisEnum && progstabilization==3) || (analysis_type==BalancethicknessAnalysisEnum && balancestabilization==3)){
+		/*P1 Discontinuous Galerkin*/
+		tria_type=P1DGEnum;
+	}
+	else{
+		/*P1 Continuous Galerkin*/
+		tria_type=P1Enum;
+	}
+	this->SetElementType(tria_type,analysis_counter);
+
+	/*Recover vertices ids needed to initialize inputs*/
+	for(i=0;i<3;i++){ 
+		tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
+	}
+
+	/*Recover nodes ids needed to initialize the node hook.*/
+	if (tria_type==P1DGEnum){
+		/*Discontinuous Galerkin*/
+		tria_node_ids[0]=iomodel->nodecounter+3*index+1;
+		tria_node_ids[1]=iomodel->nodecounter+3*index+2;
+		tria_node_ids[2]=iomodel->nodecounter+3*index+3;
+	}
+	else{
+		/*Continuous Galerkin*/
+		for(i=0;i<3;i++){ 
+			tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->Data(MeshElementsEnum)+3*index+i); //ids for vertices are in the elements array from Matlab
+		}
+	}
+
+	/*hooks: */
+	this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
+
+	/*Fill with IoModel*/
+	this->InputUpdateFromIoModel(index,iomodel);
+
+	/*Defaults if not provided in iomodel*/
+	switch(analysis_type){
+
+		case DiagnosticHorizAnalysisEnum:
+
+			/*default vx,vy and vz: either observation or 0 */
+			if(!iomodel->Data(VxEnum)){
+				if (iomodel->Data(InversionVxObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVxObsEnum)[tria_vertex_ids[i]-1]/yts;
+				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
+				this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
+				this->inputs->AddInput(new TriaVertexInput(VxPicardEnum,nodeinputs));
+				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs));
+			}
+			if(!iomodel->Data(VyEnum)){
+				if (iomodel->Data(InversionVyObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVyObsEnum)[tria_vertex_ids[i]-1]/yts;
+				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
+				this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
+				this->inputs->AddInput(new TriaVertexInput(VyPicardEnum,nodeinputs));
+				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs));
+			}
+			if(!iomodel->Data(VzEnum)){
+				if (iomodel->Data(InversionVzObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVzObsEnum)[tria_vertex_ids[i]-1]/yts;
+				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
+				this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
+				this->inputs->AddInput(new TriaVertexInput(VzPicardEnum,nodeinputs));
+				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs));
+			}
+			if(!iomodel->Data(PressureEnum)){
+				for(i=0;i<3;i++)nodeinputs[i]=0;
+				if(dakota_analysis){
+					this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
+					this->inputs->AddInput(new TriaVertexInput(QmuPressureEnum,nodeinputs));
+				}
+			}
+			break;
+
+		default:
+			/*No update for other solution types*/
+			break;
+
+	}
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateShelfStatus{{{1*/
+int  Tria::UpdateShelfStatus(Vec new_shelf_nodes){
+
+	int     i;
+
+	double  h[3];
+	double  s[3];
+	double  b[3];
+	double  ba[3];
+	Input  *surface_input  = NULL;
+	Input  *bed_input      = NULL;
+	double  rho_water;
+	double  rho_ice;
+	double  density;
+	bool    elementonshelf = false;
+	int     flipped=0;
+	int     shelfstatus[3];
+
+
+	/*Recover info at the vertices: */
+	surface_input   =inputs->GetInput(SurfaceEnum);   _assert_(surface_input);
+	bed_input   =inputs->GetInput(BedEnum);   _assert_(bed_input);
+	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+
+	/*material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	density=rho_ice/rho_water;
+
+	/*Initialize current status of nodes: */
+	for(i=0;i<3;i++){
+		shelfstatus[i]=nodes[i]->IsOnShelf();
+		if((nodes[i]->Sid()+1)==36) printf("UpdateShelfStatus: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,shelfstatus[i]);
+	}
+	
+	/*go through vertices, and figure out if they are grounded or not, then update their status: */
+	flipped=0;
+	for(i=0;i<3;i++){
+		if(b[i]<=ba[i]){ //the = will lead to oscillations.
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
+			if(shelfstatus[i]){
+				flipped++;
+				if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+			VecSetValue(new_shelf_nodes,nodes[i]->Sid(),0,INSERT_VALUES);
+		}
+		else{
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
+			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
+			if(!shelfstatus[i]){
+				flipped++;
+				if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
+			}
+			VecSetValue(new_shelf_nodes,nodes[i]->Sid(),1,INSERT_VALUES);
+		}
+	}
+
+	/*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
+	elementonshelf=false;
+	for(i=0;i<3;i++){
+		if(nodes[i]->IsOnShelf()){
+			elementonshelf=true;
+			break;
+		}
+	}
+    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
+
+	 return flipped;
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateShelfFlags{{{1*/
+void Tria::UpdateShelfFlags(double* new_shelf_nodes){
+
+	/*go through vertices, and update the status of MaskVertexonfloatingiceEnum and MaskVertexongroundediceEnum flags: */
+	bool flag;
+	int  i;
+	double  h[3];
+	double  s[3];
+	double  b[3];
+	double  ba[3];
+
+	GetParameterListOnVertices(&h[0],ThicknessEnum);
+	GetParameterListOnVertices(&s[0],SurfaceEnum);
+	GetParameterListOnVertices(&b[0],BedEnum);
+	GetParameterListOnVertices(&ba[0],BathymetryEnum);
+
+	for(i=0;i<3;i++){
+		flag=(bool)new_shelf_nodes[nodes[i]->Sid()];
+		nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,flag));
+		nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,!flag));
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::UpdatePotentialSheetUngrounding{{{1*/
+int Tria::UpdatePotentialSheetUngrounding(double* potential_sheet_ungrounding,Vec vec_nodes_on_iceshelf,double* nodes_on_iceshelf){
+
+	/*intermediary: */
+	int i;
+	int nflipped=0;
+
+	/*Ok, go through our 3 nodes, and whoever is on the potential_sheet_ungrounding, ends up in nodes_on_iceshelf: */
+	for(i=0;i<3;i++){
+		if (potential_sheet_ungrounding[nodes[i]->Sid()]){
+			VecSetValue(vec_nodes_on_iceshelf,nodes[i]->Sid(),1,INSERT_VALUES);
+		
+			/*Figure out if we flipped: */
+			if (potential_sheet_ungrounding[nodes[i]->Sid()] != nodes_on_iceshelf[nodes[i]->Sid()])nflipped++;
+		}
+	}
+	return nflipped;
+}
+/*}}}*/
+
+#ifdef _HAVE_DIAGNOSTIC_
+/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyeal {{{1*/
+ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyeal(void){
+
+	/*compute all stiffness matrices for this element*/
+	ElementMatrix* Ke1=CreateKMatrixDiagnosticMacAyealViscous();
+	ElementMatrix* Ke2=CreateKMatrixDiagnosticMacAyealFriction();
+	ElementMatrix* Ke =new ElementMatrix(Ke1,Ke2);
+	
+	/*clean-up and return*/
+	delete Ke1;
+	delete Ke2;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealViscous{{{1*/
+ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealViscous(void){
+
+	/*Constants*/
+	const int  numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries*/
+	int        i,j,ig;
+	double     xyz_list[NUMVERTICES][3];
+	double     viscosity,newviscosity,oldviscosity;
+	double     viscosity_overshoot,thickness,Jdet;
+	double     epsilon[3],oldepsilon[3];    /* epsilon=[exx,eyy,exy];    */
+	double     B[3][numdof];
+	double     Bprime[3][numdof];
+	double     D[3][3]   = {0.0};
+	double     D_scalar;
+	GaussTria *gauss = NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+	Input* vx_input=inputs->GetInput(VxEnum);               _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);               _assert_(vy_input);
+	Input* vxold_input=inputs->GetInput(VxPicardEnum);      _assert_(vxold_input);
+	Input* vyold_input=inputs->GetInput(VyPicardEnum);      _assert_(vyold_input);
+	this->parameters->FindParam(&viscosity_overshoot,DiagnosticViscosityOvershootEnum);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+		GetBMacAyeal(&B[0][0], &xyz_list[0][0], gauss);
+		GetBprimeMacAyeal(&Bprime[0][0], &xyz_list[0][0], gauss);
+
+		this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
+		this->GetStrainRate2d(&oldepsilon[0],&xyz_list[0][0],gauss,vxold_input,vyold_input);
+		matice->GetViscosity2d(&viscosity, &epsilon[0]);
+		matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
+		thickness_input->GetParameterValue(&thickness, gauss);
+
+		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+		D_scalar=2*newviscosity*thickness*gauss->weight*Jdet;
+		for (i=0;i<3;i++) D[i][i]=D_scalar;
+
+		TripleMultiply(&B[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&Bprime[0][0],3,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticMacAyealFriction {{{1*/
+ElementMatrix* Tria::CreateKMatrixDiagnosticMacAyealFriction(void){
+
+	/*Constants*/
+	const int  numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries*/
+	int        i,j,ig;
+	int        analysis_type;
+	double     MAXSLOPE  = .06; // 6 %
+	double     MOUNTAINKEXPONENT = 10;
+	double     slope_magnitude,alpha2;
+	double     Jdet;
+	double     L[2][numdof];
+	double     DL[2][2]  = {{ 0,0 },{0,0}};
+	double     DL_scalar;
+	double     slope[2]  = {0.0,0.0};
+	double     xyz_list[NUMVERTICES][3];
+	Friction  *friction = NULL;
+	GaussTria *gauss    = NULL;
+
+	/*Initialize Element matrix and return if necessary*/
+	if(IsOnShelf()) return NULL;
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* surface_input=inputs->GetInput(SurfaceEnum); _assert_(surface_input);
+	Input* vx_input=inputs->GetInput(VxEnum);           _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(VyEnum);           _assert_(vy_input);
+	Input* vz_input=inputs->GetInput(VzEnum);           _assert_(vz_input);
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+
+	/*build friction object, used later on: */
+	friction=new Friction("2d",inputs,matpar,analysis_type);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
+		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
+		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
+		if(slope_magnitude>MAXSLOPE) alpha2=pow((double)10,MOUNTAINKEXPONENT);
+		else friction->GetAlpha2(&alpha2, gauss,VxEnum,VyEnum,VzEnum);
+
+		GetL(&L[0][0], &xyz_list[0][0], gauss,NDOF2);
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+		DL_scalar=alpha2*gauss->weight*Jdet;
+		for (i=0;i<2;i++) DL[i][i]=DL_scalar;
+		
+		TripleMultiply( &L[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&L[0][0],2,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticHutter{{{1*/
+ElementMatrix* Tria::CreateKMatrixDiagnosticHutter(void){
+
+	/*Intermediaries*/
+	const int numdof=NUMVERTICES*NDOF2;
+	int    i,connectivity;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Create Element matrix*/
+	for(i=0;i<NUMVERTICES;i++){
+		connectivity=nodes[i]->GetConnectivity();
+		Ke->values[(2*i)*numdof  +(2*i)  ]=1/(double)connectivity;
+		Ke->values[(2*i+1)*numdof+(2*i+1)]=1/(double)connectivity;
+	}
+
+	/*Clean up and return*/
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorDiagnosticMacAyeal {{{1*/
+ElementVector* Tria::CreatePVectorDiagnosticMacAyeal(){
+
+	/*Constants*/
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	/*Intermediaries */
+	int            i,j,ig;
+	double         driving_stress_baseline,thickness;
+	double         Jdet;
+	double         xyz_list[NUMVERTICES][3];
+	double         slope[2];
+	double         basis[3];
+	double         pe_g_gaussian[numdof];
+	GaussTria*     gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters,MacAyealApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input); 
+	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
+	Input* drag_input=inputs->GetInput(FrictionCoefficientEnum);_assert_(drag_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctions(basis, gauss);
+
+		thickness_input->GetParameterValue(&thickness,gauss);
+		surface_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+		driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
+
+		/*Build pe_g_gaussian vector: */
+		for (i=0;i<NUMVERTICES;i++){
+			for (j=0;j<NDOF2;j++){
+				pe->values[i*NDOF2+j]+=-driving_stress_baseline*slope[j]*Jdet*gauss->weight*basis[i];
+			}
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorDiagnosticHutter{{{1*/
+ElementVector* Tria::CreatePVectorDiagnosticHutter(void){
+
+	/*Intermediaries */
+	int        i,connectivity;
+	double     constant_part,ub,vb;
+	double     rho_ice,gravity,n,B;
+	double     slope2,thickness;
+	double     slope[2];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	n=matice->GetN();
+	B=matice->GetBbar();
+	Input* slopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(slopex_input);
+	Input* slopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(slopey_input);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum);  _assert_(thickness_input);
+
+	/*Spawn 3 sing elements: */
+	gauss=new GaussTria();
+	for(i=0;i<NUMVERTICES;i++){
+
+		gauss->GaussVertex(i);
+
+		connectivity=nodes[i]->GetConnectivity();
+
+		thickness_input->GetParameterValue(&thickness,gauss);
+		slopex_input->GetParameterValue(&slope[0],gauss);
+		slopey_input->GetParameterValue(&slope[1],gauss);
+		slope2=pow(slope[0],2)+pow(slope[1],2);
+
+		constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
+
+		ub=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[0];
+		vb=-1.58*pow((double)10.0,(double)-10.0)*rho_ice*gravity*thickness*slope[1];
+
+		pe->values[2*i]  =(ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0])/(double)connectivity;
+		pe->values[2*i+1]=(vb-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[1])/(double)connectivity;
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
 }
 /*}}}*/
@@ -2082,108 +3189,141 @@
 }
 /*}}}*/
-/*FUNCTION Tria::GetSolutionFromInputsHydrology{{{1*/
-void  Tria::GetSolutionFromInputsHydrology(Vec solution){
-
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	int i,dummy;
-	int*         doflist=NULL;
-	double       watercolumn;
-	double       values[numdof];
-	GaussTria*   gauss=NULL;
-
+/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
+void  Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
+	
+	const int numdof=NDOF2*NUMVERTICES;
+
+	int       i;
+	int       dummy;
+	int*      doflist=NULL;
+	double    rho_ice,g;
+	double    values[numdof];
+	double    vx[NUMVERTICES];
+	double    vy[NUMVERTICES];
+	double    vz[NUMVERTICES];
+	double    vel[NUMVERTICES];
+	double    pressure[NUMVERTICES];
+	double    thickness[NUMVERTICES];
+	
 	/*Get dof list: */
 	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
 
-	/*Get inputs*/
-	Input* watercolumn_input=inputs->GetInput(WatercolumnEnum); _assert_(watercolumn_input);
-
-	/*Ok, we have watercolumn values, fill in watercolumn array: */
-	/*P1 element only for now*/
-	gauss=new GaussTria();
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
-
-		gauss->GaussVertex(i);
-
-		/*Recover watercolumn*/
-		watercolumn_input->GetParameterValue(&watercolumn,gauss);
-		values[i]=watercolumn;
-	}
-
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+		vx[i]=values[i*NDOF2+0];
+		vy[i]=values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz and compute vel*/
+	GetParameterListOnVertices(&vz[0],VzEnum,0);
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 
+	 *so the pressure is just the pressure at the bedrock: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	GetParameterListOnVertices(&thickness[0],ThicknessEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
 
 	/*Free ressources:*/
-	delete gauss;
 	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){{{1*/
-void Tria::GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input){
-	/*Compute the 2d Strain Rate (3 components):
-	 * epsilon=[exx eyy exy] */
-
-	int i;
-	double epsilonvx[3];
-	double epsilonvy[3];
-
-	/*Check that both inputs have been found*/
-	if (!vx_input || !vy_input){
-		_error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p\n",vx_input,vy_input);
-	}
-
-	/*Get strain rate assuming that epsilon has been allocated*/
-	vx_input->GetVxStrainRate2d(epsilonvx,xyz_list,gauss);
-	vy_input->GetVyStrainRate2d(epsilonvy,xyz_list,gauss);
-
-	/*Sum all contributions*/
-	for(i=0;i<3;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
-}
-/*}}}*/
-/*FUNCTION Tria::GetVectorFromInputs{{{1*/
-void  Tria::GetVectorFromInputs(Vec vector,int input_enum){
-
-	int doflist1[NUMVERTICES];
-
-	/*Get out if this is not an element input*/
-	if (!IsInput(input_enum)) return;
-
-	/*Prepare index list*/
-	this->GetDofList1(&doflist1[0]);
-
-	/*Get input (either in element or material)*/
-	Input* input=inputs->GetInput(input_enum);
-	if(!input) _error_("Input %s not found in element",EnumToStringx(input_enum));
-
-	/*We found the enum.  Use its values to fill into the vector, using the vertices ids: */
-	input->GetVectorFromInputs(vector,&doflist1[0]);
-}
-/*}}}*/
-/*FUNCTION Tria::Id {{{1*/
-int    Tria::Id(){
+
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/
+void  Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){
 	
-	return id;
-
-}
-/*}}}*/
-/*FUNCTION Tria::Sid {{{1*/
-int    Tria::Sid(){
+	const int numdof=NDOF2*NUMVERTICES;
 	
-	return sid;
-
-}
-/*}}}*/
-/*FUNCTION Tria::InputArtificialNoise{{{1*/
-void  Tria::InputArtificialNoise(int enum_type,double min,double max){
-
-	Input* input=NULL;
-
-	/*Make a copy of the original input: */
-	input=(Input*)this->inputs->GetInput(enum_type);
-	if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
-
-	/*ArtificialNoise: */
-	input->ArtificialNoise(min,max);
-}
-/*}}}*/
+	int       i;
+	int       dummy;
+	int*      doflist=NULL;
+	double    rho_ice,g;
+	double    values[numdof];
+	double    vx[NUMVERTICES];
+	double    vy[NUMVERTICES];
+	double    vz[NUMVERTICES];
+	double    vel[NUMVERTICES];
+	double    pressure[NUMVERTICES];
+	double    thickness[NUMVERTICES];
+	double*   vz_ptr=NULL;
+	Input*    vz_input=NULL;
+	
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Use the dof list to index into the solution vector: */
+	for(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(i=0;i<NUMVERTICES;i++){
+		vx[i]=values[i*NDOF2+0];
+		vy[i]=values[i*NDOF2+1];
+
+		/*Check solution*/
+		if(isnan(vx[i])) _error_("NaN found in solution vector");
+		if(isnan(vy[i])) _error_("NaN found in solution vector");
+	}
+
+	/*Get Vz*/
+	vz_input=inputs->GetInput(VzEnum);
+	if (vz_input){
+		if (vz_input->Enum()!=TriaVertexInputEnum){
+			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
+		}
+		vz_input->GetValuesPtr(&vz_ptr,&dummy);
+		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
+	}
+	else{
+		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
+	}
+
+	/*Now Compute vel*/
+	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
+
+	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 
+	 *so the pressure is just the pressure at the bedrock: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	GetParameterListOnVertices(&thickness[0],ThicknessEnum);
+	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
+
+	/*Now, we have to move the previous Vx and Vy inputs  to old 
+	 * status, otherwise, we'll wipe them off: */
+	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
+	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
+	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
+	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
+	this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
+
+	/*Free ressources:*/
+	xfree((void**)&doflist);
+}
+/*}}}*/
+
+#endif
 
 #ifdef _HAVE_CONTROL_
@@ -3586,284 +4726,37 @@
 }
 /*}}}*/
-#endif
-
-/*FUNCTION Tria::InputConvergence{{{1*/
-bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
-
-	bool    converged=true;
-	int     i;
-	Input** new_inputs=NULL;
-	Input** old_inputs=NULL;
-
-	new_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the new inputs
-	old_inputs=(Input**)xmalloc(num_enums/2*sizeof(Input*)); //half the enums are for the old inputs
-
-	for(i=0;i<num_enums/2;i++){
-		new_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+0]);
-		old_inputs[i]=(Input*)this->inputs->GetInput(enums[2*i+1]);
-		if(!new_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
-		if(!old_inputs[i])_error_("%s%s"," could not find input with enum ",EnumToStringx(enums[2*i+0]));
-	}
-
-	/*ok, we've got the inputs (new and old), now loop throught the number of criterions and fill the eps array:*/
-	for(i=0;i<num_criterionenums;i++){
-		IsInputConverged(eps+i,new_inputs,old_inputs,num_enums/2,criterionenums[i]);
-		if(eps[i]>criterionvalues[i]) converged=false; 
-	}
-
-	/*clean up and return*/
-	xfree((void**)&new_inputs);
-	xfree((void**)&old_inputs);
-	return converged;
-}
-/*}}}*/
-/*FUNCTION Tria::InputDepthAverageAtBase {{{1*/
-void  Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum){
-
-	/*New input*/
-	Input* oldinput=NULL;
-	Input* newinput=NULL;
-
-	/*copy input of enum_type*/
-	if (object_enum==MeshElementsEnum)
-	 oldinput=(Input*)this->inputs->GetInput(enum_type);
-	else if (object_enum==MaterialsEnum)
-	 oldinput=(Input*)this->matice->inputs->GetInput(enum_type);
-	else
-	 _error_("object %s not supported yet",EnumToStringx(object_enum));
-	if(!oldinput)_error_("%s%s"," could not find old input with enum: ",EnumToStringx(enum_type));
-	newinput=(Input*)oldinput->copy();
-
-	/*Assign new name (average)*/
-	newinput->ChangeEnum(average_enum_type);
-
-	/*Add new input to current element*/
-	if (object_enum==MeshElementsEnum)
-	 this->inputs->AddInput((Input*)newinput);
-	else if (object_enum==MaterialsEnum)
-	 this->matice->inputs->AddInput((Input*)newinput);
-	else
-	 _error_("object %s not supported yet",EnumToStringx(object_enum));
-}
-/*}}}*/
-/*FUNCTION Tria::InputDuplicate{{{1*/
-void  Tria::InputDuplicate(int original_enum,int new_enum){
-
-	/*Call inputs method*/
-	if (IsInput(original_enum)) inputs->DuplicateInput(original_enum,new_enum);
-
-}
-/*}}}*/
-/*FUNCTION Tria::InputScale{{{1*/
-void  Tria::InputScale(int enum_type,double scale_factor){
-
-	Input* input=NULL;
-
-	/*Make a copy of the original input: */
-	input=(Input*)this->inputs->GetInput(enum_type);
-	if(!input)_error_(" could not find old input with enum: %s",EnumToStringx(enum_type));
-
-	/*Scale: */
-	input->Scale(scale_factor);
-}
-/*}}}*/
-/*FUNCTION Tria::InputToResult{{{1*/
-void  Tria::InputToResult(int enum_type,int step,double time){
-
-	int    i;
-	Input *input = NULL;
-
-	/*Go through all the input objects, and find the one corresponding to enum_type, if it exists: */
-	if (enum_type==MaterialsRheologyBbarEnum) input=this->matice->inputs->GetInput(enum_type);
-	else input=this->inputs->GetInput(enum_type);
-	if (!input) _error_("Input %s not found in tria->inputs",EnumToStringx(enum_type));
-
-	/*If we don't find it, no big deal, just don't do the transfer. Otherwise, build a new Result 
-	 * object out of the input, with the additional step and time information: */
-	this->results->AddObject((Object*)input->SpawnResult(step,time));
-	#ifdef _HAVE_CONTROL_
-	if(input->Enum()==ControlInputEnum) this->results->AddObject((Object*)((ControlInput*)input)->SpawnGradient(step,time));
-	#endif
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromConstant(int value, int name);{{{1*/
-void  Tria::InputUpdateFromConstant(int constant, int name){
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-
-	/*update input*/
-	this->inputs->AddInput(new IntInput(name,constant));
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromConstant(double value, int name);{{{1*/
-void  Tria::InputUpdateFromConstant(double constant, int name){
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-
-	/*update input*/
-	this->inputs->AddInput(new DoubleInput(name,constant));
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromConstant(bool value, int name);{{{1*/
-void  Tria::InputUpdateFromConstant(bool constant, int name){
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-
-	/*update input*/
-	this->inputs->AddInput(new BoolInput(name,constant));
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromIoModel{{{1*/
-void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index
-
-	/*Intermediaries*/
-	int    i,j;
-	int    tria_vertex_ids[3];
-	double nodeinputs[3];
-	double cmmininputs[3];
-	double cmmaxinputs[3];
-	bool   control_analysis=false;
-	int    num_control_type;
-	double yts;
-	int    num_cm_responses;
-   
-	/*Get parameters: */
-	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
-	iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);
-	iomodel->Constant(&yts,ConstantsYtsEnum); 
-	iomodel->Constant(&num_cm_responses,InversionNumCostFunctionsEnum);
-
-	/*Recover vertices ids needed to initialize inputs*/
-	for(i=0;i<3;i++){ 
-		tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
-	}
-
-	/*Control Inputs*/
-	#ifdef _HAVE_CONTROL_
-	if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
-		for(i=0;i<num_control_type;i++){
-			switch((int)iomodel->Data(InversionControlParametersEnum)[i]){
-				case BalancethicknessThickeningRateEnum:
-					if (iomodel->Data(BalancethicknessThickeningRateEnum)){
-						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(BalancethicknessThickeningRateEnum)[tria_vertex_ids[j]-1]/yts;
-						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						this->inputs->AddInput(new ControlInput(BalancethicknessThickeningRateEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
-					}
-					break;
-				case VxEnum:
-					if (iomodel->Data(VxEnum)){
-						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VxEnum)[tria_vertex_ids[j]-1]/yts;
-						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						this->inputs->AddInput(new ControlInput(VxEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
-					}
-					break;
-				case VyEnum:
-					if (iomodel->Data(VyEnum)){
-						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(VyEnum)[tria_vertex_ids[j]-1]/yts;
-						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i]/yts;
-						this->inputs->AddInput(new ControlInput(VyEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
-					}
-					break;
-				case FrictionCoefficientEnum:
-					if (iomodel->Data(FrictionCoefficientEnum)){
-						for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(FrictionCoefficientEnum)[tria_vertex_ids[j]-1];
-						for(j=0;j<3;j++)cmmininputs[j]=iomodel->Data(InversionMinParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
-						for(j=0;j<3;j++)cmmaxinputs[j]=iomodel->Data(InversionMaxParametersEnum)[(tria_vertex_ids[j]-1)*num_control_type+i];
-						this->inputs->AddInput(new ControlInput(FrictionCoefficientEnum,TriaVertexInputEnum,nodeinputs,cmmininputs,cmmaxinputs,i+1));
-					}
-					break;
-				case MaterialsRheologyBbarEnum:
-					/*Matice will take care of it*/ break;
-				default:
-					_error_("Control %s not implemented yet",EnumToStringx((int)iomodel->Data(InversionControlParametersEnum)[i]));
-			}
-		}
-	}
-	#endif
-
-	/*DatasetInputs*/
-	if (control_analysis && iomodel->Data(InversionCostFunctionsCoefficientsEnum)){
-
-		/*Create inputs and add to DataSetInput*/
-		DatasetInput* datasetinput=new DatasetInput(InversionCostFunctionsCoefficientsEnum);
-		for(i=0;i<num_cm_responses;i++){
-			for(j=0;j<3;j++)nodeinputs[j]=iomodel->Data(InversionCostFunctionsCoefficientsEnum)[(tria_vertex_ids[j]-1)*num_cm_responses+i];
-			datasetinput->inputs->AddObject(new TriaVertexInput(InversionCostFunctionsCoefficientsEnum,nodeinputs));
-		}
-
-		/*Add datasetinput to element inputs*/
-		this->inputs->AddInput(datasetinput);
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolution {{{1*/
-void  Tria::InputUpdateFromSolution(double* solution){
-
-	/*retrive parameters: */
-	int analysis_type;
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-
-	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
-	switch(analysis_type){
-		case DiagnosticHorizAnalysisEnum:
-			InputUpdateFromSolutionDiagnosticHoriz( solution);
+/*FUNCTION Tria::CreateKMatrixAdjointBalancethickness {{{1*/
+ElementMatrix* Tria::CreateKMatrixAdjointBalancethickness(void){
+
+	ElementMatrix* Ke=NULL;
+
+	/*Get Element Matrix of the forward model*/
+	switch(GetElementType()){
+		case P1Enum:
+			Ke=CreateKMatrixBalancethickness_CG();
 			break;
-		case DiagnosticHutterAnalysisEnum:
-			InputUpdateFromSolutionDiagnosticHoriz( solution);
-			break;
-		#ifdef _HAVE_CONTROL_
-		case AdjointHorizAnalysisEnum:
-			InputUpdateFromSolutionAdjointHoriz( solution);
-			break;
-		case AdjointBalancethicknessAnalysisEnum:
-			InputUpdateFromSolutionAdjointBalancethickness( solution);
-			break;
-		#endif
-		case BedSlopeXAnalysisEnum:
-			InputUpdateFromSolutionOneDof(solution,BedSlopeXEnum);
-			break;
-		case BedSlopeYAnalysisEnum:
-			InputUpdateFromSolutionOneDof(solution,BedSlopeYEnum);
-			break;
-		case SurfaceSlopeXAnalysisEnum:
-			InputUpdateFromSolutionOneDof(solution,SurfaceSlopeXEnum);
-			break;
-		case SurfaceSlopeYAnalysisEnum:
-			InputUpdateFromSolutionOneDof(solution,SurfaceSlopeYEnum);
-			break;
-		case PrognosticAnalysisEnum:
-			InputUpdateFromSolutionPrognostic(solution);
-			break;
-		case HydrologyAnalysisEnum:
-			InputUpdateFromSolutionHydrology(solution);
-			break;
-		case BalancethicknessAnalysisEnum:
-			InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
+		case P1DGEnum:
+			Ke=CreateKMatrixBalancethickness_DG();
 			break;
 		default:
-			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHoriz {{{1*/
-void  Tria::InputUpdateFromSolutionDiagnosticHoriz(double* solution){
-	
+			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
+	}
+
+	/*Transpose and return Ke*/
+	Ke->Transpose();
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolutionAdjointHoriz {{{1*/
+void  Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){
+
 	const int numdof=NDOF2*NUMVERTICES;
 
 	int       i;
-	int       dummy;
 	int*      doflist=NULL;
-	double    rho_ice,g;
 	double    values[numdof];
-	double    vx[NUMVERTICES];
-	double    vy[NUMVERTICES];
-	double    vz[NUMVERTICES];
-	double    vel[NUMVERTICES];
-	double    pressure[NUMVERTICES];
-	double    thickness[NUMVERTICES];
-	
+	double    lambdax[NUMVERTICES];
+	double    lambday[NUMVERTICES];
+
 	/*Get dof list: */
 	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
@@ -3874,59 +4767,30 @@
 	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
 	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=values[i*NDOF2+0];
-		vy[i]=values[i*NDOF2+1];
+		lambdax[i]=values[i*NDOF2+0];
+		lambday[i]=values[i*NDOF2+1];
 
 		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz and compute vel*/
-	GetParameterListOnVertices(&vz[0],VzEnum,0);
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 
-	 *so the pressure is just the pressure at the bedrock: */
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-	GetParameterListOnVertices(&thickness[0],ThicknessEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+		if(isnan(lambdax[i])) _error_("NaN found in solution vector");
+		if(isnan(lambday[i])) _error_("NaN found in solution vector");
+	}
 
 	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
+	this->inputs->AddInput(new TriaVertexInput(AdjointxEnum,lambdax));
+	this->inputs->AddInput(new TriaVertexInput(AdjointyEnum,lambday));
 
 	/*Free ressources:*/
 	xfree((void**)&doflist);
-
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionDiagnosticHutter {{{1*/
-void  Tria::InputUpdateFromSolutionDiagnosticHutter(double* solution){
-	
-	const int numdof=NDOF2*NUMVERTICES;
-	
+}
+/*}}}*/
+/*FUNCTION Tria::InputUpdateFromSolutionAdjointBalancethickness {{{1*/
+void  Tria::InputUpdateFromSolutionAdjointBalancethickness(double* solution){
+
+	const int numdof=NDOF1*NUMVERTICES;
+
 	int       i;
-	int       dummy;
 	int*      doflist=NULL;
-	double    rho_ice,g;
 	double    values[numdof];
-	double    vx[NUMVERTICES];
-	double    vy[NUMVERTICES];
-	double    vz[NUMVERTICES];
-	double    vel[NUMVERTICES];
-	double    pressure[NUMVERTICES];
-	double    thickness[NUMVERTICES];
-	double*   vz_ptr=NULL;
-	Input*    vz_input=NULL;
-	
+	double    lambda[NUMVERTICES];
+
 	/*Get dof list: */
 	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
@@ -3936,47 +4800,11 @@
 
 	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
-	for(i=0;i<NUMVERTICES;i++){
-		vx[i]=values[i*NDOF2+0];
-		vy[i]=values[i*NDOF2+1];
-
-		/*Check solution*/
-		if(isnan(vx[i])) _error_("NaN found in solution vector");
-		if(isnan(vy[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Get Vz*/
-	vz_input=inputs->GetInput(VzEnum);
-	if (vz_input){
-		if (vz_input->Enum()!=TriaVertexInputEnum){
-			_error_("Cannot compute Vel as Vz is of type %s",EnumToStringx(vz_input->Enum()));
-		}
-		vz_input->GetValuesPtr(&vz_ptr,&dummy);
-		for(i=0;i<NUMVERTICES;i++) vz[i]=vz_ptr[i];
-	}
-	else{
-		for(i=0;i<NUMVERTICES;i++) vz[i]=0.0;
-	}
-
-	/*Now Compute vel*/
-	for(i=0;i<NUMVERTICES;i++) vel[i]=pow( pow(vx[i],2.0) + pow(vy[i],2.0) + pow(vz[i],2.0) , 0.5);
-
-	/*For pressure: we have not computed pressure in this analysis, for this element. We are in 2D, 
-	 *so the pressure is just the pressure at the bedrock: */
-	rho_ice=matpar->GetRhoIce();
-	g=matpar->GetG();
-	GetParameterListOnVertices(&thickness[0],ThicknessEnum);
-	for(i=0;i<NUMVERTICES;i++) pressure[i]=rho_ice*g*thickness[i];
-
-	/*Now, we have to move the previous Vx and Vy inputs  to old 
-	 * status, otherwise, we'll wipe them off: */
-	this->inputs->ChangeEnum(VxEnum,VxPicardEnum);
-	this->inputs->ChangeEnum(VyEnum,VyPicardEnum);
-	this->inputs->ChangeEnum(PressureEnum,PressurePicardEnum);
+	for(i=0;i<numdof;i++){
+		lambda[i]=values[i];
+		if(isnan(lambda[i])) _error_("NaN found in solution vector");
+	}
 
 	/*Add vx and vy as inputs to the tria element: */
-	this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
-	this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
-	this->inputs->AddInput(new TriaVertexInput(VelEnum,vel));
-	this->inputs->AddInput(new TriaVertexInput(PressureEnum,pressure));
+	this->inputs->AddInput(new TriaVertexInput(AdjointEnum,lambda));
 
 	/*Free ressources:*/
@@ -3984,96 +4812,235 @@
 }
 /*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionOneDof{{{1*/
-void  Tria::InputUpdateFromSolutionOneDof(double* solution,int enum_type){
-
-	const int numdof          = NDOF1*NUMVERTICES;
-
-	int*      doflist=NULL;
-	double    values[numdof];
+#endif
+
+#ifdef _HAVE_HYDROLOGY_
+/*FUNCTION Tria::CreateHydrologyWaterVelocityInput {{{1*/
+void Tria::CreateHydrologyWaterVelocityInput(void){
+
+	/*material parameters: */
+	double mu_water=0.001787;  //unit= [N s/m2]
+	double w;
+	double rho_ice, rho_water, g;
+	double dsdx,dsdy,dbdx,dbdy;
+	double vx[NUMVERTICES];
+	double vy[NUMVERTICES];
+	GaussTria *gauss = NULL;
+
+	/*Retrieve all inputs and parameters*/
+	rho_ice=matpar->GetRhoIce();
+	rho_water=matpar->GetRhoWater();
+	g=matpar->GetG();
+	Input* surfaceslopex_input=inputs->GetInput(SurfaceSlopeXEnum); _assert_(surfaceslopex_input);
+	Input* surfaceslopey_input=inputs->GetInput(SurfaceSlopeYEnum); _assert_(surfaceslopey_input);
+	Input* bedslopex_input=inputs->GetInput(BedSlopeXEnum);         _assert_(bedslopex_input);
+	Input* bedslopey_input=inputs->GetInput(BedSlopeYEnum);         _assert_(bedslopey_input);
+	Input* watercolumn_input=inputs->GetInput(WatercolumnEnum);     _assert_(watercolumn_input);
+
+	gauss=new GaussTria();
+	for (int iv=0;iv<NUMVERTICES;iv++){
+		gauss->GaussVertex(iv);
+		surfaceslopex_input->GetParameterValue(&dsdx,gauss);
+		surfaceslopey_input->GetParameterValue(&dsdy,gauss);
+		bedslopex_input->GetParameterValue(&dbdx,gauss);
+		bedslopey_input->GetParameterValue(&dbdy,gauss);
+		watercolumn_input->GetParameterValue(&w,gauss);
+
+		/* Water velocity x and y components */
+		vx[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdx+(rho_water-rho_ice)*g*dbdx);
+		vy[iv]= - pow(w,2)/(12 * mu_water)*(rho_ice*g*dsdy+(rho_water-rho_ice)*g*dbdy);
+		//vx[iv]=0.001;
+		//vy[iv]=0;
+	}
+
+	/*clean-up*/
+	delete gauss;
+
+	/*Add to inputs*/
+	this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVxEnum,vx));
+	this->inputs->AddInput(new TriaVertexInput(HydrologyWaterVyEnum,vy));
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixHydrology{{{1*/
+ElementMatrix* Tria::CreateKMatrixHydrology(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        artdiff;
+	int        i,j,ig;
+	double     Jdettria,DL_scalar,dt,h;
+	double     vx,vy,vel,dvxdx,dvydy;
+	double     dvx[2],dvy[2];
+	double     v_gauss[2]={0.0};
+	double     xyz_list[NUMVERTICES][3];
+	double     L[NUMVERTICES];
+	double     B[2][NUMVERTICES];
+	double     Bprime[2][NUMVERTICES];
+	double     K[2][2]                        ={0.0};
+	double     KDL[2][2]                      ={0.0};
+	double     DL[2][2]                        ={0.0};
+	double     DLprime[2][2]                   ={0.0};
+	GaussTria *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Create water velocity vx and vy from current inputs*/
+	CreateHydrologyWaterVelocityInput();
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	this->parameters->FindParam(&artdiff,HydrologyStabilizationEnum);
+	Input* vx_input=inputs->GetInput(HydrologyWaterVxEnum); _assert_(vx_input);
+	Input* vy_input=inputs->GetInput(HydrologyWaterVyEnum); _assert_(vy_input);
+	h=this->GetArea();
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
+
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
+		vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
+
+		DL_scalar=gauss->weight*Jdettria;
+
+		TripleMultiply( &L[0],1,numdof,1,
+					&DL_scalar,1,1,0,
+					&L[0],1,numdof,0,
+					&Ke->values[0],1);
+
+		GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
+		GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
+
+		dvxdx=dvx[0];
+		dvydy=dvy[1];
+		DL_scalar=dt*gauss->weight*Jdettria;
+
+		DL[0][0]=DL_scalar*dvxdx;
+		DL[1][1]=DL_scalar*dvydy;
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&B[0][0],2,numdof,0,
+					&Ke->values[0],1);
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke->values[0],1);
+
+		if(artdiff){
+			vel=sqrt(pow(vx,2.)+pow(vy,2.));
+			K[0][0]=h/(2*vel)*vx*vx;
+			K[1][0]=h/(2*vel)*vy*vx;
+			K[0][1]=h/(2*vel)*vx*vy;
+			K[1][1]=h/(2*vel)*vy*vy;
+			KDL[0][0]=DL_scalar*K[0][0];
+			KDL[1][0]=DL_scalar*K[1][0];
+			KDL[0][1]=DL_scalar*K[0][1];
+			KDL[1][1]=DL_scalar*K[1][1];
+
+			TripleMultiply( &Bprime[0][0],2,numdof,1,
+						&KDL[0][0],2,2,0,
+						&Bprime[0][0],2,numdof,0,
+						&Ke->values[0],1);
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorHydrology {{{1*/
+ElementVector* Tria::CreatePVectorHydrology(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     Jdettria,dt;
+	double     basal_melting_g;
+	double     old_watercolumn_g;
+	double     xyz_list[NUMVERTICES][3];
+	double     basis[numdof];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum); _assert_(basal_melting_input);
+	Input* old_watercolumn_input=inputs->GetInput(WaterColumnOldEnum);         _assert_(old_watercolumn_input);
+
+	/*Initialize basal_melting_correction_g to 0, do not forget!:*/
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		GetNodalFunctions(basis, gauss);
+
+		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
+		old_watercolumn_input->GetParameterValue(&old_watercolumn_g,gauss);
+
+		if(dt)for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(old_watercolumn_g+dt*basal_melting_g)*basis[i];
+		else  for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*basal_melting_g*basis[i];
+	}
+		
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::GetSolutionFromInputsHydrology{{{1*/
+void  Tria::GetSolutionFromInputsHydrology(Vec solution){
+
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	int i,dummy;
+	int*         doflist=NULL;
+	double       watercolumn;
+	double       values[numdof];
+	GaussTria*   gauss=NULL;
 
 	/*Get dof list: */
 	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
 
-	/*Use the dof list to index into the solution vector: */
-	for(int i=0;i<numdof;i++){
-		values[i]=solution[doflist[i]];
-		if(isnan(values[i])) _error_("NaN found in solution vector");
-	}
-
-	/*Add input to the element: */
-	this->inputs->AddInput(new TriaVertexInput(enum_type,values));
+	/*Get inputs*/
+	Input* watercolumn_input=inputs->GetInput(WatercolumnEnum); _assert_(watercolumn_input);
+
+	/*Ok, we have watercolumn values, fill in watercolumn array: */
+	/*P1 element only for now*/
+	gauss=new GaussTria();
+	for(i=0;i<NUMVERTICES;i++){
+
+		gauss->GaussVertex(i);
+
+		/*Recover watercolumn*/
+		watercolumn_input->GetParameterValue(&watercolumn,gauss);
+		values[i]=watercolumn;
+	}
+
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
 
 	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionPrognostic{{{1*/
-void  Tria::InputUpdateFromSolutionPrognostic(double* solution){
-
-	/*Intermediaries*/
-	const int numdof = NDOF1*NUMVERTICES;
-
-	int       i,dummy,hydroadjustment;
-	int*      doflist=NULL;
-	double    rho_ice,rho_water;
-	double    values[numdof];
-	double    bed[numdof];
-	double    surface[numdof];
-	double    *bed_ptr = NULL;
-	double    *thickness_ptr = NULL;
-	double    *surface_ptr = NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Use the dof list to index into the solution vector: */
-	for(i=0;i<numdof;i++){
-		values[i]=solution[doflist[i]];
-		if(isnan(values[i])) _error_("NaN found in solution vector");
-		/*Constrain thickness to be at least 1m*/
-		if(values[i]<1) values[i]=1;
-	}
-
-	/*Get previous bed, thickness and surface*/
-	Input* bed_input=inputs->GetInput(BedEnum);             _assert_(bed_input);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
-	Input* surface_input=inputs->GetInput(SurfaceEnum);     _assert_(surface_input);
-	bed_input->GetValuesPtr(&bed_ptr,&dummy);
-	thickness_input->GetValuesPtr(&thickness_ptr,&dummy);
-	surface_input->GetValuesPtr(&surface_ptr,&dummy);
-
-	/*Fing PrognosticHydrostaticAdjustment to figure out how to update the geometry:*/
-	this->parameters->FindParam(&hydroadjustment,PrognosticHydrostaticAdjustmentEnum);
-
-	/*recover material parameters: */
-	rho_ice=matpar->GetRhoIce();
-	rho_water=matpar->GetRhoWater();
-
-	for(i=0;i<numdof;i++) {
-		/*If shelf: hydrostatic equilibrium*/
-		if (this->nodes[i]->IsOnSheet()){
-			surface[i]=bed_ptr[i]+values[i]; //surface=oldbed+newthickness
-			bed[i]=bed_ptr[i]; //do nothing
-		}
-		else{ //this is an ice shelf
-
-			if(hydroadjustment==AbsoluteEnum){
-				surface[i]=values[i]*(1-rho_ice/rho_water);
-				bed[i]=values[i]*(-rho_ice/rho_water);
-			}
-			else if(hydroadjustment==IncrementalEnum){
-				surface[i]=surface_ptr[i]+(1.0-rho_ice/rho_water)*(values[i]-thickness_ptr[i]); //surface = oldsurface + (1-di) * dH 
-				bed[i]=bed_ptr[i]-rho_ice/rho_water*(values[i]-thickness_ptr[i]); //bed = oldbed + di * dH
-			}
-			else _error_("Hydrostatic adjustment %i (%s) not supported yet",hydroadjustment,EnumToStringx(hydroadjustment));
-		}
-	}
-
-	/*Add input to the element: */
-	this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,values));
-	this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,surface));
-	this->inputs->AddInput(new TriaVertexInput(BedEnum,bed));
-
-	/*Free ressources:*/
+	delete gauss;
 	xfree((void**)&doflist);
 }
@@ -4107,47 +5074,5 @@
 }
 /*}}}*/
-/*FUNCTION Tria::InputUpdateFromVector(double* vector, int name, int type);{{{1*/
-void  Tria::InputUpdateFromVector(double* vector, int name, int type){
-
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-
-	switch(type){
-
-		case VertexEnum:
-
-			/*New TriaVertexInput*/
-			double values[3];
-
-			/*Get values on the 3 vertices*/
-			for (int i=0;i<3;i++){
-				values[i]=vector[this->nodes[i]->GetVertexDof()];
-			}
-
-			/*update input*/
-			if (name==MaterialsRheologyBbarEnum || name==MaterialsRheologyBEnum){
-				matice->inputs->AddInput(new TriaVertexInput(name,values));
-			}
-			else{
-				this->inputs->AddInput(new TriaVertexInput(name,values));
-			}
-			return;
-
-		default:
-			_error_("type %i (%s) not implemented yet",type,EnumToStringx(type));
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromVector(int* vector, int name, int type);{{{1*/
-void  Tria::InputUpdateFromVector(int* vector, int name, int type){
-	_error_(" not supported yet!");
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
-void  Tria::InputUpdateFromVector(bool* vector, int name, int type){
-	_error_(" not supported yet!");
-}
-/*}}}*/
-
+#endif
 
 #ifdef _HAVE_DAKOTA_
@@ -4265,1112 +5190,289 @@
 /*}}}*/
 #endif
-/*FUNCTION Tria::InputCreate(double scalar,int enum,int code);{{{1*/
-void Tria::InputCreate(double scalar,int name,int code){
-
-	/*Check that name is an element input*/
-	if (!IsInput(name)) return;
-	
-	if ((code==5) || (code==1)){ //boolean
-		this->inputs->AddInput(new BoolInput(name,(bool)scalar));
-	}
-	else if ((code==6) || (code==2)){ //integer
-		this->inputs->AddInput(new IntInput(name,(int)scalar));
-	}
-	else if ((code==7) || (code==3)){ //double
-		this->inputs->AddInput(new DoubleInput(name,(int)scalar));
-	}
-	else _error_("%s%i"," could not recognize nature of vector from code ",code);
-
-}
-/*}}}*/
-/*FUNCTION Tria::InputCreate(double* vector,int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){{{1*/
-void Tria::InputCreate(double* vector, int index,IoModel* iomodel,int M,int N,int vector_type,int vector_enum,int code){//index into elements
+
+#ifdef _HAVE_BALANCED_
+/*FUNCTION Tria::CreateKMatrixBalancethickness {{{1*/
+ElementMatrix* Tria::CreateKMatrixBalancethickness(void){
+
+	switch(GetElementType()){
+		case P1Enum:
+			return CreateKMatrixBalancethickness_CG();
+		case P1DGEnum:
+			return CreateKMatrixBalancethickness_DG();
+		default:
+			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixBalancethickness_CG {{{1*/
+ElementMatrix* Tria::CreateKMatrixBalancethickness_CG(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        stabilization;
+	int        i,j,ig,dim;
+	double     Jdettria,vx,vy,dvxdx,dvydy,vel,h;
+	double     dvx[2],dvy[2];
+	double     xyz_list[NUMVERTICES][3];
+	double     L[NUMVERTICES];
+	double     B[2][NUMVERTICES];
+	double     Bprime[2][NUMVERTICES];
+	double     K[2][2]                          = {0.0};
+	double     KDL[2][2]                        = {0.0};
+	double     DL[2][2]                         = {0.0};
+	double     DLprime[2][2]                    = {0.0};
+	double     DL_scalar;
+	GaussTria *gauss                            = NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all Inputs and parameters: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	this->parameters->FindParam(&stabilization,BalancethicknessStabilizationEnum);
+	this->parameters->FindParam(&dim,MeshDimensionEnum);
+	Input* vxaverage_input=NULL;
+	Input* vyaverage_input=NULL;
+	if(dim==2){
+		vxaverage_input=inputs->GetInput(VxEnum); _assert_(vxaverage_input);
+		vyaverage_input=inputs->GetInput(VyEnum); _assert_(vyaverage_input);
+	}
+	else{
+		vxaverage_input=inputs->GetInput(VxAverageEnum); _assert_(vxaverage_input);
+		vyaverage_input=inputs->GetInput(VyAverageEnum); _assert_(vyaverage_input);
+	}
+	h=sqrt(2*this->GetArea());
+
+	///*Create Artificial diffusivity once for all if requested*/
+	//if(stabilization){
+	//	gauss=new GaussTria();
+	//	gauss->GaussCenter();
+	//	GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+	//	delete gauss;
+
+	//	vxaverage_input->GetParameterAverage(&vx);
+	//	vyaverage_input->GetParameterAverage(&vy);
+	//	K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(vx);
+	//	K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(vy);
+	//}
+
+	/*Start looping on the number of gaussian points:*/
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		GetBPrognostic(&B[0][0], &xyz_list[0][0], gauss);
+		GetBprimePrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
+
+		vxaverage_input->GetParameterValue(&vx,gauss);
+		vyaverage_input->GetParameterValue(&vy,gauss);
+		vxaverage_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
+		vyaverage_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
+
+		dvxdx=dvx[0];
+		dvydy=dvy[1];
+		DL_scalar=gauss->weight*Jdettria;
+
+		DL[0][0]=DL_scalar*dvxdx;
+		DL[1][1]=DL_scalar*dvydy;
+
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&B[0][0],2,numdof,0,
+					&Ke->values[0],1);
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke->values[0],1);
+
+		if(stabilization==1){
+			vel=sqrt(pow(vx,2.)+pow(vy,2.));
+			K[0][0]=h/(2*vel)*vx*vx;
+			K[1][0]=h/(2*vel)*vy*vx;
+			K[0][1]=h/(2*vel)*vx*vy;
+			K[1][1]=h/(2*vel)*vy*vy;
+			KDL[0][0]=DL_scalar*K[0][0];
+			KDL[1][0]=DL_scalar*K[1][0];
+			KDL[0][1]=DL_scalar*K[0][1];
+			KDL[1][1]=DL_scalar*K[1][1];
+
+			//KDL[0][0]=DL_scalar*K[0][0];
+			//KDL[1][1]=DL_scalar*K[1][1];
+
+			TripleMultiply( &Bprime[0][0],2,numdof,1,
+						&KDL[0][0],2,2,0,
+						&Bprime[0][0],2,numdof,0,
+						&Ke->values[0],1);
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixBalancethickness_DG {{{1*/
+ElementMatrix* Tria::CreateKMatrixBalancethickness_DG(void){
+
+	/*Constants*/
+	const int  numdof=NDOF1*NUMVERTICES;
 
 	/*Intermediaries*/
-	int    i,j,t;
-	int    tria_vertex_ids[3];
-	int    row;
-	double nodeinputs[3];
-	double time;
-	TransientInput* transientinput=NULL;
-	int    numberofvertices;
-	int    numberofelements;
-	double yts;
-
-
-	/*Fetch parameters: */
-	iomodel->Constant(&numberofvertices,MeshNumberofverticesEnum);
-	iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
-	iomodel->Constant(&yts,ConstantsYtsEnum);
-
-	/*Branch on type of vector: nodal or elementary: */
-	if(vector_type==1){ //nodal vector
-
-		/*Recover vertices ids needed to initialize inputs*/
-		for(i=0;i<3;i++){ 
-			tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
-		}
-
-		/*Are we in transient or static? */
-		if(M==numberofvertices){
-
-			/*create input values: */
-			for(i=0;i<3;i++)nodeinputs[i]=(double)vector[tria_vertex_ids[i]-1];
-
-			/*process units: */
-			UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
-
-			/*create static input: */
-			this->inputs->AddInput(new TriaVertexInput(vector_enum,nodeinputs));
-		}
-		else if(M==numberofvertices+1){
-			/*create transient input: */
-			for(t=0;t<N;t++){ //N is the number of times
-
-				/*create input values: */
-				for(i=0;i<3;i++){
-					row=tria_vertex_ids[i]-1;
-					nodeinputs[i]=(double)vector[N*row+t];
-				}
-
-				/*process units: */
-				UnitConversion(&nodeinputs[0], 3 ,ExtToIuEnum, vector_enum);
-
-				/*time? :*/
-				time=(double)vector[(M-1)*N+t]*yts;
-
-				if(t==0) transientinput=new TransientInput(vector_enum);
-				transientinput->AddTimeInput(new TriaVertexInput(vector_enum,nodeinputs),time);
-			}
-			this->inputs->AddInput(transientinput);
-		}
-		else _error_("nodal vector is either numberofnodes (%i), or numberofnodes+1 long. Field provided is %i long",numberofvertices,M);
-	}
-	else if(vector_type==2){ //element vector
-		/*Are we in transient or static? */
-		if(M==numberofelements){
-
-			/*static mode: create an input out of the element value: */
-
-			if (code==5){ //boolean
-				this->inputs->AddInput(new BoolInput(vector_enum,(bool)vector[index]));
-			}
-			else if (code==6){ //integer
-				this->inputs->AddInput(new IntInput(vector_enum,(int)vector[index]));
-			}
-			else if (code==7){ //double
-				this->inputs->AddInput(new DoubleInput(vector_enum,(double)vector[index]));
-			}
-			else _error_("%s%i"," could not recognize nature of vector from code ",code);
-		}
-		else {
-			_error_("transient elementary inputs not supported yet!");
-		}
-	}
-	else{
-		_error_("Cannot add input for vector type %i (not supported)",vector_type);
-	}
-
-}
-/*}}}*/
-/*FUNCTION Tria::IsInput{{{1*/
-bool Tria::IsInput(int name){
-	if (
-				name==ThicknessEnum ||
-				name==SurfaceEnum ||
-				name==BedEnum ||
-				name==SurfaceSlopeXEnum ||
-				name==SurfaceSlopeYEnum ||
-				name==BasalforcingsMeltingRateEnum ||
-				name==WatercolumnEnum || 
-				name==SurfaceforcingsMassBalanceEnum ||
-				name==SurfaceAreaEnum||
-				name==VxEnum ||
-				name==VyEnum ||
-				name==InversionVxObsEnum ||
-				name==InversionVyObsEnum ||
-				name==FrictionCoefficientEnum ||
-				name==GradientEnum ||
-				name==OldGradientEnum
-		){
-		return true;
-	}
-	else return false;
-}
-/*}}}*/
-/*FUNCTION Tria::IsOnBed {{{1*/
-bool Tria::IsOnBed(){
-	
-	bool onbed;
-	inputs->GetParameterValue(&onbed,MeshElementonbedEnum);
-	return onbed;
-}
-/*}}}*/
-/*FUNCTION Tria::IsOnShelf {{{1*/
-bool   Tria::IsOnShelf(){
-
-	bool shelf;
-	inputs->GetParameterValue(&shelf,MaskElementonfloatingiceEnum);
-	return shelf;
-}
-/*}}}*/
-/*FUNCTION Tria::IsNodeOnShelf {{{1*/
-bool   Tria::IsNodeOnShelf(){
-
-	int  i;
-	bool shelf=false;
-
-	for(i=0;i<3;i++){
-		if (nodes[i]->IsOnShelf()){
-			shelf=true;
-			break;
-		}
-	}
-	return shelf;
-}
-/*}}}*/
-/*FUNCTION Tria::IsNodeOnShelfFromFlags {{{1*/
-bool   Tria::IsNodeOnShelfFromFlags(double* flags){
-
-	int  i;
-	bool shelf=false;
-
-	for(i=0;i<3;i++){
-		if (flags[nodes[i]->Sid()]){
-			shelf=true;
-			break;
-		}
-	}
-	return shelf;
-}
-/*}}}*/
-/*FUNCTION Tria::IsOnWater {{{1*/
-bool   Tria::IsOnWater(){
-
-	bool water;
-	inputs->GetParameterValue(&water,MaskElementonwaterEnum);
-	return water;
-}
-/*}}}*/
-/*FUNCTION Tria::MassFlux {{{1*/
-double Tria::MassFlux( double* segment,bool process_units){
-
-	const int    numdofs=2;
-
-	int        i;
-	double     mass_flux=0;
+	int        i,j,ig,dim;
+	double     vx,vy,Jdettria;
 	double     xyz_list[NUMVERTICES][3];
-	double     normal[2];
-	double     length,rho_ice;
-	double     x1,y1,x2,y2,h1,h2;
-	double     vx1,vx2,vy1,vy2;
-	GaussTria* gauss_1=NULL;
-	GaussTria* gauss_2=NULL;
-
-	/*Get material parameters :*/
-	rho_ice=matpar->GetRhoIce();
-
-	/*First off, check that this segment belongs to this element: */
-	if ((int)*(segment+4)!=this->id)_error_("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id);
-
-	/*Recover segment node locations: */
-	x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3);
-
-	/*Get xyz list: */
+	double     B[2][NUMVERTICES];
+	double     Bprime[2][NUMVERTICES];
+	double     DL[2][2]={0.0};
+	double     DL_scalar;
+	GaussTria  *gauss=NULL;
+
+	/*Initialize Element matrix*/
+	ElementMatrix* Ke=new ElementMatrix(nodes,NUMVERTICES,this->parameters,NoneApproximationEnum);
+
+	/*Retrieve all inputs and parameters*/
 	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*get area coordinates of 0 and 1 locations: */
-	gauss_1=new GaussTria();
-	gauss_1->GaussFromCoords(x1,y1,&xyz_list[0][0]);
-	gauss_2=new GaussTria();
-	gauss_2->GaussFromCoords(x2,y2,&xyz_list[0][0]);
-
-	normal[0]=cos(atan2(x1-x2,y2-y1));
-	normal[1]=sin(atan2(x1-x2,y2-y1));
-
-	length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2));
-
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+	this->parameters->FindParam(&dim,MeshDimensionEnum);
 	Input* vx_input=inputs->GetInput(VxEnum); _assert_(vx_input);
 	Input* vy_input=inputs->GetInput(VyEnum); _assert_(vy_input);
 
-	thickness_input->GetParameterValue(&h1, gauss_1);
-	thickness_input->GetParameterValue(&h2, gauss_2);
-	vx_input->GetParameterValue(&vx1,gauss_1);
-	vx_input->GetParameterValue(&vx2,gauss_2);
-	vy_input->GetParameterValue(&vy1,gauss_1);
-	vy_input->GetParameterValue(&vy2,gauss_2);
-
-	mass_flux= rho_ice*length*(  
-				(ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+
-				(ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1]
-				);
-
-	/*Process units: */
-	mass_flux=UnitConversion(mass_flux,IuToExtEnum,MassFluxEnum);
-
-	/*clean up and return:*/
-	delete gauss_1;
-	delete gauss_2;
-	return mass_flux;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxAbsVx{{{1*/
-void  Tria::MaxAbsVx(double* pmaxabsvx, bool process_units){
-
-	/*Get maximum:*/
-	double maxabsvx=this->inputs->MaxAbs(VxEnum);
-
-	/*process units if requested: */
-	if(process_units) maxabsvx=UnitConversion(maxabsvx,IuToExtEnum,VxEnum);
-
-	/*Assign output pointers:*/
-	*pmaxabsvx=maxabsvx;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxAbsVy{{{1*/
-void  Tria::MaxAbsVy(double* pmaxabsvy, bool process_units){
-
-	/*Get maximum:*/
-	double maxabsvy=this->inputs->MaxAbs(VyEnum);
-
-	/*process units if requested: */
-	if(process_units) maxabsvy=UnitConversion(maxabsvy,IuToExtEnum,VyEnum);
-
-	/*Assign output pointers:*/
-	*pmaxabsvy=maxabsvy;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxAbsVz{{{1*/
-void  Tria::MaxAbsVz(double* pmaxabsvz, bool process_units){
-
-	/*Get maximum:*/
-	double maxabsvz=this->inputs->MaxAbs(VzEnum);
-
-	/*process units if requested: */
-	if(process_units) maxabsvz=UnitConversion(maxabsvz,IuToExtEnum,VyEnum);
-
-	/*Assign output pointers:*/
-	*pmaxabsvz=maxabsvz;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxVel{{{1*/
-void  Tria::MaxVel(double* pmaxvel, bool process_units){
-
-	/*Get maximum:*/
-	double maxvel=this->inputs->Max(VelEnum);
-
-	/*process units if requested: */
-	if(process_units) maxvel=UnitConversion(maxvel,IuToExtEnum,VelEnum);
-
-	/*Assign output pointers:*/
-	*pmaxvel=maxvel;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxVx{{{1*/
-void  Tria::MaxVx(double* pmaxvx, bool process_units){
-
-	/*Get maximum:*/
-	double maxvx=this->inputs->Max(VxEnum);
-
-	/*process units if requested: */
-	if(process_units) maxvx=UnitConversion(maxvx,IuToExtEnum,VxEnum);
-
-	/*Assign output pointers:*/
-	*pmaxvx=maxvx;
-}
-/*}}}*/
-/*FUNCTION Tria::MaxVy{{{1*/
-void  Tria::MaxVy(double* pmaxvy, bool process_units){
-
-	/*Get maximum:*/
-	double maxvy=this->inputs->Max(VyEnum);
-
-	/*process units if requested: */
-	if(process_units) maxvy=UnitConversion(maxvy,IuToExtEnum,VyEnum);
-
-	/*Assign output pointers:*/
-	*pmaxvy=maxvy;
-
-}
-/*}}}*/
-/*FUNCTION Tria::MaxVz{{{1*/
-void  Tria::MaxVz(double* pmaxvz, bool process_units){
-
-	/*Get maximum:*/
-	double maxvz=this->inputs->Max(VzEnum);
-
-	/*process units if requested: */
-	if(process_units) maxvz=UnitConversion(maxvz,IuToExtEnum,VzEnum);
-
-	/*Assign output pointers:*/
-	*pmaxvz=maxvz;
-}
-/*}}}*/
-/*FUNCTION Tria::MigrateGroundingLine{{{1*/
-void  Tria::MigrateGroundingLine(void){
-
-
-	double *values         = NULL;
-	double  h[3],s[3],b[3],ba[3];
-	double  bed_hydro;
-	double  rho_water,rho_ice,density;
-	int     isonshelf[3];
-	int     i;
-	bool    elementonshelf = false;
-
-
-	/*Recover info at the vertices: */
-	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
-	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-	for(i=0;i<3;i++){
-		isonshelf[i]=nodes[i]->IsOnShelf();
-		if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
-	}
-
-	/*material parameters: */
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	density=rho_ice/rho_water;
-
-	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
-	for(i=0;i<3;i++){
-		if (isonshelf[i]){
-			/*This node is on the shelf. See if its bed is going under the bathymetry: */
-			if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
-				/*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
-				b[i]=ba[i];
-				s[i]=b[i]+h[i];
-				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-			else{
-				/*do nothing, we are still floating.*/
-				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-		}
-		else{
-			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
-			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
-			bed_hydro=-density*h[i];
-			if (bed_hydro>ba[i]){
-				/*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
-				s[i]=(1-density)*h[i];
-				b[i]=-density*h[i];
-				printf("%i\n",nodes[i]->Sid()+1);
-				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-			else{
-				/*do nothing, we are still grounded.*/
-				if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i still grounded %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-		}
-	}
-
-	/*Surface and bed are updated. Update inputs:*/
-	surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
-	bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
+	/*Start looping on the number of gaussian points:*/
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		/*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
+		GetBPrognostic(&Bprime[0][0], &xyz_list[0][0], gauss);
+		GetBprimePrognostic(&B[0][0], &xyz_list[0][0], gauss);
+
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+
+		DL_scalar=-gauss->weight*Jdettria;
+		DL[0][0]=DL_scalar*vx;
+		DL[1][1]=DL_scalar*vy;
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke->values[0],1);
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Ke;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancethickness{{{1*/
+ElementVector* Tria::CreatePVectorBalancethickness(void){
+
+	switch(GetElementType()){
+		case P1Enum:
+			return CreatePVectorBalancethickness_CG();
+			break;
+		case P1DGEnum:
+			return CreatePVectorBalancethickness_DG();
+		default:
+			_error_("Element type %s not supported yet",EnumToStringx(GetElementType()));
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancethickness_CG{{{1*/
+ElementVector* Tria::CreatePVectorBalancethickness_CG(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
 	
-	for(i=0;i<3;i++){
-		isonshelf[i]=nodes[i]->IsOnShelf();
-		if((nodes[i]->Sid()+1)==36)printf("MigrateGroundingLine: El %i Node %i second shelf status %i\n",this->Id(),nodes[i]->Sid()+1,isonshelf[i]);
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::MinVel{{{1*/
-void  Tria::MinVel(double* pminvel, bool process_units){
-
-	/*Get minimum:*/
-	double minvel=this->inputs->Min(VelEnum);
-
-	/*process units if requested: */
-	if(process_units) minvel=UnitConversion(minvel,IuToExtEnum,VelEnum);
-
-	/*Assign output pointers:*/
-	*pminvel=minvel;
-}
-/*}}}*/
-/*FUNCTION Tria::MinVx{{{1*/
-void  Tria::MinVx(double* pminvx, bool process_units){
-
-	/*Get minimum:*/
-	double minvx=this->inputs->Min(VxEnum);
-
-	/*process units if requested: */
-	if(process_units) minvx=UnitConversion(minvx,IuToExtEnum,VxEnum);
-
-	/*Assign output pointers:*/
-	*pminvx=minvx;
-}
-/*}}}*/
-/*FUNCTION Tria::MinVy{{{1*/
-void  Tria::MinVy(double* pminvy, bool process_units){
-
-	/*Get minimum:*/
-	double minvy=this->inputs->Min(VyEnum);
-
-	/*process units if requested: */
-	if(process_units) minvy=UnitConversion(minvy,IuToExtEnum,VyEnum);
-
-	/*Assign output pointers:*/
-	*pminvy=minvy;
-}
-/*}}}*/
-/*FUNCTION Tria::MinVz{{{1*/
-void  Tria::MinVz(double* pminvz, bool process_units){
-
-	/*Get minimum:*/
-	double minvz=this->inputs->Min(VzEnum);
-
-	/*process units if requested: */
-	if(process_units) minvz=UnitConversion(minvz,IuToExtEnum,VzEnum);
-
-	/*Assign output pointers:*/
-	*pminvz=minvz;
-}
-/*}}}*/
-/*FUNCTION Tria::MyRank {{{1*/
-int    Tria::MyRank(void){ 
-	extern int my_rank;
-	return my_rank; 
-}
-/*}}}*/
-/*FUNCTION Tria::NodalValue {{{1*/
-int    Tria::NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units){
-
-	int i;
-	int found=0;
-	double value;
-	Input* data=NULL;
-	GaussTria *gauss                            = NULL;
-
-	/*First, serarch the input: */
-	data=inputs->GetInput(natureofdataenum); 
-
-	/*figure out if we have the vertex id: */
-	found=0;
-	for(i=0;i<NUMVERTICES;i++){
-		if(index==nodes[i]->GetVertexId()){
-			/*Do we have natureofdataenum in our inputs? :*/
-			if(data){
-				/*ok, we are good. retrieve value of input at vertex :*/
-				gauss=new GaussTria(); gauss->GaussVertex(i);
-				data->GetParameterValue(&value,gauss);
-				found=1;
-				break;
-			}
-		}
-	}
-
-	if(found)*pvalue=value;
-	return found;
-}
-/*}}}*/
-/*FUNCTION Tria::PatchFill{{{1*/
-void  Tria::PatchFill(int* prow, Patch* patch){
-
-	int i,row;
-	int vertices_ids[3];
-
-	/*recover pointer: */
-	row=*prow;
-		
-	for(i=0;i<3;i++) vertices_ids[i]=nodes[i]->GetVertexId(); //vertices id start at column 3 of the patch.
-
-	for(i=0;i<this->results->Size();i++){
-		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
-
-		/*For this result,fill the information in the Patch object (element id + vertices ids), and then hand 
-		 *it to the result object, to fill the rest: */
-		patch->fillelementinfo(row,this->sid+1,vertices_ids,3);
-		elementresult->PatchFill(row,patch);
-
-		/*increment rower: */
-		row++;
-	}
-
-	/*Assign output pointers:*/
-	*prow=row;
-}
-/*}}}*/
-/*FUNCTION Tria::PatchSize{{{1*/
-void  Tria::PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes){
-
-	int     i;
-	int     numrows     = 0;
-	int     numnodes    = 0;
-	int     temp_numnodes    = 0;
-
-	/*Go through all the results objects, and update the counters: */
-	for (i=0;i<this->results->Size();i++){
-		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
-		/*first, we have one more result: */
-		numrows++;
-		/*now, how many vertices and how many nodal values for this result? :*/
-		temp_numnodes=elementresult->NumberOfNodalValues(); //ask result object.
-		if(temp_numnodes>numnodes)numnodes=temp_numnodes;
-	}
-
-	/*Assign output pointers:*/
-	*pnumrows=numrows;
-	*pnumvertices=NUMVERTICES;
-	*pnumnodes=numnodes;
-}
-/*}}}*/
-/*FUNCTION Tria::PotentialSheetUngrounding{{{1*/
-void  Tria::PotentialSheetUngrounding(Vec potential_sheet_ungrounding){
-
-
-	double *values         = NULL;
-	double  h[3],s[3],b[3],ba[3];
-	double  bed_hydro;
-	double  rho_water,rho_ice,density;
-	int     i;
-	bool    elementonshelf = false;
-
-	/*Recover info at the vertices: */
-	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
-	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-
-	/*material parameters: */
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	density=rho_ice/rho_water;
-
-	/*go through vertices, and figure out which ones are on the ice sheet, and want to unground: */
-	for(i=0;i<3;i++){
-		if (!nodes[i]->IsOnShelf()){
-			
-			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
-			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
-			bed_hydro=-density*h[i];
-			if (bed_hydro>ba[i]){
-				/*ok, this node wants to unground. flag it: */
-				VecSetValue(potential_sheet_ungrounding,nodes[i]->Sid(),1,INSERT_VALUES);
-			}
-		}
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::ProcessResultsUnits{{{1*/
-void  Tria::ProcessResultsUnits(void){
-
-	int i;
-
-	for(i=0;i<this->results->Size();i++){
-		ElementResult* elementresult=(ElementResult*)this->results->GetObjectByOffset(i);
-		elementresult->ProcessUnits(this->parameters);
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::RheologyBbarx{{{1*/
-double Tria::RheologyBbarx(void){
-
-	return this->matice->GetBbar();
-
-}
-/*}}}*/
-/*FUNCTION Tria::RequestedOutput{{{1*/
-void Tria::RequestedOutput(int output_enum,int step,double time){
-
-	if(IsInput(output_enum)){
-		/*just transfer this input to results, and we are done: */
-		InputToResult(output_enum,step,time);
-	}
-	else{
-		/*this input does not exist, compute it, and then transfer to results: */
-		switch(output_enum){
-			default:
-				/*do nothing, no need to derail the computation because one of the outputs requested cannot be found: */
-				break;
-		}
-	}
-
-}
-/*}}}*/
-/*FUNCTION Tria::SetClone {{{1*/
-void  Tria::SetClone(int* minranks){
-
-	_error_("not implemented yet");
-}
-/*}}}1*/
-/*FUNCTION Tria::SetCurrentConfiguration {{{1*/
-void  Tria::SetCurrentConfiguration(Elements* elementsin, Loads* loadsin, DataSet* nodesin, Materials* materialsin, Parameters* parametersin){
+	/*Intermediaries */
+	int        i,j,ig;
+	double     xyz_list[NUMVERTICES][3];
+	double     dhdt_g,basal_melting_g,surface_mass_balance_g,Jdettria;
+	double     L[NUMVERTICES];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
+	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
+	Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);             _assert_(dhdt_input);
 	
-	/*go into parameters and get the analysis_counter: */
-	int analysis_counter;
-	parametersin->FindParam(&analysis_counter,AnalysisCounterEnum);
-
-	/*Get Element type*/
-	this->element_type=this->element_type_list[analysis_counter];
-
-	/*Pick up nodes*/
-	if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
-	else this->nodes=NULL;
-
-}
-/*}}}*/
-/*FUNCTION Tria::ShelfSync{{{1*/
-void  Tria::ShelfSync(void){
-
-
-	double *values         = NULL;
-	double  h[3],s[3],b[3],ba[3];
-	double  bed_hydro;
-	double  rho_water,rho_ice,density;
-	int     i;
-	bool    elementonshelf = false;
-
-	/*melting rate at the grounding line: */
-	double  yts;
-	int     swap;
-	double  gl_melting_rate;
-
-	/*recover parameters: */
-	parameters->FindParam(&yts,ConstantsYtsEnum);
-	parameters->FindParam(&gl_melting_rate,GroundinglineMeltingRateEnum);
-
-	/*Recover info at the vertices: */
-	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
-	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-
-	/*material parameters: */
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	density=rho_ice/rho_water;
-
-	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
-	for(i=0;i<3;i++){
-		if(b[i]==ba[i]){
-				
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
-		}
-		else{
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
-
-		}
-	}
-
-	/*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
-	swap=0;
-	elementonshelf=false;
-	for(i=0;i<3;i++){
-		if(nodes[i]->IsOnShelf()){
-			elementonshelf=true;
-			break;
-		}
-	}
-	if(!this->IsOnShelf() && elementonshelf==true)swap=1;
-    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
-	
-    /*If this element just  became ungrounded, set its basal melting rate at 50 m/yr:*/
-	if(swap){
-		Input* basal_melting_rate_input     =inputs->GetInput(BasalforcingsMeltingRateEnum);     _assert_(basal_melting_rate_input);
-		basal_melting_rate_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=gl_melting_rate/yts;
-	}
-
-
-}
-/*}}}*/
-/*FUNCTION Tria::SoftMigration{{{1*/
-void  Tria::SoftMigration(double* sheet_ungrounding){
-
-
-	double *values         = NULL;
-	double  h[3],s[3],b[3],ba[3];
-	double  bed_hydro;
-	double  rho_water,rho_ice,density;
-	int     i;
-	bool    elementonshelf = false;
-
-	/*Recover info at the vertices: */
-	Input* surface_input =inputs->GetInput(SurfaceEnum); _assert_(surface_input);
-	Input* bed_input     =inputs->GetInput(BedEnum);     _assert_(bed_input);
-	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-
-	/*material parameters: */
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	density=rho_ice/rho_water;
-	
-	/*go through vertices, and update inputs, considering them to be TriaVertex type: */
-	for(i=0;i<3;i++){
-		if (nodes[i]->IsOnShelf()){
-			/*This node is on the shelf. See if its bed is going under the bathymetry: */
-			if(b[i]<=ba[i]){ //<= because Neff being 0 when b=ba, drag will be 0 anyway.
-				/*The ice shelf is getting grounded, the thickness is the same, so just update the bed to stick to the bathymetry and elevate the surface accordingly: */
-				b[i]=ba[i];
-				s[i]=b[i]+h[i];
-			}
-			else{
-				/*do nothing, we are still floating.*/
-			}
-		}
-		else{
-			/*This node is on the sheet, near the grounding line. See if wants to unground. To 
-			 * do so, we compute the hydrostatic bed, and if it is > bathymetry, then we unground: */
-			bed_hydro=-density*h[i];
-			if (bed_hydro>ba[i]){
-
-				/*Now, are we connected to the grounding line, if so, go forward, otherwise, bail out: */
-				if(sheet_ungrounding[nodes[i]->Sid()]){
-					/*We are now floating, bed and surface are determined from hydrostatic equilibrium: */
-					s[i]=(1-density)*h[i];
-					b[i]=-density*h[i];
-				}
-			}
-			else{
-				/*do nothing, we are still grounded.*/
-			}
-		}
-	}
-
-	/*Surface and bed are updated. Update inputs:*/    
-	surface_input->GetValuesPtr(&values,NULL); for(i=0;i<3;i++)values[i]=s[i];
-	bed_input->GetValuesPtr(&values,NULL);     for(i=0;i<3;i++)values[i]=b[i];
-
-	}
-/*}}}*/
-/*FUNCTION Tria::SurfaceArea {{{1*/
-double Tria::SurfaceArea(void){
-
-	int    i;
-	double S;
-	double normal[3];
-	double v13[3],v23[3];
-	double xyz_list[NUMVERTICES][3];
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
+		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
+		dhdt_input->GetParameterValue(&dhdt_g,gauss);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
+
+		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancethickness_DG {{{1*/
+ElementVector* Tria::CreatePVectorBalancethickness_DG(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     xyz_list[NUMVERTICES][3];
+	double     basal_melting_g,surface_mass_balance_g,dhdt_g,Jdettria;
+	double     L[NUMVERTICES];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
 	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	for (i=0;i<3;i++){
-		v13[i]=xyz_list[0][i]-xyz_list[2][i];
-		v23[i]=xyz_list[1][i]-xyz_list[2][i];
-	}
-
-	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
-	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
-	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
-
-	S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
-
-	/*Return: */
-	return S;
-}
-/*}}}*/
-/*FUNCTION Tria::SurfaceNormal{{{1*/
-void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
-
-	int i;
-	double v13[3],v23[3];
-	double normal[3];
-	double normal_norm;
-
-	for (i=0;i<3;i++){
-		v13[i]=xyz_list[0][i]-xyz_list[2][i];
-		v23[i]=xyz_list[1][i]-xyz_list[2][i];
-	}
-
-	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
-	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
-	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
-
-	normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
-
-	*(surface_normal)=normal[0]/normal_norm;
-	*(surface_normal+1)=normal[1]/normal_norm;
-	*(surface_normal+2)=normal[2]/normal_norm;
-}
-/*}}}*/
-/*FUNCTION Tria::TimeAdapt{{{1*/
-double  Tria::TimeAdapt(void){
-
-	/*intermediary: */
-	int    i;
-	double C,dt;
-	double dx,dy;
-	double maxx,minx;
-	double maxy,miny;
-	double maxabsvx,maxabsvy;
-	double xyz_list[NUMVERTICES][3];
-
-	/*get CFL coefficient:*/
-	this->parameters->FindParam(&C,TimesteppingCflCoefficientEnum);
-
-	/*Get for Vx and Vy, the max of abs value: */
-	this->MaxAbsVx(&maxabsvx,false);
-	this->MaxAbsVy(&maxabsvy,false);
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], this->nodes, NUMVERTICES);
-
-	minx=xyz_list[0][0];
-	maxx=xyz_list[0][0];
-	miny=xyz_list[0][1];
-	maxy=xyz_list[0][1];
-
-	for(i=1;i<NUMVERTICES;i++){
-		if (xyz_list[i][0]<minx)minx=xyz_list[i][0];
-		if (xyz_list[i][0]>maxx)maxx=xyz_list[i][0];
-		if (xyz_list[i][1]<miny)miny=xyz_list[i][1];
-		if (xyz_list[i][1]>maxy)maxy=xyz_list[i][1];
-	}
-	dx=maxx-minx;
-	dy=maxy-miny;
-
-	/*CFL criterion: */
-	dt=C/(maxabsvy/dx+maxabsvy/dy);
-
-	return dt;
-}
-/*}}}*/
-/*FUNCTION Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){{{1*/
-void Tria::Update(int index, IoModel* iomodel,int analysis_counter,int analysis_type){ //i is the element index
-
-	/*Intermediaries*/
-	int    i,j;
-	int    tria_node_ids[3];
-	int    tria_vertex_ids[3];
-	int    tria_type;
-	double nodeinputs[3];
-	double yts;
-	int    progstabilization,balancestabilization;
-	bool   dakota_analysis;
-
-	/*Checks if debuging*/
-	/*{{{2*/
-	_assert_(iomodel->Data(MeshElementsEnum));
-	/*}}}*/
-
-	/*Fetch parameters: */
-	iomodel->Constant(&yts,ConstantsYtsEnum);
-	iomodel->Constant(&progstabilization,PrognosticStabilizationEnum);
-	iomodel->Constant(&balancestabilization,BalancethicknessStabilizationEnum);
-	iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
-
-	/*Recover element type*/
-	if ((analysis_type==PrognosticAnalysisEnum && progstabilization==3) || (analysis_type==BalancethicknessAnalysisEnum && balancestabilization==3)){
-		/*P1 Discontinuous Galerkin*/
-		tria_type=P1DGEnum;
-	}
-	else{
-		/*P1 Continuous Galerkin*/
-		tria_type=P1Enum;
-	}
-	this->SetElementType(tria_type,analysis_counter);
-
-	/*Recover vertices ids needed to initialize inputs*/
-	for(i=0;i<3;i++){ 
-		tria_vertex_ids[i]=(int)iomodel->Data(MeshElementsEnum)[3*index+i]; //ids for vertices are in the elements array from Matlab
-	}
-
-	/*Recover nodes ids needed to initialize the node hook.*/
-	if (tria_type==P1DGEnum){
-		/*Discontinuous Galerkin*/
-		tria_node_ids[0]=iomodel->nodecounter+3*index+1;
-		tria_node_ids[1]=iomodel->nodecounter+3*index+2;
-		tria_node_ids[2]=iomodel->nodecounter+3*index+3;
-	}
-	else{
-		/*Continuous Galerkin*/
-		for(i=0;i<3;i++){ 
-			tria_node_ids[i]=iomodel->nodecounter+(int)*(iomodel->Data(MeshElementsEnum)+3*index+i); //ids for vertices are in the elements array from Matlab
-		}
-	}
-
-	/*hooks: */
-	this->SetHookNodes(tria_node_ids,analysis_counter); this->nodes=NULL; //set hook to nodes, for this analysis type
-
-	/*Fill with IoModel*/
-	this->InputUpdateFromIoModel(index,iomodel);
-
-	/*Defaults if not provided in iomodel*/
-	switch(analysis_type){
-
-		case DiagnosticHorizAnalysisEnum:
-
-			/*default vx,vy and vz: either observation or 0 */
-			if(!iomodel->Data(VxEnum)){
-				if (iomodel->Data(InversionVxObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVxObsEnum)[tria_vertex_ids[i]-1]/yts;
-				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
-				this->inputs->AddInput(new TriaVertexInput(VxEnum,nodeinputs));
-				this->inputs->AddInput(new TriaVertexInput(VxPicardEnum,nodeinputs));
-				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVxEnum,nodeinputs));
-			}
-			if(!iomodel->Data(VyEnum)){
-				if (iomodel->Data(InversionVyObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVyObsEnum)[tria_vertex_ids[i]-1]/yts;
-				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
-				this->inputs->AddInput(new TriaVertexInput(VyEnum,nodeinputs));
-				this->inputs->AddInput(new TriaVertexInput(VyPicardEnum,nodeinputs));
-				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVyEnum,nodeinputs));
-			}
-			if(!iomodel->Data(VzEnum)){
-				if (iomodel->Data(InversionVzObsEnum)) for(i=0;i<3;i++)nodeinputs[i]=iomodel->Data(InversionVzObsEnum)[tria_vertex_ids[i]-1]/yts;
-				else                 for(i=0;i<3;i++)nodeinputs[i]=0;
-				this->inputs->AddInput(new TriaVertexInput(VzEnum,nodeinputs));
-				this->inputs->AddInput(new TriaVertexInput(VzPicardEnum,nodeinputs));
-				if(dakota_analysis) this->inputs->AddInput(new TriaVertexInput(QmuVzEnum,nodeinputs));
-			}
-			if(!iomodel->Data(PressureEnum)){
-				for(i=0;i<3;i++)nodeinputs[i]=0;
-				if(dakota_analysis){
-					this->inputs->AddInput(new TriaVertexInput(PressureEnum,nodeinputs));
-					this->inputs->AddInput(new TriaVertexInput(QmuPressureEnum,nodeinputs));
-				}
-			}
-			break;
-
-		default:
-			/*No update for other solution types*/
-			break;
-
-	}
-
-	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
-	this->parameters=NULL;
-}
-/*}}}*/
-/*FUNCTION Tria::UpdateShelfStatus{{{1*/
-int  Tria::UpdateShelfStatus(Vec new_shelf_nodes){
-
-	int     i;
-
-	double  h[3];
-	double  s[3];
-	double  b[3];
-	double  ba[3];
-	Input  *surface_input  = NULL;
-	Input  *bed_input      = NULL;
-	double  rho_water;
-	double  rho_ice;
-	double  density;
-	bool    elementonshelf = false;
-	int     flipped=0;
-	int     shelfstatus[3];
-
-
-	/*Recover info at the vertices: */
-	surface_input   =inputs->GetInput(SurfaceEnum);   _assert_(surface_input);
-	bed_input   =inputs->GetInput(BedEnum);   _assert_(bed_input);
-	if((surface_input->Enum()!=TriaVertexInputEnum) | (bed_input->Enum()!=TriaVertexInputEnum))_error_(" not supported yet for bed and surface interpolations not P1!");
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-
-	/*material parameters: */
-	rho_water=matpar->GetRhoWater();
-	rho_ice=matpar->GetRhoIce();
-	density=rho_ice/rho_water;
-
-	/*Initialize current status of nodes: */
-	for(i=0;i<3;i++){
-		shelfstatus[i]=nodes[i]->IsOnShelf();
-		if((nodes[i]->Sid()+1)==36) printf("UpdateShelfStatus: El %i Node %i shelf status %i\n",this->Id(),nodes[i]->Sid()+1,shelfstatus[i]);
-	}
-	
-	/*go through vertices, and figure out if they are grounded or not, then update their status: */
-	flipped=0;
-	for(i=0;i<3;i++){
-		if(b[i]<=ba[i]){ //the = will lead to oscillations.
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,false));
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,true));
-			if(shelfstatus[i]){
-				flipped++;
-				if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i grounding %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-			VecSetValue(new_shelf_nodes,nodes[i]->Sid(),0,INSERT_VALUES);
-		}
-		else{
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,true));
-			nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,false));
-			if(!shelfstatus[i]){
-				flipped++;
-				if((nodes[i]->Sid()+1)==36)printf("UpdateShelfStatus: El %i Node %i floating %g %g %g\n",this->Id(),nodes[i]->Sid()+1,b[i],ba[i],s[i]);
-			}
-			VecSetValue(new_shelf_nodes,nodes[i]->Sid(),1,INSERT_VALUES);
-		}
-	}
-
-	/*Now, update  shelf status of element. An element can only be on shelf if all its nodes are on shelf: */
-	elementonshelf=false;
-	for(i=0;i<3;i++){
-		if(nodes[i]->IsOnShelf()){
-			elementonshelf=true;
-			break;
-		}
-	}
-    this->inputs->AddInput(new BoolInput(MaskElementonfloatingiceEnum,elementonshelf));
-
-	 return flipped;
-}
-/*}}}*/
-/*FUNCTION Tria::UpdateShelfFlags{{{1*/
-void Tria::UpdateShelfFlags(double* new_shelf_nodes){
-
-	/*go through vertices, and update the status of MaskVertexonfloatingiceEnum and MaskVertexongroundediceEnum flags: */
-	bool flag;
-	int  i;
-	double  h[3];
-	double  s[3];
-	double  b[3];
-	double  ba[3];
-
-	GetParameterListOnVertices(&h[0],ThicknessEnum);
-	GetParameterListOnVertices(&s[0],SurfaceEnum);
-	GetParameterListOnVertices(&b[0],BedEnum);
-	GetParameterListOnVertices(&ba[0],BathymetryEnum);
-
-	for(i=0;i<3;i++){
-		flag=(bool)new_shelf_nodes[nodes[i]->Sid()];
-		nodes[i]->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,flag));
-		nodes[i]->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,!flag));
-	}
-}
-/*}}}*/
-/*FUNCTION Tria::UpdatePotentialSheetUngrounding{{{1*/
-int Tria::UpdatePotentialSheetUngrounding(double* potential_sheet_ungrounding,Vec vec_nodes_on_iceshelf,double* nodes_on_iceshelf){
-
-	/*intermediary: */
-	int i;
-	int nflipped=0;
-
-	/*Ok, go through our 3 nodes, and whoever is on the potential_sheet_ungrounding, ends up in nodes_on_iceshelf: */
-	for(i=0;i<3;i++){
-		if (potential_sheet_ungrounding[nodes[i]->Sid()]){
-			VecSetValue(vec_nodes_on_iceshelf,nodes[i]->Sid(),1,INSERT_VALUES);
-		
-			/*Figure out if we flipped: */
-			if (potential_sheet_ungrounding[nodes[i]->Sid()] != nodes_on_iceshelf[nodes[i]->Sid()])nflipped++;
-		}
-	}
-	return nflipped;
-}
-/*}}}*/
+	Input* surface_mass_balance_input=inputs->GetInput(SurfaceforcingsMassBalanceEnum); _assert_(surface_mass_balance_input);
+	Input* basal_melting_input=inputs->GetInput(BasalforcingsMeltingRateEnum);          _assert_(basal_melting_input);
+	Input* dhdt_input=inputs->GetInput(BalancethicknessThickeningRateEnum);                                       _assert_(dhdt_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for(ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
+		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
+		dhdt_input->GetParameterValue(&dhdt_g,gauss);
+
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss);
+		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
+
+		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(surface_mass_balance_g-basal_melting_g-dhdt_g)*L[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+#endif
+
Index: /issm/trunk/src/c/objects/Elements/Tria.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.h	(revision 9774)
+++ /issm/trunk/src/c/objects/Elements/Tria.h	(revision 9775)
@@ -89,29 +89,5 @@
 		void   GetSolutionFromInputs(Vec solution);
 		void   GetVectorFromInputs(Vec vector,int NameEnum);
-		#ifdef _HAVE_CONTROL_
-		double DragCoefficientAbsGradient(bool process_units,int weight_index);
-		void   Gradj(Vec gradient,int control_type);
-		void   GradjBGradient(Vec gradient,int weight_index);
-		void   GradjBMacAyeal(Vec gradient);
-		void   GradjDragMacAyeal(Vec gradient);
-		void   GradjDragStokes(Vec gradient);
-		void   GradjDragGradient(Vec gradient,int weight_index);
-		void   GradjDhDtBalancedthickness(Vec gradient);
-		void   GradjVxBalancedthickness(Vec gradient);
-		void   GradjVyBalancedthickness(Vec gradient);
-		void   ControlInputGetGradient(Vec gradient,int enum_type);
-		void   ControlInputScaleGradient(int enum_type,double scale);
-		void   ControlInputSetGradient(double* gradient,int enum_type);
-		double RheologyBbarAbsGradient(bool process_units,int weight_index);
-		double ThicknessAbsMisfit(     bool process_units,int weight_index);
-		double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
-		double ThicknessAbsGradient(bool process_units,int weight_index);
-		double SurfaceRelVelMisfit(    bool process_units,int weight_index);
-		double SurfaceLogVelMisfit(    bool process_units,int weight_index);
-		double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
-		double SurfaceAverageVelMisfit(bool process_units,int weight_index);
-		void   InputControlUpdate(double scalar,bool save_parameter);
-		#endif
-
+		
 		void   InputArtificialNoise(int enum_type,double min, double max);
 		bool   InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums);
@@ -121,5 +97,5 @@
 		void   InputDuplicate(int original_enum,int new_enum);
 		void   InputScale(int enum_type,double scale_factor);
-				void   InputToResult(int enum_type,int step,double time);
+		void   InputToResult(int enum_type,int step,double time);
 		void   DeleteResults(void);
 		void   MaterialUpdateFromTemperature(void){_error_("not implemented yet");};
@@ -154,16 +130,37 @@
 		double RheologyBbarx(void);
 		int    NodalValue(double* pvalue, int index, int natureofdataenum,bool process_units);
+
+
+		#ifdef _HAVE_CONTROL_
+		double DragCoefficientAbsGradient(bool process_units,int weight_index);
+		void   Gradj(Vec gradient,int control_type);
+		void   GradjBGradient(Vec gradient,int weight_index);
+		void   GradjBMacAyeal(Vec gradient);
+		void   GradjDragMacAyeal(Vec gradient);
+		void   GradjDragStokes(Vec gradient);
+		void   GradjDragGradient(Vec gradient,int weight_index);
+		void   GradjDhDtBalancedthickness(Vec gradient);
+		void   GradjVxBalancedthickness(Vec gradient);
+		void   GradjVyBalancedthickness(Vec gradient);
+		void   ControlInputGetGradient(Vec gradient,int enum_type);
+		void   ControlInputScaleGradient(int enum_type,double scale);
+		void   ControlInputSetGradient(double* gradient,int enum_type);
+		double RheologyBbarAbsGradient(bool process_units,int weight_index);
+		double ThicknessAbsMisfit(     bool process_units,int weight_index);
+		double SurfaceAbsVelMisfit(    bool process_units,int weight_index);
+		double ThicknessAbsGradient(bool process_units,int weight_index);
+		double SurfaceRelVelMisfit(    bool process_units,int weight_index);
+		double SurfaceLogVelMisfit(    bool process_units,int weight_index);
+		double SurfaceLogVxVyMisfit(   bool process_units,int weight_index);
+		double SurfaceAverageVelMisfit(bool process_units,int weight_index);
+		void   InputControlUpdate(double scalar,bool save_parameter);
+		#endif
+
 		/*}}}*/
 		/*Tria specific routines:{{{1*/
-		ElementMatrix* CreateKMatrixAdjointBalancethickness(void);
 		ElementMatrix* CreateKMatrixBalancethickness(void);
 		ElementMatrix* CreateKMatrixBalancethickness_DG(void);
 		ElementMatrix* CreateKMatrixBalancethickness_CG(void);
-		ElementMatrix* CreateKMatrixDiagnosticMacAyeal(void);
-		ElementMatrix* CreateKMatrixDiagnosticMacAyealViscous(void);
-		ElementMatrix* CreateKMatrixDiagnosticMacAyealFriction(void);
-		ElementMatrix* CreateKMatrixDiagnosticHutter(void);
 		ElementMatrix* CreateKMatrixMelting(void);
-		ElementMatrix* CreateKMatrixHydrology(void);
 		ElementMatrix* CreateKMatrixPrognostic(void);
 		ElementMatrix* CreateKMatrixPrognostic_CG(void);
@@ -173,38 +170,57 @@
 		ElementVector* CreatePVectorBalancethickness_DG(void);
 		ElementVector* CreatePVectorBalancethickness_CG(void);
-		ElementVector* CreatePVectorDiagnosticMacAyeal(void);
-		ElementVector* CreatePVectorAdjointHoriz(void);
-		ElementVector* CreatePVectorAdjointStokes(void);
-		ElementVector* CreatePVectorAdjointBalancethickness(void);
-		ElementVector* CreatePVectorDiagnosticHutter(void);
-		ElementVector* CreatePVectorHydrology(void);
 		ElementVector* CreatePVectorPrognostic(void);
 		ElementVector* CreatePVectorPrognostic_CG(void);
 		ElementVector* CreatePVectorPrognostic_DG(void);
 		ElementVector* CreatePVectorSlope(void);
-		double  GetArea(void);
-		int     GetElementType(void);
-		void	  GetDofList(int** pdoflist,int approximation_enum,int setenum);
-		void    CreateHydrologyWaterVelocityInput(void);
-		void	  GetDofList1(int* doflist);
-		void    GetSidList(int* sidlist);
-		void    GetParameterListOnVertices(double* pvalue,int enumtype);
-		void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
-		void    GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index); //TO BE REMOVED
-		void    GetParameterValue(double* pvalue,Node* node,int enumtype);
+		double         GetArea(void);
+		int            GetElementType(void);
+		void	       GetDofList(int** pdoflist,int approximation_enum,int setenum);
+		void	       GetDofList1(int* doflist);
+		void           GetSidList(int* sidlist);
+		void           GetParameterListOnVertices(double* pvalue,int enumtype);
+		void           GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue);
+		void           GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index); //TO BE REMOVED
+		void           GetParameterValue(double* pvalue,Node* node,int enumtype);
+		void           GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input);
+		void	       InputUpdateFromSolutionOneDof(double* solution,int enum_type);
+		void	       InputUpdateFromSolutionPrognostic(double* solution);
+		bool	       IsInput(int name);
+		void	       SetClone(int* minranks);
+		void	       SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+
+		
+		#ifdef _HAVE_DIAGNOSTIC_
+		ElementMatrix* CreateKMatrixDiagnosticMacAyeal(void);
+		ElementMatrix* CreateKMatrixDiagnosticMacAyealViscous(void);
+		ElementMatrix* CreateKMatrixDiagnosticMacAyealFriction(void);
+		ElementMatrix* CreateKMatrixDiagnosticHutter(void);
+		ElementVector* CreatePVectorDiagnosticMacAyeal(void);
+		ElementVector* CreatePVectorDiagnosticHutter(void);
 		void	  GetSolutionFromInputsDiagnosticHoriz(Vec solution);
 		void	  GetSolutionFromInputsDiagnosticHutter(Vec solution);
-		void	  GetSolutionFromInputsHydrology(Vec solution);
-		void    GetStrainRate2d(double* epsilon,double* xyz_list, GaussTria* gauss, Input* vx_input, Input* vy_input);
+		void	  InputUpdateFromSolutionDiagnosticHoriz( double* solution);
+		void	  InputUpdateFromSolutionDiagnosticHutter( double* solution);
+		#endif
+
+		#ifdef _HAVE_CONTROL_
+		ElementMatrix* CreateKMatrixAdjointBalancethickness(void);
+		ElementVector* CreatePVectorAdjointHoriz(void);
+		ElementVector* CreatePVectorAdjointStokes(void);
+		ElementVector* CreatePVectorAdjointBalancethickness(void);
 		void	  InputUpdateFromSolutionAdjointBalancethickness( double* solution);
 		void	  InputUpdateFromSolutionAdjointHoriz( double* solution);
-		void	  InputUpdateFromSolutionDiagnosticHoriz( double* solution);
-		void	  InputUpdateFromSolutionDiagnosticHutter( double* solution);
-		void	  InputUpdateFromSolutionOneDof(double* solution,int enum_type);
-		void	  InputUpdateFromSolutionPrognostic(double* solution);
+		#endif
+
+		#ifdef _HAVE_HYDROLOGY_
+		ElementMatrix* CreateKMatrixHydrology(void);
+		ElementVector* CreatePVectorHydrology(void);
+		void      CreateHydrologyWaterVelocityInput(void);
+		void	  GetSolutionFromInputsHydrology(Vec solution);
 		void	  InputUpdateFromSolutionHydrology(double* solution);
-		bool	  IsInput(int name);
-		void	  SetClone(int* minranks);
-		void	  SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+		#endif
+		#ifdef _HAVE_BALANCED_
+		#endif
+
 		/*}}}*/
 
Index: /issm/trunk/src/c/objects/Loads/Icefront.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Icefront.cpp	(revision 9774)
+++ /issm/trunk/src/c/objects/Loads/Icefront.cpp	(revision 9775)
@@ -436,4 +436,5 @@
 		case MacAyeal2dIceFrontEnum:
 			return CreatePVectorDiagnosticMacAyeal2d();
+        #ifdef _HAVE_THREED_
 		case MacAyeal3dIceFrontEnum:
 			return CreatePVectorDiagnosticMacAyeal3d();
@@ -442,4 +443,5 @@
 		case StokesIceFrontEnum:
 			return CreatePVectorDiagnosticStokes();
+	    #endif
 		default:
 			_error_("Icefront type %s not supported yet",EnumToStringx(type));
@@ -532,4 +534,5 @@
 }
 /*}}}*/
+#ifdef _HAVE_THREED_
 /*FUNCTION Icefront::CreatePVectorDiagnosticMacAyeal3d{{{1*/
 ElementVector* Icefront::CreatePVectorDiagnosticMacAyeal3d(void){
@@ -709,4 +712,5 @@
 }
 /*}}}*/
+#endif
 /*FUNCTION Icefront::GetDofList {{{1*/
 void  Icefront::GetDofList(int** pdoflist,int approximation_enum,int setenum){
Index: /issm/trunk/src/c/objects/Loads/Icefront.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Icefront.h	(revision 9774)
+++ /issm/trunk/src/c/objects/Loads/Icefront.h	(revision 9775)
@@ -81,7 +81,9 @@
 		ElementVector* CreatePVectorDiagnosticHoriz(void);
 		ElementVector* CreatePVectorDiagnosticMacAyeal2d(void);
+        #ifdef _HAVE_THREED_
 		ElementVector* CreatePVectorDiagnosticMacAyeal3d(void);
 		ElementVector* CreatePVectorDiagnosticPattyn(void);
 		ElementVector* CreatePVectorDiagnosticStokes(void);
+	    #endif
 		void  GetDofList(int** pdoflist,int approximation_enum,int setenum);
 		void GetSegmentNormal(double* normal,double xyz_list[2][3]);
Index: /issm/trunk/src/c/objects/Loads/Riftfront.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Riftfront.cpp	(revision 9774)
+++ /issm/trunk/src/c/objects/Loads/Riftfront.cpp	(revision 9775)
@@ -851,18 +851,4 @@
 }
 /*}}}1*/
-/*FUNCTION Riftfront::OutputProperties {{{1*/
-void  Riftfront::OutputProperties(Vec riftproperties){
-
-	int row_id=0;
-	double value;
-
-	/*recover id of penalty: */
-	row_id=this->Id()-1; //c indexing, ids were matlab indexed
-	value=(double)this->fraction;
-
-	/*Plug id and fraction  into riftproperties matrix: */
-	VecSetValues(riftproperties,1,&row_id,&value,INSERT_VALUES);
-}
-/*}}}1*/
 /*FUNCTION Riftfront::Penetration {{{1*/
 int   Riftfront::Penetration(double* ppenetration){
Index: /issm/trunk/src/c/objects/Loads/Riftfront.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Riftfront.h	(revision 9774)
+++ /issm/trunk/src/c/objects/Loads/Riftfront.h	(revision 9775)
@@ -98,5 +98,4 @@
 		int   PotentialUnstableConstraint(int* punstable);
 		int   IsMaterialStable(void);
-		void  OutputProperties(Vec riftproperties);
 		bool  IsInput(int name);
 		/*}}}*/
Index: /issm/trunk/src/c/objects/Materials/Matice.cpp
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 9774)
+++ /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 9775)
@@ -706,4 +706,5 @@
 
 	/*if 3d*/
+	#ifdef _HAVE_THREED_
 	else if(dim==3){
 
@@ -745,4 +746,5 @@
 		#endif
 	}
+	#endif
 	else{
 		_error_(" Mesh type not supported yet!");
Index: /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp
===================================================================
--- /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp	(revision 9774)
+++ /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp	(revision 9775)
@@ -26,8 +26,15 @@
 	
 		case DiagnosticSolutionEnum:
+			#ifdef _HAVE_DIAGNOSTIC_
 			solutioncore=&diagnostic_core;
+			#else
+			_error_("ISSM was not compiled with diagnostic capabilities. Exiting");
+			#endif
 			break;
 		case SteadystateSolutionEnum:
+			#ifdef _HAVE_STEADYSTATE_
 			solutioncore=&steadystate_core;
+			_error_("ISSM was not compiled with steady state capabilities. Exiting");
+			#endif
 			break;
 		case ThermalSolutionEnum:
@@ -45,24 +52,52 @@
 			#endif
 			break;
-		case PrognosticSolutionEnum:
-			solutioncore=&prognostic_core;
+		case BalancethicknessSolutionEnum:
+			#ifdef _HAVE_BALANCED_
+			solutioncore=&balancethickness_core;
+			#else
+			_error_("ISSM was not compiled with balanced capabilities. Exiting");
+			#endif
 			break;
-		case BalancethicknessSolutionEnum:
-			solutioncore=&balancethickness_core;
+		case HydrologySolutionEnum:
+			#ifdef _HAVE_HYDROLOGY_
+			solutioncore=&hydrology_core;
+			#else
+			_error_("ISSM was not compiled with hydrology capabilities. Exiting");
+			#endif
 			break;
 		case SurfaceSlopeSolutionEnum:
+			#ifdef _HAVE_SLOPE_
 			solutioncore=&surfaceslope_core;
+			#else
+			_error_("ISSM was not compiled with slope capabilities. Exiting");
+			#endif
 			break;
 		case BedSlopeSolutionEnum:
+			#ifdef _HAVE_SLOPE_
 			solutioncore=&bedslope_core;
+			#else
+			_error_("ISSM was not compiled with slope capabilities. Exiting");
+			#endif
 			break;
 		case TransientSolutionEnum:
+			#ifdef _HAVE_TRANSIENT_
 			solutioncore=&transient_core;
+			#else
+			_error_("ISSM was not compiled with transient capabilities. Exiting");
+			#endif
 			break;
 		case GroundinglineMigration2dSolutionEnum:
+			#ifdef _HAVE_GROUNDINGLINE_
 			solutioncore=&groundinglinemigration2d_core;
+			#else
+			_error_("ISSM was not compiled with grounding line migration capabilities. Exiting");
+			#endif
 			break;
-		case HydrologySolutionEnum:
-			solutioncore=&hydrology_core;
+		case PrognosticSolutionEnum:
+			#ifdef _HAVE_PROGNOSTIC_
+			solutioncore=&prognostic_core;
+			#else
+			_error_("ISSM was not compiled with prognostic capabilities. Exiting");
+			#endif
 			break;
 		default:
Index: /issm/trunk/src/c/solutions/transient_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/transient_core.cpp	(revision 9774)
+++ /issm/trunk/src/c/solutions/transient_core.cpp	(revision 9775)
@@ -81,5 +81,10 @@
 		if(isdiagnostic){
 			_printf_(VerboseSolution(),"   computing new velocity\n");
+			#ifdef _HAVE_DIAGNOSTIC_
 			diagnostic_core(femmodel);
+			#else
+			_error_("ISSM was not compiled with diagnostic capabilities. Exiting");
+			#endif
+
 		}
 
@@ -94,5 +99,10 @@
 			if(dim==3) _error_("Grounding line migration not implemented in 3d");
 			_printf_(VerboseSolution(),"   computing new grounding line position\n");
+			#ifdef _HAVE_DIAGNOSTIC_
 			GroundingLineMigrationx(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters);
+			#else
+			_error_("ISSM was not compiled with grounding line migration capabilities. Exiting");
+			#endif
+
 		}
 
Index: /issm/trunk/src/mex/Makefile.am
===================================================================
--- /issm/trunk/src/mex/Makefile.am	(revision 9774)
+++ /issm/trunk/src/mex/Makefile.am	(revision 9775)
@@ -54,5 +54,4 @@
 				NodesDof\
 				Orth\
-				OutputRifts\
 				OutputResults\
 				ParsePetscOptions\
@@ -261,7 +260,4 @@
 			  Orth/Orth.h
 
-OutputRifts_SOURCES = OutputRifts/OutputRifts.cpp\
-			  OutputRifts/OutputRifts.h
-
 OutputResults_SOURCES = OutputResults/OutputResults.cpp\
 			  OutputResults/OutputResults.h
