Index: /issm/trunk/src/ad/Makefile.am
===================================================================
--- /issm/trunk/src/ad/Makefile.am	(revision 9760)
+++ /issm/trunk/src/ad/Makefile.am	(revision 9761)
@@ -102,6 +102,4 @@
 					./objects/Inputs/DoubleInput.h\
 					./objects/Inputs/DoubleInput.cpp\
-					./objects/Inputs/ControlInput.h\
-					./objects/Inputs/ControlInput.cpp\
 					./objects/Inputs/DatasetInput.h\
 					./objects/Inputs/DatasetInput.cpp\
@@ -190,7 +188,4 @@
 					./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\
@@ -207,7 +202,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\
@@ -308,22 +300,8 @@
 					./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\
@@ -371,30 +349,10 @@
 					./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\
@@ -439,10 +397,4 @@
 					./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\
@@ -451,6 +403,4 @@
 					./modules/ConstraintsStatex/ConstraintsStateLocal.h\
 					./modules/ConstraintsStatex/RiftConstraintsState.cpp\
-					./modules/ConstraintsStatex/ThermalConstraintsState.cpp\
-					./modules/ConstraintsStatex/ThermalIsPresent.cpp\
 					./modules/Responsex/Responsex.h\
 					./modules/Responsex/Responsex.cpp\
@@ -459,5 +409,4 @@
 					./modules/ResetConstraintsx/ResetConstraintsx.h\
 					./modules/ResetConstraintsx/ResetConstraintsx.cpp\
-					./modules/ResetConstraintsx/ThermalConstraintsReset.cpp\
 					./modules/Solverx/Solverx.cpp\
 					./modules/Solverx/Solverx.h\
@@ -473,26 +422,9 @@
 					./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\
@@ -508,10 +440,7 @@
 					./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
+					./solvers/solver_stokescoupling_nonlinear.cpp
 
 
@@ -553,9 +482,91 @@
 					  ./modules/ModelProcessorx/Qmu/CreateParametersQmu.cpp\
 					  ./modules/AverageOntoPartitionx/AverageOntoPartitionx.h
-
-libDAKOTA_a_CXXFLAGS = -fPIC -D_PARALLEL_   -D_C_ $(CXXOPTFLAGS)
-endif
-
-#}}}
+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
+
+#}}}
+
 #Executable {{{1
 
Index: /issm/trunk/src/c/Container/DataSet.cpp
===================================================================
--- /issm/trunk/src/c/Container/DataSet.cpp	(revision 9760)
+++ /issm/trunk/src/c/Container/DataSet.cpp	(revision 9761)
@@ -19,4 +19,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../include/include.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
@@ -240,4 +241,5 @@
 				dataset->AddObject(transientinput);}
 				break;
+			#ifdef _HAVE_CONTROL_
 			case ControlInputEnum:{
 			   ControlInput* controlinputinput=NULL;
@@ -246,4 +248,5 @@
 				dataset->AddObject(controlinputinput);}
 				break;
+			#endif
 			case DatasetInputEnum:{
 				DatasetInput* datasetinputinput=NULL;
Index: /issm/trunk/src/c/Container/Options.cpp
===================================================================
--- /issm/trunk/src/c/Container/Options.cpp	(revision 9760)
+++ /issm/trunk/src/c/Container/Options.cpp	(revision 9761)
@@ -16,4 +16,5 @@
 #include "./DataSet.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../include/include.h"
 #include "../shared/shared.h"
Index: /issm/trunk/src/c/Makefile.am
===================================================================
--- /issm/trunk/src/c/Makefile.am	(revision 9760)
+++ /issm/trunk/src/c/Makefile.am	(revision 9761)
@@ -307,5 +307,4 @@
 					./shared/Threads/PartitionRange.cpp\
 					./shared/Matlab/matlabshared.h\
-					./shared/Matlab/PrintfFunction.cpp\
 					./shared/Matlab/ModuleBoot.cpp\
 					./shared/Matlab/mxGetAssignedField.cpp\
@@ -355,5 +354,4 @@
 					./shared/Elements/GetGlobalDofList.cpp\
 					./shared/Elements/GetNumberOfDofs.cpp\
-					./shared/String/DescriptorIndex.cpp\
 					./shared/String/sharedstring.h\
 					./shared/Bamg/Abs.h \
@@ -415,4 +413,5 @@
 					./io/Matlab/FetchMatlabData.cpp\
 					./io/Matlab/OptionParse.cpp\
+					./io/PrintfFunction.cpp\
 					./EnumDefinitions/EnumDefinitions.h\
 					./EnumDefinitions/EnumToModelField.cpp\
@@ -685,4 +684,5 @@
 					./modules/Dakotax/SpawnCore.cpp\
 					./modules/Dakotax/SpawnCoreSerial.cpp\
+					./modules/Dakotax/DescriptorIndex.cpp\
 					./modules/InputToResultx/InputToResultx.cpp\
 					./modules/InputToResultx/InputToResultx.h\
@@ -1000,5 +1000,4 @@
 					./shared/Alloc/alloc.cpp\
 					./shared/Matlab/matlabshared.h\
-					./shared/Matlab/PrintfFunction.cpp\
 					./shared/Matlab/ModuleBoot.cpp\
 					./shared/Matlab/mxGetAssignedField.cpp\
@@ -1046,5 +1045,4 @@
 					./shared/Elements/GetGlobalDofList.cpp\
 					./shared/Elements/GetNumberOfDofs.cpp\
-					./shared/String/DescriptorIndex.cpp\
 					./shared/String/sharedstring.h\
 					./shared/Bamg/Abs.h \
@@ -1104,4 +1102,5 @@
 					./io/Matlab/FetchMatlabData.cpp\
 					./io/Matlab/OptionParse.cpp\
+					./io/PrintfFunction.cpp\
 					./EnumDefinitions/EnumDefinitions.h\
 					./EnumDefinitions/EnumToModelField.cpp\
@@ -1366,4 +1365,5 @@
 					./modules/Dakotax/SpawnCore.cpp\
 					./modules/Dakotax/SpawnCoreParallel.cpp\
+					./modules/Dakotax/DescriptorIndex.cpp\
 					./modules/InputToResultx/InputToResultx.cpp\
 					./modules/InputToResultx/InputToResultx.h\
Index: /issm/trunk/src/c/include/globals.h
===================================================================
--- /issm/trunk/src/c/include/globals.h	(revision 9760)
+++ /issm/trunk/src/c/include/globals.h	(revision 9761)
@@ -6,6 +6,6 @@
 #define GLOBALS_H_
 
-extern int my_rank;
-extern int num_procs;
+int my_rank;
+int num_procs;
 
 #endif
Index: /issm/trunk/src/c/include/include.h
===================================================================
--- /issm/trunk/src/c/include/include.h	(revision 9760)
+++ /issm/trunk/src/c/include/include.h	(revision 9761)
@@ -6,5 +6,4 @@
 #define  _INCLUDEGLOBAL_H_
 
-#include "./globals.h"  
 #include "./macros.h"
 #include "./typedefs.h"
Index: /issm/trunk/src/c/io/Matlab/OptionParse.cpp
===================================================================
--- /issm/trunk/src/c/io/Matlab/OptionParse.cpp	(revision 9760)
+++ /issm/trunk/src/c/io/Matlab/OptionParse.cpp	(revision 9761)
@@ -9,4 +9,5 @@
 
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
 #include "./matlabio.h"
Index: /issm/trunk/src/c/io/PrintfFunction.cpp
===================================================================
--- /issm/trunk/src/c/io/PrintfFunction.cpp	(revision 9761)
+++ /issm/trunk/src/c/io/PrintfFunction.cpp	(revision 9761)
@@ -0,0 +1,64 @@
+/*\file PrintfFunction.c
+ *\brief: this function is used by the _printf_ macro, to take into account the 
+ *fact we may be running on a cluster. 
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "../shared/shared.h"
+#include "../include/include.h"
+
+#ifdef _SERIAL_
+#include "mex.h"
+#endif
+
+int PrintfFunction(char* format,...){
+	/*http://linux.die.net/man/3/vsnprintf*/
+
+	/*string to be printed: */
+	char *buffer = NULL;
+	int   n,size = 100;
+	int         string_size;
+	extern int  my_rank;
+	extern int  num_procs;
+                                                                                                                                                                                                     
+	//variable list of arguments
+	va_list args;
+
+	while(true){
+
+		/*allocate buffer for given string size*/
+		buffer=(char*)xmalloc(size*sizeof(char));
+
+		/* Try to print in the allocated space. */
+		va_start(args, format);
+#ifndef WIN32
+		n=vsnprintf(buffer,size,format,args);
+#else
+		n=vsnprintf(buffer,size,format,args);
+#endif
+		va_end(args);
+
+		/* If that worked, return the string. */
+		if(n>-1 && n<size) break;
+
+		/* Else try again with more space. */
+		if(n>-1)   /* glibc 2.1 */
+		 size=n+1; /* precisely what is needed */
+		else       /* glibc 2.0 */
+		 size*=2;  /* twice the old size */
+
+		xfree((void**)&buffer);
+	}
+
+	/*Ok, if we are running in parallel, get node 0 to print*/
+#if defined(_PARALLEL_)
+	if(my_rank==0)printf(buffer);
+#else
+	mexPrintf(buffer);
+#endif
+
+	/*Clean up and return*/
+	xfree((void**)&buffer);
+	return 1;
+}
Index: /issm/trunk/src/c/io/io.h
===================================================================
--- /issm/trunk/src/c/io/io.h	(revision 9760)
+++ /issm/trunk/src/c/io/io.h	(revision 9761)
@@ -6,6 +6,19 @@
 #define _IO_H_
 
+#ifdef HAVE_CONFIG_H //config.h {{{1
+#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif 
+//}}}
+
 #include "./Disk/diskio.h"
+
+#ifdef _SERIAL_
 #include "./Matlab/matlabio.h"
+#endif
+
+/*printf: */
+int PrintfFunction(char* format,...);
 
 #endif	/* _IO_H_ */
Index: /issm/trunk/src/c/issm.h
===================================================================
--- /issm/trunk/src/c/issm.h	(revision 9760)
+++ /issm/trunk/src/c/issm.h	(revision 9761)
@@ -22,3 +22,4 @@
 #include "./modules/modules.h"
 
+
 #endif //ifndef _ISSM_H_
Index: /issm/trunk/src/c/modules/ConfigureObjectsx/ConfigureObjectsx.cpp
===================================================================
--- /issm/trunk/src/c/modules/ConfigureObjectsx/ConfigureObjectsx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ConfigureObjectsx/ConfigureObjectsx.cpp	(revision 9761)
@@ -7,4 +7,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/ConstraintsStatex/ConstraintsStatex.cpp
===================================================================
--- /issm/trunk/src/c/modules/ConstraintsStatex/ConstraintsStatex.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ConstraintsStatex/ConstraintsStatex.cpp	(revision 9761)
@@ -7,4 +7,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
@@ -35,7 +36,9 @@
 		RiftConstraintsState(&converged,&num_unstable_constraints,loads,min_mechanical_constraints,analysis_type);
 	}
+	#ifdef _HAVE_THERMAL_
 	else if(ThermalIsPresent(loads,analysis_type)){
 		ThermalConstraintsState(loads,&converged,&num_unstable_constraints,analysis_type);
 	}
+	#endif
 	else{
 		/*Do nothing, no constraints management!:*/
Index: /issm/trunk/src/c/modules/ConstraintsStatex/RiftConstraintsState.cpp
===================================================================
--- /issm/trunk/src/c/modules/ConstraintsStatex/RiftConstraintsState.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ConstraintsStatex/RiftConstraintsState.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../../EnumDefinitions/EnumDefinitions.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../shared/shared.h"
 
Index: /issm/trunk/src/c/modules/Dakotax/DakotaFree.cpp
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/DakotaFree.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Dakotax/DakotaFree.cpp	(revision 9761)
@@ -20,4 +20,5 @@
 
 	int i;
+	extern int my_rank;
 	
 	double* variables=NULL;
Index: /issm/trunk/src/c/modules/Dakotax/DakotaMPI_Bcast.cpp
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/DakotaMPI_Bcast.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Dakotax/DakotaMPI_Bcast.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 
 	int i;
+	extern int my_rank;
 
 	/*inputs and outputs: */
Index: /issm/trunk/src/c/modules/Dakotax/Dakotax.h
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/Dakotax.h	(revision 9760)
+++ /issm/trunk/src/c/modules/Dakotax/Dakotax.h	(revision 9761)
@@ -11,4 +11,5 @@
 /* local prototypes: */
 int SpawnCore(double* responses, int numresponses, double* variables, char** variables_descriptors,int numvariables, void* femmodel,int counter);
+int  DescriptorIndex(char* root, int* pindex,char* descriptor);
 
 #ifdef _SERIAL_
Index: /issm/trunk/src/c/modules/Dakotax/DescriptorIndex.cpp
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/DescriptorIndex.cpp	(revision 9761)
+++ /issm/trunk/src/c/modules/Dakotax/DescriptorIndex.cpp	(revision 9761)
@@ -0,0 +1,71 @@
+/*!\file:  DescriptorIndex: return type of qmu variable: indexed, scaled, nodal or regular
+ * + figure out the descriptor root. 
+ * Ex: scaled_Thickness_1 should return SCALEDENUM, fill root with Thickness, and initialize index 
+ * to 1.
+ */ 
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "../../shared/shared.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+
+int  DescriptorIndex(char* root, int* pindex,char* descriptor){ //We assume root has already been allocated, and we just have to copy into it.
+	
+	char * pch=NULL;
+
+	/*retrieve first token, separated by underscore: */
+	pch = strtok (descriptor,"_");
+	if(!pch)_error_("%s%s%s"," descriptor ",descriptor," is not correctly formatted!");
+
+	if (strncmp(pch,"scaled",6)==0){
+		/*we have a scaled variable. recover the root: */
+		pch = strtok (NULL, "_");
+		if(!pch)_error_("%s%s%s"," scaled descriptor ",descriptor," is not correctly formatted!");
+		memcpy(root,pch,(strlen(pch)+1)*sizeof(char));
+
+		/*now recover  the index if it exists: */
+		pch = strtok (NULL, "_");
+		if(!pch){
+			*pindex=-1;
+		}
+		else{
+			sscanf(pch,"%i",pindex);
+		}
+		return ScaledEnum;
+	}
+	else if (strncmp(pch,"indexed",7)==0){
+		/*we have an indexed variable. recover the root: */
+		pch = strtok (NULL, "_");
+		if(!pch)_error_("%s%s%s"," indexed descriptor ",descriptor," is not correctly formatted!");
+		memcpy(root,pch,(strlen(pch)+1)*sizeof(char));
+		/*now recover  the index: */
+		pch = strtok (NULL, "_");
+		if(!pch)_error_("%s%s%s"," indexed descriptor ",descriptor," is not correctly formatted!");
+		sscanf(pch,"%i",pindex);
+		return IndexedEnum;
+	}
+	else if (strncmp(pch,"nodal",5)==0){
+		/*we have an indexed variable. recover the root: */
+		pch = strtok (NULL, "_");
+		if(!pch)_error_("%s%s%s"," nodal descriptor ",descriptor," is not correctly formatted!");
+		memcpy(root,pch,(strlen(pch)+1)*sizeof(char));
+		/*now recover  the index: */
+		pch = strtok (NULL, "_");
+		if(!pch)_error_("%s%s%s"," nodal descriptor ",descriptor," is not correctly formatted!");
+		sscanf(pch,"%i",pindex);
+		return NodalEnum;
+	}
+	else{
+		/*We don't have _ in the name, this is a regular variable: */
+		memcpy(root,pch,(strlen(pch)+1)*sizeof(char));
+		*pindex=-1;
+		return RegularEnum;
+	}
+}
Index: /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp
===================================================================
--- /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Dakotax/SpawnCoreParallel.cpp	(revision 9761)
@@ -29,4 +29,5 @@
 #include "../../io/io.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../io/io.h"
 #include "../../shared/shared.h"
 #include "./Dakotax.h"
Index: /issm/trunk/src/c/modules/Exp2Kmlx/Exp2Kmlx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Exp2Kmlx/Exp2Kmlx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Exp2Kmlx/Exp2Kmlx.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp
===================================================================
--- /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationx.cpp	(revision 9761)
@@ -7,5 +7,7 @@
 
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp
===================================================================
--- /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/GroundingLineMigrationx/GroundingLineMigrationxUtils.cpp	(revision 9761)
@@ -6,4 +6,6 @@
 #include "./GroundingLineMigrationxLocal.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
 #include "../../toolkits/toolkits.h"
Index: /issm/trunk/src/c/modules/InputConvergencex/InputConvergencex.cpp
===================================================================
--- /issm/trunk/src/c/modules/InputConvergencex/InputConvergencex.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/InputConvergencex/InputConvergencex.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/KMLMeshWritex/KMLFileReadx.cpp
===================================================================
--- /issm/trunk/src/c/modules/KMLMeshWritex/KMLFileReadx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/KMLMeshWritex/KMLFileReadx.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/KMLMeshWritex/KMLMeshWritex.cpp
===================================================================
--- /issm/trunk/src/c/modules/KMLMeshWritex/KMLMeshWritex.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/KMLMeshWritex/KMLMeshWritex.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/KMLOverlayx/KMLOverlayx.cpp
===================================================================
--- /issm/trunk/src/c/modules/KMLOverlayx/KMLOverlayx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/KMLOverlayx/KMLOverlayx.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/Kml2Expx/Kml2Expx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Kml2Expx/Kml2Expx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Kml2Expx/Kml2Expx.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/Ll2xyx/Ll2xyx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Ll2xyx/Ll2xyx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Ll2xyx/Ll2xyx.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../include/include.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include <math.h>
 
Index: /issm/trunk/src/c/modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Mergesolutionfromftogx/Mergesolutionfromftogx.cpp	(revision 9761)
@@ -4,4 +4,5 @@
 
 #include "../VecMergex/VecMergex.h"
+#include "../../io/io.h"
 #include "./Mergesolutionfromftogx.h"
 
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateDataSets.cpp	(revision 9761)
@@ -67,4 +67,12 @@
 			break;
 
+		case HydrologyAnalysisEnum:
+			CreateNodesHydrology(pnodes, iomodel);
+			CreateConstraintsHydrology(pconstraints,iomodel);
+			CreateLoadsHydrology(ploads,iomodel);
+			UpdateElementsHydrology(elements,iomodel,analysis_counter,analysis_type);
+			break;
+
+		#ifdef _HAVE_THERMAL_
 		case ThermalAnalysisEnum:
 			CreateNodesThermal(pnodes, iomodel);
@@ -73,5 +81,5 @@
 			UpdateElementsThermal(elements,iomodel,analysis_counter,analysis_type);
 			break;
-		
+	
 		case EnthalpyAnalysisEnum:
 			CreateNodesEnthalpy(pnodes, iomodel);
@@ -81,11 +89,4 @@
 			break;
 		
-		case HydrologyAnalysisEnum:
-			CreateNodesHydrology(pnodes, iomodel);
-			CreateConstraintsHydrology(pconstraints,iomodel);
-			CreateLoadsHydrology(ploads,iomodel);
-			UpdateElementsHydrology(elements,iomodel,analysis_counter,analysis_type);
-			break;
-
 		case MeltingAnalysisEnum:
 			CreateNodesMelting(pnodes, iomodel);
@@ -94,4 +95,5 @@
 			UpdateElementsMelting(elements,iomodel,analysis_counter,analysis_type);
 			break;
+		#endif
 
 		case PrognosticAnalysisEnum:
@@ -114,5 +116,7 @@
 
 	/*Update Elements and Materials For Control methods*/
+	#ifdef _HAVE_CONTROL_
 	UpdateElementsAndMaterialsControl(elements,materials,iomodel);
+	#endif
 
 	/*Generate objects that are not dependent on any analysis_type: */
Index: /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ModelProcessorx/CreateParameters.cpp	(revision 9761)
@@ -2,4 +2,11 @@
  * \brief general driver for creating parameters dataset
  */ 
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
 
 #include "../../Container/Container.h"
@@ -93,6 +100,11 @@
 	
 	/*Before returning, create parameters in case we are running Qmu or control types runs: */
+	#ifdef _HAVE_CONTROL_
 	CreateParametersControl(&parameters,iomodel,solution_type,analysis_type);
+	#endif
+
+	#ifdef _HAVE_DAKOTA_
 	CreateParametersQmu(&parameters,iomodel,solution_type,analysis_type);
+	#endif
 
 	/*Go through all parameters, and convert units to SI: */
Index: /issm/trunk/src/c/modules/ModelProcessorx/ModelProcessorx.cpp
===================================================================
--- /issm/trunk/src/c/modules/ModelProcessorx/ModelProcessorx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ModelProcessorx/ModelProcessorx.cpp	(revision 9761)
@@ -11,4 +11,5 @@
 #include "../../objects/objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/Reduceloadx/Reduceloadx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Reduceloadx/Reduceloadx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Reduceloadx/Reduceloadx.cpp	(revision 9761)
@@ -10,4 +10,5 @@
 
 #include "./Reduceloadx.h"
+#include "../../io/io.h"
 
 void	Reduceloadx( Vec pf, Mat Kfs, Vec y_s,bool flag_ys0){
Index: /issm/trunk/src/c/modules/ResetConstraintsx/ResetConstraintsx.cpp
===================================================================
--- /issm/trunk/src/c/modules/ResetConstraintsx/ResetConstraintsx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/ResetConstraintsx/ResetConstraintsx.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../modules.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
 #include "../../toolkits/toolkits.h"
Index: /issm/trunk/src/c/modules/Solverx/Solverx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Solverx/Solverx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Solverx/Solverx.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 
 #ifdef HAVE_CONFIG_H
Index: /issm/trunk/src/c/modules/SystemMatricesx/SystemMatricesx.cpp
===================================================================
--- /issm/trunk/src/c/modules/SystemMatricesx/SystemMatricesx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/SystemMatricesx/SystemMatricesx.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../../shared/shared.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/UpdateConstraintsx/UpdateConstraintsx.cpp
===================================================================
--- /issm/trunk/src/c/modules/UpdateConstraintsx/UpdateConstraintsx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/UpdateConstraintsx/UpdateConstraintsx.cpp	(revision 9761)
@@ -8,4 +8,5 @@
 #include "../../include/include.h"
 #include "../../modules/modules.h"
+#include "../../io/io.h"
 #include "../../toolkits/toolkits.h"
 #include "../../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/modules/Xy2llx/Xy2llx.cpp
===================================================================
--- /issm/trunk/src/c/modules/Xy2llx/Xy2llx.cpp	(revision 9760)
+++ /issm/trunk/src/c/modules/Xy2llx/Xy2llx.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../../include/include.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include <math.h>
 
Index: /issm/trunk/src/c/objects/Bamg/include.h
===================================================================
--- /issm/trunk/src/c/objects/Bamg/include.h	(revision 9760)
+++ /issm/trunk/src/c/objects/Bamg/include.h	(revision 9761)
@@ -6,4 +6,5 @@
 #define  _INCLUDE2_H_
 
+#include "../../include/macros.h"
 #include "./macros.h"
 #include "./typedefs.h"
Index: /issm/trunk/src/c/objects/Contour.cpp
===================================================================
--- /issm/trunk/src/c/objects/Contour.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Contour.cpp	(revision 9761)
@@ -11,5 +11,5 @@
 #include "./objects.h"
 #include "../include/include.h"
-#include "../shared/Matlab/matlabshared.h"
+#include "../io/io.h"
 
 void ContourEcho(Contour* contour){
Index: /issm/trunk/src/c/objects/Elements/Element.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Element.h	(revision 9760)
+++ /issm/trunk/src/c/objects/Elements/Element.h	(revision 9761)
@@ -40,4 +40,5 @@
 		virtual void   GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue)=0;
 		virtual void   GetParameterValue(double* pvalue,Node* node,int enumtype)=0;
+		#ifdef _HAVE_CONTROL_
 		virtual void   Gradj(Vec gradient,int control_type)=0;
 		virtual double ThicknessAbsMisfit(bool process_units  ,int weight_index)=0;
@@ -50,4 +51,9 @@
 		virtual double RheologyBbarAbsGradient(bool process_units,int weight_index)=0;
 		virtual double DragCoefficientAbsGradient(bool process_units,int weight_index)=0;
+		virtual void   ControlInputGetGradient(Vec gradient,int enum_type)=0;
+		virtual void   ControlInputSetGradient(double* gradient,int enum_type)=0;
+		virtual void   ControlInputScaleGradient(int enum_type, double scale)=0;
+		virtual void   InputControlUpdate(double scalar,bool save_parameter)=0;
+		#endif
 		virtual double SurfaceArea(void)=0;
 		virtual void   InputDepthAverageAtBase(int enum_type,int average_enum_type,int object_enum)=0;
@@ -63,8 +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   ControlInputGetGradient(Vec gradient,int enum_type)=0;
-		virtual void   ControlInputSetGradient(double* gradient,int enum_type)=0;
-		virtual void   ControlInputScaleGradient(int enum_type, double scale)=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;
@@ -81,5 +84,4 @@
 		virtual void   InputScale(int enum_type,double scale_factor)=0;
 		virtual void   GetVectorFromInputs(Vec vector,int NameEnum)=0;
-		virtual void   InputControlUpdate(double scalar,bool save_parameter)=0;
 		virtual void   InputArtificialNoise(int enum_type,double min,double max)=0;
 		virtual bool   InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums)=0;
Index: /issm/trunk/src/c/objects/Elements/Penta.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 9761)
@@ -524,63 +524,4 @@
 }
 /*}}}*/
-/*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::CreateDVectorDiagnosticHoriz {{{1*/
 ElementVector* Penta::CreateDVectorDiagnosticHoriz(void){
@@ -658,4 +599,5 @@
 			Ke=CreateKMatrixBalancethickness();
 			break;
+		#ifdef _HAVE_THERMAL_
 		case ThermalAnalysisEnum:
 			Ke=CreateKMatrixThermal();
@@ -667,4 +609,5 @@
 			Ke=CreateKMatrixMelting();
 			break;
+		#endif
 		default:
 			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
@@ -1817,4 +1760,40 @@
 }
 /*}}}*/
+/*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){
+
+	if (!IsOnBed()) return NULL;
+
+	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
+	ElementMatrix* Ke=tria->CreateKMatrixSlope();
+	delete tria->matice; delete tria;
+
+	/*clean up and return*/
+	return Ke;
+}
+/*}}}*/
+
+#ifdef _HAVE_THERMAL_
 /*FUNCTION Penta::CreateKMatrixEnthalpy {{{1*/
 ElementMatrix* Penta::CreateKMatrixEnthalpy(void){
@@ -2060,38 +2039,4 @@
 }
 /*}}}*/
-/*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){
-
-	if (!IsOnBed()) return NULL;
-
-	Tria* tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 make the new tria.
-	ElementMatrix* Ke=tria->CreateKMatrixSlope();
-	delete tria->matice; delete tria;
-
-	/*clean up and return*/
-	return Ke;
-}
-/*}}}*/
 /*FUNCTION Penta::CreateKMatrixThermal {{{1*/
 ElementMatrix* Penta::CreateKMatrixThermal(void){
@@ -2317,950 +2262,4 @@
 }
 /*}}}*/
-/*FUNCTION Penta::CreatePVector {{{1*/
-void  Penta::CreatePVector(Vec pf){
-
-	/*retrive parameters: */
-	ElementVector* pe=NULL;
-	int analysis_type;
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-
-	/*if debugging mode, check that all pointers exist {{{2*/
-	_assert_(this->nodes && this->matice && this->matpar && this->verticalneighbors && this->parameters && this->inputs);
-	/*}}}*/
-
-	/*Skip if water element*/
-	if(IsOnWater()) return;
-
-	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
-	switch(analysis_type){
-		case DiagnosticHorizAnalysisEnum:
-			pe=CreatePVectorDiagnosticHoriz();
-			break;
-		case AdjointHorizAnalysisEnum:
-			pe=CreatePVectorAdjointHoriz();
-			break;
-		case DiagnosticHutterAnalysisEnum:
-			pe=CreatePVectorDiagnosticHutter();
-			break;
-		case DiagnosticVertAnalysisEnum:
-			pe=CreatePVectorDiagnosticVert();
-			break;
-		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
-			pe=CreatePVectorSlope();
-			break;
-		case PrognosticAnalysisEnum:
-			pe=CreatePVectorPrognostic();
-			break;
-		case BalancethicknessAnalysisEnum:
-			pe=CreatePVectorBalancethickness();
-			break;
-		case ThermalAnalysisEnum:
-			pe=CreatePVectorThermal();
-			break;
-		case EnthalpyAnalysisEnum:
-			pe=CreatePVectorEnthalpy();
-			break;
-		case MeltingAnalysisEnum:
-			pe=CreatePVectorMelting();
-			break;
-		default:
-			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
-	}
-
-	/*Add to global Vector*/
-	if(pe){
-		pe->AddToGlobal(pf);
-		delete pe;
-	}
-}
-/*}}}*/
-/*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::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::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::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::CreatePVectorEnthalpy {{{1*/
 ElementVector* Penta::CreatePVectorEnthalpy(void){
@@ -3494,40 +2493,4 @@
 }
 /*}}}*/
-/*FUNCTION Penta::CreatePVectorPrognostic {{{1*/
-ElementVector* Penta::CreatePVectorPrognostic(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->CreatePVectorPrognostic();
-	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::CreatePVectorSlope {{{1*/
-ElementVector* Penta::CreatePVectorSlope(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->CreatePVectorSlope();
-	delete tria->matice; delete tria;
-
-	/*clean up and return*/
-	return pe;
-}
-/*}}}*/
 /*FUNCTION Penta::CreatePVectorThermal {{{1*/
 ElementVector* Penta::CreatePVectorThermal(void){
@@ -3756,467 +2719,4 @@
 }
 /*}}}*/
-/*FUNCTION Penta::DeepEcho{{{1*/
-void Penta::DeepEcho(void){
-
-	int i;
-	
-	printf("Penta:\n");
-	printf("   id: %i\n",id);
-	nodes[0]->DeepEcho();
-	nodes[1]->DeepEcho();
-	nodes[2]->DeepEcho();
-	nodes[3]->DeepEcho();
-	nodes[4]->DeepEcho();
-	nodes[5]->DeepEcho();
-	matice->DeepEcho();
-	matpar->DeepEcho();
-	printf("   neighbor ids: %i-%i\n",verticalneighbors[0]->Id(),verticalneighbors[1]->Id());
-	printf("   parameters\n");
-	parameters->DeepEcho();
-	printf("   inputs\n");
-	inputs->DeepEcho();
-	printf("   results\n");
-	results->DeepEcho();
-	printf("neighboor sids: \n");
-	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
-
-	return;
-}
-/*}}}*/
-/*FUNCTION Penta::DeleteResults {{{1*/
-void  Penta::DeleteResults(void){
-
-	/*Delete and reinitialize results*/
-	delete this->results;
-	this->results=new Results();
-
-}
-/*}}}*/
-/*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::Echo{{{1*/
-
-void Penta::Echo(void){
-	this->DeepEcho();
-}
-/*}}}*/
-/*FUNCTION Penta::Enum {{{1*/
-int Penta::Enum(void){
-
-	return PentaEnum;
-
-}
-/*}}}*/
-/*FUNCTION Penta::GetBasalElement{{{1*/
-Penta* Penta::GetBasalElement(void){
-
-	/*Output*/
-	Penta* penta=NULL;
-
-	/*Go through all elements till the bed is reached*/
-	penta=this;
-	for(;;){
-		/*Stop if we have reached the surface, else, take lower penta*/
-		if (penta->IsOnBed()) break;
-
-		/* get lower Penta*/
-		penta=penta->GetLowerElement();
-		_assert_(penta->Id()!=this->id);
-	}
-
-	/*return output*/
-	return penta;
-}
-/*}}}*/
-/*FUNCTION Penta::GetDofList {{{1*/
-void  Penta::GetDofList(int** pdoflist,int approximation_enum,int setenum){
-
-	int  i,j,count=0;
-	int  numberofdofs=0;
-	int* doflist=NULL;
-
-	/*First, figure out size of doflist: */
-	for(i=0;i<6;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
-
-	/*Allocate: */
-	doflist=(int*)xmalloc(numberofdofs*sizeof(int));
-
-	/*Populate: */
-	count=0;
-	for(i=0;i<6;i++){
-		nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);
-		count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
-	}
-
-	/*Assign output pointers:*/
-	*pdoflist=doflist;
-}
-/*}}}*/
-/*FUNCTION Penta::GetDofList1 {{{1*/
-void  Penta::GetDofList1(int* doflist){
-
-	int i;
-	for(i=0;i<6;i++) doflist[i]=nodes[i]->GetDofList1();
-
-}
-/*}}}*/
-/*FUNCTION Penta::GetElementType {{{1*/
-int Penta::GetElementType(){
-
-	/*return PentaRef field*/
-	return this->element_type;
-}
-/*}}}*/
-/*FUNCTION Penta::GetHorizontalNeighboorSids {{{1*/
-int* Penta::GetHorizontalNeighboorSids(){
-
-	/*return PentaRef field*/
-	return &this->horizontalneighborsids[0];
-
-}
-/*}}}*/
-/*FUNCTION Penta::GetLowerElement{{{1*/
-Penta* Penta::GetLowerElement(void){
-
-	Penta* upper_penta=NULL;
-
-	upper_penta=(Penta*)verticalneighbors[0]; //first one (0) under, second one (1) above
-
-	return upper_penta;
-}
-/*}}}*/
-/*FUNCTION Penta::GetNodeIndex {{{1*/
-int Penta::GetNodeIndex(Node* node){
-
-	_assert_(nodes);
-	for(int i=0;i<NUMVERTICES;i++){
-		if(node==nodes[i])
-		 return i;
-	}
-	_error_("Node provided not found among element nodes");
-
-}
-/*}}}*/
-/*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/
-void Penta::GetParameterListOnVertices(double* pvalue,int enumtype){
-
-	/*Intermediaries*/
-	double     value[NUMVERTICES];
-	GaussPenta *gauss              = NULL;
-
-	/*Recover input*/
-	Input* input=inputs->GetInput(enumtype);
-	if (!input) _error_("Input %s not found in element",EnumToStringx(enumtype));
-
-	/*Checks in debugging mode*/
-	_assert_(pvalue);
-
-	/* Start looping on the number of vertices: */
-	gauss=new GaussPenta();
-	for (int iv=0;iv<NUMVERTICES;iv++){
-		gauss->GaussVertex(iv);
-		input->GetParameterValue(&pvalue[iv],gauss);
-	}
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/
-void Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){
-
-	/*Intermediaries*/
-	double     value[NUMVERTICES];
-	GaussPenta *gauss              = NULL;
-
-	/*Recover input*/
-	Input* input=inputs->GetInput(enumtype);
-
-	/*Checks in debugging mode*/
-	_assert_(pvalue);
-
-	/* Start looping on the number of vertices: */
-	if (input){
-		gauss=new GaussPenta();
-		for (int iv=0;iv<NUMVERTICES;iv++){
-			gauss->GaussVertex(iv);
-			input->GetParameterValue(&pvalue[iv],gauss);
-		}
-	}
-	else{
-		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
-	}
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/
-void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){
-
-	Input* input=inputs->GetInput(enumtype);
-	if(!input) _error_("No input of type %s found in tria",EnumToStringx(enumtype));
-
-	GaussPenta* gauss=new GaussPenta();
-	gauss->GaussVertex(this->GetNodeIndex(node));
-
-	input->GetParameterValue(pvalue,gauss);
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Penta::GetPhi {{{1*/
-void Penta::GetPhi(double* phi, double*  epsilon, double viscosity){
-	/*Compute deformational heating from epsilon and viscosity */
-
-	double epsilon_matrix[3][3];
-	double epsilon_eff;
-	double epsilon_sqr[3][3];
-
-	/* Build epsilon matrix */
-	epsilon_matrix[0][0]=*(epsilon+0);
-	epsilon_matrix[1][0]=*(epsilon+3);
-	epsilon_matrix[2][0]=*(epsilon+4);
-	epsilon_matrix[0][1]=*(epsilon+3);
-	epsilon_matrix[1][1]=*(epsilon+1);
-	epsilon_matrix[2][1]=*(epsilon+5);
-	epsilon_matrix[0][2]=*(epsilon+4);
-	epsilon_matrix[1][2]=*(epsilon+5);
-	epsilon_matrix[2][2]=*(epsilon+2);
-
-	/* Effective value of epsilon_matrix */
-	epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2);
-	epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2);
-	epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2);
-	epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2);
-	epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2);
-	epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2);
-	epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2);
-	epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2);
-	epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2);
-	epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5);
-
-	/*Phi = Tr(sigma * eps) 
-	 *    = Tr(sigma'* eps)
-	 *    = 2 * eps_eff * sigma'_eff
-	 *    = 4 * mu * eps_eff ^2*/
-	*phi=4*pow(epsilon_eff,2.0)*viscosity;
-}
-/*}}}*/
-/*FUNCTION Penta::GetSidList{{{1*/
-void  Penta::GetSidList(int* sidlist){
-
-	int i;
-	for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();
-
-}
-/*}}}*/
-/*FUNCTION Penta::GetSolutionFromInputs{{{1*/
-void  Penta::GetSolutionFromInputs(Vec solution){
-
-	int analysis_type;
-
-	/*retrive parameters: */
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-
-	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
-	if (analysis_type==DiagnosticHorizAnalysisEnum){
-		int approximation;
-		inputs->GetParameterValue(&approximation,ApproximationEnum);
-		if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
-			GetSolutionFromInputsDiagnosticStokes(solution);
-		}
-		else if (approximation==MacAyealApproximationEnum || approximation==PattynApproximationEnum || approximation==HutterApproximationEnum){
-			GetSolutionFromInputsDiagnosticHoriz(solution);
-		}
-		else if (approximation==MacAyealPattynApproximationEnum || approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
-			return; //the elements around will create the solution
-		}
-	}
-	else if(analysis_type==DiagnosticHutterAnalysisEnum){
-		GetSolutionFromInputsDiagnosticHutter(solution);
-	}
-	else if(analysis_type==DiagnosticVertAnalysisEnum){
-		GetSolutionFromInputsDiagnosticVert(solution);
-	}
-	else if(analysis_type==ThermalAnalysisEnum){
-		GetSolutionFromInputsThermal(solution);
-	}
-	else if(analysis_type==EnthalpyAnalysisEnum){
-		GetSolutionFromInputsEnthalpy(solution);
-	}
-	else{
-		_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);
-}
-/*}}}*/
 /*FUNCTION Penta::GetSolutionFromInputsThermal{{{1*/
 void  Penta::GetSolutionFromInputsThermal(Vec solution){
@@ -4281,117 +2781,268 @@
 }
 /*}}}*/
-/*FUNCTION Penta::GetStabilizationParameter {{{1*/
-double Penta::GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity){
-	/*Compute stabilization parameter*/
-
-	double normu;
-	double tau_parameter;
-
-	normu=pow(pow(u,2)+pow(v,2)+pow(w,2),0.5);
-	if(normu*diameter/(3*2*thermalconductivity/(rho_ice*heatcapacity))<1){
-		tau_parameter=pow(diameter,2)/(3*2*2*thermalconductivity/(rho_ice*heatcapacity));
-	}
-	else tau_parameter=diameter/(2*normu);
-
-	return tau_parameter;
-}
-/*}}}*/
-/*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/
-void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input){
-	/*Compute the 3d Blatter/PattynStrain Rate (5 components):
-	 *
-	 * epsilon=[exx eyy exy exz eyz]
-	 *
-	 * with exz=1/2 du/dz
-	 *      eyz=1/2 dv/dz
-	 *
-	 * the contribution of vz is neglected
-	 */
-
-	int i;
-	double epsilonvx[5];
-	double epsilonvy[5];
-
-	/*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->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss);
-	vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss);
-
-	/*Sum all contributions*/
-	for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
-}
-/*}}}*/
-/*FUNCTION Penta::GetStrainRate3d{{{1*/
-void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input){
-	/*Compute the 3d Strain Rate (6 components):
-	 *
-	 * epsilon=[exx eyy ezz exy exz eyz]
-	 */
-
-	int i;
-	double epsilonvx[6];
-	double epsilonvy[6];
-	double epsilonvz[6];
-
-	/*Check that both inputs have been found*/
-	if (!vx_input || !vy_input || !vz_input){
-		_error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input);
-	}
-
-	/*Get strain rate assuming that epsilon has been allocated*/
-	vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss);
-	vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss);
-	vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss);
-
-	/*Sum all contributions*/
-	for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i];
-}
-/*}}}*/
-/*FUNCTION Penta::GetUpperElement{{{1*/
-Penta* Penta::GetUpperElement(void){
-
-	Penta* upper_penta=NULL;
-
-	upper_penta=(Penta*)verticalneighbors[1]; //first one under, second one above
-
-	return upper_penta;
-}
-/*}}}*/
-/*FUNCTION Penta::GetVectorFromInputs{{{1*/
-void  Penta::GetVectorFromInputs(Vec vector,int input_enum){
+/*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];
-
-	/*Get out if this is not an element input*/
-	if (!IsInput(input_enum)) return;
-
-	/*Prepare index list*/
+	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]);
-
-	/*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 Penta::GetZcoord {{{1*/
-double Penta::GetZcoord(GaussPenta* gauss){
-
-	int    i;
-	double z;
-	double xyz_list[NUMVERTICES][3];
-	double z_list[NUMVERTICES];
-
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	for(i=0;i<NUMVERTICES;i++) z_list[i]=xyz_list[i][2];
-	PentaRef::GetParameterValue(&z,z_list,gauss);
-
-	return z;
+	((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;
 }
 /*}}}*/
@@ -4714,4 +3365,1971 @@
 	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){
+
+	/*retrive parameters: */
+	ElementVector* pe=NULL;
+	int analysis_type;
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+
+	/*if debugging mode, check that all pointers exist {{{2*/
+	_assert_(this->nodes && this->matice && this->matpar && this->verticalneighbors && this->parameters && this->inputs);
+	/*}}}*/
+
+	/*Skip if water element*/
+	if(IsOnWater()) return;
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	switch(analysis_type){
+		case DiagnosticHorizAnalysisEnum:
+			pe=CreatePVectorDiagnosticHoriz();
+			break;
+		#ifdef _HAVE_CONTROL_
+		case AdjointHorizAnalysisEnum:
+			pe=CreatePVectorAdjointHoriz();
+			break;
+		#endif
+		case DiagnosticHutterAnalysisEnum:
+			pe=CreatePVectorDiagnosticHutter();
+			break;
+		case DiagnosticVertAnalysisEnum:
+			pe=CreatePVectorDiagnosticVert();
+			break;
+		case BedSlopeXAnalysisEnum: case SurfaceSlopeXAnalysisEnum: case BedSlopeYAnalysisEnum: case SurfaceSlopeYAnalysisEnum:
+			pe=CreatePVectorSlope();
+			break;
+		case PrognosticAnalysisEnum:
+			pe=CreatePVectorPrognostic();
+			break;
+		case BalancethicknessAnalysisEnum:
+			pe=CreatePVectorBalancethickness();
+			break;
+		#ifdef _HAVE_THERMAL_
+		case ThermalAnalysisEnum:
+			pe=CreatePVectorThermal();
+			break;
+		case EnthalpyAnalysisEnum:
+			pe=CreatePVectorEnthalpy();
+			break;
+		case MeltingAnalysisEnum:
+			pe=CreatePVectorMelting();
+			break;
+		#endif
+		default:
+			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
+	}
+
+	/*Add to global Vector*/
+	if(pe){
+		pe->AddToGlobal(pf);
+		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;
+}
+/*}}}*/
+/*FUNCTION Penta::CreatePVectorPrognostic {{{1*/
+ElementVector* Penta::CreatePVectorPrognostic(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->CreatePVectorPrognostic();
+	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::CreatePVectorSlope {{{1*/
+ElementVector* Penta::CreatePVectorSlope(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->CreatePVectorSlope();
+	delete tria->matice; delete tria;
+
+	/*clean up and return*/
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Penta::DeepEcho{{{1*/
+void Penta::DeepEcho(void){
+
+	int i;
+	
+	printf("Penta:\n");
+	printf("   id: %i\n",id);
+	nodes[0]->DeepEcho();
+	nodes[1]->DeepEcho();
+	nodes[2]->DeepEcho();
+	nodes[3]->DeepEcho();
+	nodes[4]->DeepEcho();
+	nodes[5]->DeepEcho();
+	matice->DeepEcho();
+	matpar->DeepEcho();
+	printf("   neighbor ids: %i-%i\n",verticalneighbors[0]->Id(),verticalneighbors[1]->Id());
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+	printf("   results\n");
+	results->DeepEcho();
+	printf("neighboor sids: \n");
+	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Penta::DeleteResults {{{1*/
+void  Penta::DeleteResults(void){
+
+	/*Delete and reinitialize results*/
+	delete this->results;
+	this->results=new Results();
+
+}
+/*}}}*/
+/*FUNCTION Penta::Echo{{{1*/
+
+void Penta::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Penta::Enum {{{1*/
+int Penta::Enum(void){
+
+	return PentaEnum;
+
+}
+/*}}}*/
+/*FUNCTION Penta::GetBasalElement{{{1*/
+Penta* Penta::GetBasalElement(void){
+
+	/*Output*/
+	Penta* penta=NULL;
+
+	/*Go through all elements till the bed is reached*/
+	penta=this;
+	for(;;){
+		/*Stop if we have reached the surface, else, take lower penta*/
+		if (penta->IsOnBed()) break;
+
+		/* get lower Penta*/
+		penta=penta->GetLowerElement();
+		_assert_(penta->Id()!=this->id);
+	}
+
+	/*return output*/
+	return penta;
+}
+/*}}}*/
+/*FUNCTION Penta::GetDofList {{{1*/
+void  Penta::GetDofList(int** pdoflist,int approximation_enum,int setenum){
+
+	int  i,j,count=0;
+	int  numberofdofs=0;
+	int* doflist=NULL;
+
+	/*First, figure out size of doflist: */
+	for(i=0;i<6;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
+
+	/*Allocate: */
+	doflist=(int*)xmalloc(numberofdofs*sizeof(int));
+
+	/*Populate: */
+	count=0;
+	for(i=0;i<6;i++){
+		nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);
+		count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
+	}
+
+	/*Assign output pointers:*/
+	*pdoflist=doflist;
+}
+/*}}}*/
+/*FUNCTION Penta::GetDofList1 {{{1*/
+void  Penta::GetDofList1(int* doflist){
+
+	int i;
+	for(i=0;i<6;i++) doflist[i]=nodes[i]->GetDofList1();
+
+}
+/*}}}*/
+/*FUNCTION Penta::GetElementType {{{1*/
+int Penta::GetElementType(){
+
+	/*return PentaRef field*/
+	return this->element_type;
+}
+/*}}}*/
+/*FUNCTION Penta::GetHorizontalNeighboorSids {{{1*/
+int* Penta::GetHorizontalNeighboorSids(){
+
+	/*return PentaRef field*/
+	return &this->horizontalneighborsids[0];
+
+}
+/*}}}*/
+/*FUNCTION Penta::GetLowerElement{{{1*/
+Penta* Penta::GetLowerElement(void){
+
+	Penta* upper_penta=NULL;
+
+	upper_penta=(Penta*)verticalneighbors[0]; //first one (0) under, second one (1) above
+
+	return upper_penta;
+}
+/*}}}*/
+/*FUNCTION Penta::GetNodeIndex {{{1*/
+int Penta::GetNodeIndex(Node* node){
+
+	_assert_(nodes);
+	for(int i=0;i<NUMVERTICES;i++){
+		if(node==nodes[i])
+		 return i;
+	}
+	_error_("Node provided not found among element nodes");
+
+}
+/*}}}*/
+/*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/
+void Penta::GetParameterListOnVertices(double* pvalue,int enumtype){
+
+	/*Intermediaries*/
+	double     value[NUMVERTICES];
+	GaussPenta *gauss              = NULL;
+
+	/*Recover input*/
+	Input* input=inputs->GetInput(enumtype);
+	if (!input) _error_("Input %s not found in element",EnumToStringx(enumtype));
+
+	/*Checks in debugging mode*/
+	_assert_(pvalue);
+
+	/* Start looping on the number of vertices: */
+	gauss=new GaussPenta();
+	for (int iv=0;iv<NUMVERTICES;iv++){
+		gauss->GaussVertex(iv);
+		input->GetParameterValue(&pvalue[iv],gauss);
+	}
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/
+void Penta::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){
+
+	/*Intermediaries*/
+	double     value[NUMVERTICES];
+	GaussPenta *gauss              = NULL;
+
+	/*Recover input*/
+	Input* input=inputs->GetInput(enumtype);
+
+	/*Checks in debugging mode*/
+	_assert_(pvalue);
+
+	/* Start looping on the number of vertices: */
+	if (input){
+		gauss=new GaussPenta();
+		for (int iv=0;iv<NUMVERTICES;iv++){
+			gauss->GaussVertex(iv);
+			input->GetParameterValue(&pvalue[iv],gauss);
+		}
+	}
+	else{
+		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
+	}
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Penta::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/
+void Penta::GetParameterValue(double* pvalue,Node* node,int enumtype){
+
+	Input* input=inputs->GetInput(enumtype);
+	if(!input) _error_("No input of type %s found in tria",EnumToStringx(enumtype));
+
+	GaussPenta* gauss=new GaussPenta();
+	gauss->GaussVertex(this->GetNodeIndex(node));
+
+	input->GetParameterValue(pvalue,gauss);
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Penta::GetPhi {{{1*/
+void Penta::GetPhi(double* phi, double*  epsilon, double viscosity){
+	/*Compute deformational heating from epsilon and viscosity */
+
+	double epsilon_matrix[3][3];
+	double epsilon_eff;
+	double epsilon_sqr[3][3];
+
+	/* Build epsilon matrix */
+	epsilon_matrix[0][0]=*(epsilon+0);
+	epsilon_matrix[1][0]=*(epsilon+3);
+	epsilon_matrix[2][0]=*(epsilon+4);
+	epsilon_matrix[0][1]=*(epsilon+3);
+	epsilon_matrix[1][1]=*(epsilon+1);
+	epsilon_matrix[2][1]=*(epsilon+5);
+	epsilon_matrix[0][2]=*(epsilon+4);
+	epsilon_matrix[1][2]=*(epsilon+5);
+	epsilon_matrix[2][2]=*(epsilon+2);
+
+	/* Effective value of epsilon_matrix */
+	epsilon_sqr[0][0]=pow(epsilon_matrix[0][0],2);
+	epsilon_sqr[1][0]=pow(epsilon_matrix[1][0],2);
+	epsilon_sqr[2][0]=pow(epsilon_matrix[2][0],2);
+	epsilon_sqr[0][1]=pow(epsilon_matrix[0][1],2);
+	epsilon_sqr[1][1]=pow(epsilon_matrix[1][1],2);
+	epsilon_sqr[2][1]=pow(epsilon_matrix[2][1],2);
+	epsilon_sqr[0][2]=pow(epsilon_matrix[0][2],2);
+	epsilon_sqr[1][2]=pow(epsilon_matrix[1][2],2);
+	epsilon_sqr[2][2]=pow(epsilon_matrix[2][2],2);
+	epsilon_eff=1/pow(2,0.5)*pow((epsilon_sqr[0][0]+epsilon_sqr[0][1]+ epsilon_sqr[0][2]+ epsilon_sqr[1][0]+ epsilon_sqr[1][1]+ epsilon_sqr[1][2]+ epsilon_sqr[2][0]+ epsilon_sqr[2][1]+ epsilon_sqr[2][2]),0.5);
+
+	/*Phi = Tr(sigma * eps) 
+	 *    = Tr(sigma'* eps)
+	 *    = 2 * eps_eff * sigma'_eff
+	 *    = 4 * mu * eps_eff ^2*/
+	*phi=4*pow(epsilon_eff,2.0)*viscosity;
+}
+/*}}}*/
+/*FUNCTION Penta::GetSidList{{{1*/
+void  Penta::GetSidList(int* sidlist){
+
+	int i;
+	for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();
+
+}
+/*}}}*/
+/*FUNCTION Penta::GetSolutionFromInputs{{{1*/
+void  Penta::GetSolutionFromInputs(Vec solution){
+
+	int analysis_type;
+
+	/*retrive parameters: */
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+
+	/*Just branch to the correct InputUpdateFromSolution generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==DiagnosticHorizAnalysisEnum){
+		int approximation;
+		inputs->GetParameterValue(&approximation,ApproximationEnum);
+		if(approximation==StokesApproximationEnum || approximation==NoneApproximationEnum){
+			GetSolutionFromInputsDiagnosticStokes(solution);
+		}
+		else if (approximation==MacAyealApproximationEnum || approximation==PattynApproximationEnum || approximation==HutterApproximationEnum){
+			GetSolutionFromInputsDiagnosticHoriz(solution);
+		}
+		else if (approximation==MacAyealPattynApproximationEnum || approximation==PattynStokesApproximationEnum || approximation==MacAyealStokesApproximationEnum){
+			return; //the elements around will create the solution
+		}
+	}
+	else if(analysis_type==DiagnosticHutterAnalysisEnum){
+		GetSolutionFromInputsDiagnosticHutter(solution);
+	}
+	else if(analysis_type==DiagnosticVertAnalysisEnum){
+		GetSolutionFromInputsDiagnosticVert(solution);
+	}
+	#ifdef _HAVE_THERMAL_
+	else if(analysis_type==ThermalAnalysisEnum){
+		GetSolutionFromInputsThermal(solution);
+	}
+	else if(analysis_type==EnthalpyAnalysisEnum){
+		GetSolutionFromInputsEnthalpy(solution);
+	}
+	#endif
+	else{
+		_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);
+}
+/*}}}*/
+/*FUNCTION Penta::GetStabilizationParameter {{{1*/
+double Penta::GetStabilizationParameter(double u, double v, double w, double diameter, double rho_ice, double heatcapacity, double thermalconductivity){
+	/*Compute stabilization parameter*/
+
+	double normu;
+	double tau_parameter;
+
+	normu=pow(pow(u,2)+pow(v,2)+pow(w,2),0.5);
+	if(normu*diameter/(3*2*thermalconductivity/(rho_ice*heatcapacity))<1){
+		tau_parameter=pow(diameter,2)/(3*2*2*thermalconductivity/(rho_ice*heatcapacity));
+	}
+	else tau_parameter=diameter/(2*normu);
+
+	return tau_parameter;
+}
+/*}}}*/
+/*FUNCTION Penta::GetStrainRate3dPattyn{{{1*/
+void Penta::GetStrainRate3dPattyn(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input){
+	/*Compute the 3d Blatter/PattynStrain Rate (5 components):
+	 *
+	 * epsilon=[exx eyy exy exz eyz]
+	 *
+	 * with exz=1/2 du/dz
+	 *      eyz=1/2 dv/dz
+	 *
+	 * the contribution of vz is neglected
+	 */
+
+	int i;
+	double epsilonvx[5];
+	double epsilonvy[5];
+
+	/*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->GetVxStrainRate3dPattyn(epsilonvx,xyz_list,gauss);
+	vy_input->GetVyStrainRate3dPattyn(epsilonvy,xyz_list,gauss);
+
+	/*Sum all contributions*/
+	for(i=0;i<5;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i];
+}
+/*}}}*/
+/*FUNCTION Penta::GetStrainRate3d{{{1*/
+void Penta::GetStrainRate3d(double* epsilon,double* xyz_list, GaussPenta* gauss, Input* vx_input, Input* vy_input, Input* vz_input){
+	/*Compute the 3d Strain Rate (6 components):
+	 *
+	 * epsilon=[exx eyy ezz exy exz eyz]
+	 */
+
+	int i;
+	double epsilonvx[6];
+	double epsilonvy[6];
+	double epsilonvz[6];
+
+	/*Check that both inputs have been found*/
+	if (!vx_input || !vy_input || !vz_input){
+		_error_("Input missing. Here are the input pointers we have for vx: %p, vy: %p, vz: %p\n",vx_input,vy_input,vz_input);
+	}
+
+	/*Get strain rate assuming that epsilon has been allocated*/
+	vx_input->GetVxStrainRate3d(epsilonvx,xyz_list,gauss);
+	vy_input->GetVyStrainRate3d(epsilonvy,xyz_list,gauss);
+	vz_input->GetVzStrainRate3d(epsilonvz,xyz_list,gauss);
+
+	/*Sum all contributions*/
+	for(i=0;i<6;i++) epsilon[i]=epsilonvx[i]+epsilonvy[i]+epsilonvz[i];
+}
+/*}}}*/
+/*FUNCTION Penta::GetUpperElement{{{1*/
+Penta* Penta::GetUpperElement(void){
+
+	Penta* upper_penta=NULL;
+
+	upper_penta=(Penta*)verticalneighbors[1]; //first one under, second one above
+
+	return upper_penta;
+}
+/*}}}*/
+/*FUNCTION Penta::GetVectorFromInputs{{{1*/
+void  Penta::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 Penta::GetZcoord {{{1*/
+double Penta::GetZcoord(GaussPenta* gauss){
+
+	int    i;
+	double z;
+	double xyz_list[NUMVERTICES][3];
+	double z_list[NUMVERTICES];
+
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	for(i=0;i<NUMVERTICES;i++) z_list[i]=xyz_list[i][2];
+	PentaRef::GetParameterValue(&z,z_list,gauss);
+
+	return z;
+}
+/*}}}*/
 /*FUNCTION Penta::Sid {{{1*/
 int    Penta::Sid(){
@@ -4769,42 +5387,4 @@
 	/*Return output*/
 	return converged;
-}
-/*}}}*/
-/*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);
 }
 /*}}}*/
@@ -5105,5 +5685,7 @@
 	 * 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
 
 }
@@ -5169,4 +5751,5 @@
 
 	/*Control Inputs*/
+	#ifdef _HAVE_CONTROL_
 	if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
 		for(i=0;i<num_control_type;i++){
@@ -5211,4 +5794,5 @@
 		}
 	}
+	#endif
 
 	//Need to know the type of approximation for this element
@@ -5276,4 +5860,5 @@
 		InputUpdateFromSolutionDiagnosticVert( solution);
 	}
+	#ifdef _HAVE_CONTROL_
 	else if (analysis_type==AdjointHorizAnalysisEnum){
 		int approximation;
@@ -5286,4 +5871,5 @@
 		}
 	}
+	#endif
 	else if (analysis_type==BedSlopeXAnalysisEnum){
 		InputUpdateFromSolutionOneDofCollapsed(solution,BedSlopeXEnum);
@@ -5304,4 +5890,5 @@
 		InputUpdateFromSolutionOneDofCollapsed(solution,ThicknessEnum);
 	}
+	#ifdef _HAVE_THERMAL_
 	else if (analysis_type==ThermalAnalysisEnum){
 		InputUpdateFromSolutionThermal( solution);
@@ -5313,4 +5900,5 @@
 		InputUpdateFromSolutionOneDof(solution,BasalforcingsMeltingRateEnum);
 	}
+	#endif
 	else{
 		_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
@@ -6050,82 +6638,4 @@
 }
 /*}}}*/
-/*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::InputUpdateFromSolutionPrognostic{{{1*/
 void  Penta::InputUpdateFromSolutionPrognostic(double* solution){
@@ -6213,146 +6723,4 @@
 }
 /*}}}*/
-/*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);
-}
-/*}}}*/
 /*FUNCTION Penta::InputUpdateFromSolutionOneDof{{{1*/
 void  Penta::InputUpdateFromSolutionOneDof(double* solution,int enum_type){
@@ -6456,116 +6824,4 @@
 /*FUNCTION Penta::InputUpdateFromVector(bool* vector, int name, int type);{{{1*/
 void  Penta::InputUpdateFromVector(bool* vector, int name, int type){
-	_error_(" not supported yet!");
-}
-/*}}}*/
-/*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!");
 }
@@ -7089,19 +7345,4 @@
 }
 /*}}}*/
-/*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;
-}
-/*}}}*/
 /*FUNCTION Penta::SetClone {{{1*/
 void  Penta::SetClone(int* minranks){
@@ -7206,154 +7447,4 @@
 }
 /*}}}*/
-/*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::SurfaceNormal {{{1*/
 void Penta::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
@@ -7378,47 +7469,4 @@
 	*(surface_normal+1)=normal[1]/normal_norm;
 	*(surface_normal+2)=normal[2]/normal_norm;
-}
-/*}}}*/
-/*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");
 }
 /*}}}*/
@@ -7467,24 +7515,4 @@
 	return dt;
 }
-/*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::Update(int index,IoModel* iomodel,int analysis_counter,int analysis_type) {{{1*/
 void Penta::Update(int index,IoModel* iomodel,int analysis_counter,int analysis_type){ 
Index: /issm/trunk/src/c/objects/Elements/Penta.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.h	(revision 9760)
+++ /issm/trunk/src/c/objects/Elements/Penta.h	(revision 9761)
@@ -68,7 +68,9 @@
 		void  InputUpdateFromVector(double* vector, int name, int type);
 		void  InputUpdateFromVector(int* vector, int name, int type);
+		#ifdef _HAVE_DAKOTA_
 		void  InputUpdateFromVectorDakota(bool* vector, int name, int type);
 		void  InputUpdateFromVectorDakota(double* vector, int name, int type);
 		void  InputUpdateFromVectorDakota(int* vector, int name, int type);
+		#endif
 		void  InputUpdateFromIoModel(int index, IoModel* iomodel);
 		/*}}}*/
@@ -83,9 +85,10 @@
 		void   CreatePVector(Vec pf);
 		void   DeleteResults(void);
-		double DragCoefficientAbsGradient(bool process_units,int weight_index);
 		int    GetNodeIndex(Node* node);
 		void   GetSolutionFromInputs(Vec solution);
 		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);
@@ -95,7 +98,19 @@
 		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);
-		void   InputControlUpdate(double scalar,bool save_parameter);
 		bool   InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums);
 		void   InputCreate(double scalar,int name,int code);
@@ -104,7 +119,5 @@
 		void   InputDuplicate(int original_enum,int new_enum);
 		void   InputScale(int enum_type,double scale_factor);
-		void   ControlInputGetGradient(Vec gradient,int enum_type);
-		void   ControlInputScaleGradient(int enum_type,double scale);
-		void   ControlInputSetGradient(double* gradient,int enum_type);
+		
 		void   InputToResult(int enum_type,int step,double time);
 		double MassFlux(double* segment,bool process_units);
@@ -120,7 +133,5 @@
 		void   PotentialSheetUngrounding(Vec potential_sheet_ungrounding);
 		void   ShelfSync();
-		double RheologyBbarAbsGradient(bool process_units,int weight_index);
 		void   RequestedOutput(int output_enum,int step,double time);
-		double ThicknessAbsGradient(bool process_units,int weight_index);
 		void   MigrateGroundingLine();
 		void   MinVel(double* pminvel, bool process_units);
@@ -128,10 +139,4 @@
 		void   MinVy(double* pminvy, bool process_units);
 		void   MinVz(double* pminvz, bool process_units);
-		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);
 		void   PatchFill(int* pcount, Patch* patch);
 		void   PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes);
Index: /issm/trunk/src/c/objects/Elements/Tria.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 9761)
@@ -1250,7 +1250,4 @@
 			pe=CreatePVectorDiagnosticMacAyeal();
 			break;
-		case AdjointHorizAnalysisEnum:
-			pe=CreatePVectorAdjointHoriz();
-			break;
 		case DiagnosticHutterAnalysisEnum:
 			pe=CreatePVectorDiagnosticHutter();
@@ -1268,7 +1265,12 @@
 			pe=CreatePVectorBalancethickness();
 			break;
+		#ifdef _HAVE_CONTROL_
 		case AdjointBalancethicknessAnalysisEnum:
 			pe=CreatePVectorAdjointBalancethickness();
 			break;
+		case AdjointHorizAnalysisEnum:
+			pe=CreatePVectorAdjointHoriz();
+			break;
+		#endif
 		default:
 			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
@@ -1431,4 +1433,1690 @@
 	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){
+
+	switch(GetElementType()){
+		case P1Enum:
+			return CreatePVectorPrognostic_CG();
+		case P1DGEnum:
+			return CreatePVectorPrognostic_DG();
+		default:
+			_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;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorPrognostic_CG {{{1*/
+ElementVector* Tria::CreatePVectorPrognostic_CG(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     Jdettria,dt;
+	double     surface_mass_balance_g,basal_melting_g,basal_melting_correction_g,thickness_g;
+	double     xyz_list[NUMVERTICES][3];
+	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);
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	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* basal_melting_correction_input=inputs->GetInput(BasalforcingsMeltingRateCorrectionEnum);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum);                             _assert_(thickness_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);
+		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
+
+		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
+		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
+		thickness_input->GetParameterValue(&thickness_g,gauss);
+		if(basal_melting_correction_input) basal_melting_correction_input->GetParameterValue(&basal_melting_correction_g,gauss);
+
+		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(surface_mass_balance_g-basal_melting_g-basal_melting_correction_g))*L[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorPrognostic_DG {{{1*/
+ElementVector* Tria::CreatePVectorPrognostic_DG(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+
+	/*Intermediaries */
+	int        i,j,ig;
+	double     Jdettria,dt;
+	double     surface_mass_balance_g,basal_melting_g,thickness_g;
+	double     xyz_list[NUMVERTICES][3];
+	double     L[NUMVERTICES];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+	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* thickness_input=inputs->GetInput(ThicknessEnum);                             _assert_(thickness_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);
+		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
+
+		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
+		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
+		thickness_input->GetParameterValue(&thickness_g,gauss);
+
+		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(surface_mass_balance_g-basal_melting_g))*L[i];
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorSlope {{{1*/
+ElementVector* Tria::CreatePVectorSlope(void){
+
+	/*Constants*/
+	const int    numdof=NDOF1*NUMVERTICES;
+	
+	/*Intermediaries */
+	int        i,j,ig;
+	int        analysis_type;
+	double     Jdet;
+	double     xyz_list[NUMVERTICES][3];
+	double     slope[2];
+	double     basis[3];
+	GaussTria* gauss=NULL;
+
+	/*Initialize Element vector*/
+	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
+
+	/*Retrieve all inputs and parameters*/
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* slope_input=NULL;
+	if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==SurfaceSlopeYAnalysisEnum)){
+		slope_input=inputs->GetInput(SurfaceEnum); _assert_(slope_input);
+	}
+	if ( (analysis_type==BedSlopeXAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){
+		slope_input=inputs->GetInput(BedEnum);     _assert_(slope_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);
+
+		slope_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
+
+		if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==BedSlopeXAnalysisEnum)){
+			for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[0]*basis[i];
+		}
+		if ( (analysis_type==SurfaceSlopeYAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){
+			for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[1]*basis[i];
+		}
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return pe;
+}
+/*}}}*/
+/*FUNCTION Tria::ComputeBasalStress {{{1*/
+void  Tria::ComputeBasalStress(Vec eps){
+	_error_("Not Implemented yet");
+}
+/*}}}*/
+/*FUNCTION Tria::ComputeStrainRate {{{1*/
+void  Tria::ComputeStrainRate(Vec eps){
+	_error_("Not Implemented yet");
+}
+/*}}}*/
+/*FUNCTION Tria::Configure {{{1*/
+void  Tria::Configure(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];
+
+	/*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 
+	 * datasets, using internal ids and offsets hidden in hooks: */
+	if(this->hnodes[analysis_counter]) this->hnodes[analysis_counter]->configure(nodesin);
+	this->hmatice->configure(materialsin);
+	this->hmatpar->configure(materialsin);
+
+	/*Now, go pick up the objects inside the hooks: */
+	if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
+	else this->nodes=NULL;
+	this->matice=(Matice*)this->hmatice->delivers();
+	this->matpar=(Matpar*)this->hmatpar->delivers();
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+	/*get inputs configured too: */
+	this->inputs->Configure(parameters);
+
+}
+/*}}}*/
+/*FUNCTION Tria::DeepEcho{{{1*/
+void Tria::DeepEcho(void){
+
+	printf("Tria:\n");
+	printf("   id: %i\n",id);
+	if(nodes){
+		nodes[0]->DeepEcho();
+		nodes[1]->DeepEcho();
+		nodes[2]->DeepEcho();
+	}
+	else printf("nodes = NULL\n");
+
+	if (matice) matice->DeepEcho();
+	else printf("matice = NULL\n");
+
+	if (matpar) matpar->DeepEcho();
+	else printf("matpar = NULL\n");
+
+	printf("   parameters\n");
+	if (parameters) parameters->DeepEcho();
+	else printf("parameters = NULL\n");
+
+	printf("   inputs\n");
+	if (inputs) inputs->DeepEcho();
+	else printf("inputs=NULL\n");
+
+	if (results) results->DeepEcho();
+	else printf("results=NULL\n");
+
+	printf("neighboor sids: \n");
+	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
+	
+	return;
+}
+/*}}}*/
+/*FUNCTION Tria::DeleteResults {{{1*/
+void  Tria::DeleteResults(void){
+
+	/*Delete and reinitialize results*/
+	delete this->results;
+	this->results=new Results();
+
+}
+/*}}}*/
+/*FUNCTION Tria::Echo{{{1*/
+void Tria::Echo(void){
+	printf("Tria:\n");
+	printf("   id: %i\n",id);
+	if(nodes){
+		nodes[0]->Echo();
+		nodes[1]->Echo();
+		nodes[2]->Echo();
+	}
+	else printf("nodes = NULL\n");
+
+	if (matice) matice->Echo();
+	else printf("matice = NULL\n");
+
+	if (matpar) matpar->Echo();
+	else printf("matpar = NULL\n");
+
+	printf("   parameters\n");
+	if (parameters) parameters->Echo();
+	else printf("parameters = NULL\n");
+
+	printf("   inputs\n");
+	if (inputs) inputs->Echo();
+	else printf("inputs=NULL\n");
+
+	if (results) results->Echo();
+	else printf("results=NULL\n");
+
+	printf("neighboor sids: \n");
+	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
+}
+/*}}}*/
+/*FUNCTION Tria::Enum {{{1*/
+int Tria::Enum(void){
+
+	return TriaEnum;
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetArea {{{1*/
+double Tria::GetArea(void){
+
+	double area=0;
+	double xyz_list[NUMVERTICES][3];
+	double x1,y1,x2,y2,x3,y3;
+
+	/*Get xyz list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	x1=xyz_list[0][0]; y1=xyz_list[0][1];
+	x2=xyz_list[1][0]; y2=xyz_list[1][1];
+	x3=xyz_list[2][0]; y3=xyz_list[2][1];
+ 
+	return (x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1)/2;
+}
+/*}}}*/
+/*FUNCTION Tria::GetDofList {{{1*/
+void  Tria::GetDofList(int** pdoflist, int approximation_enum,int setenum){
+
+	int i,j;
+	int count=0;
+	int numberofdofs=0;
+	int* doflist=NULL;
+
+	/*First, figure out size of doflist and create it: */
+	for(i=0;i<3;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
+	doflist=(int*)xmalloc(numberofdofs*sizeof(int));
+
+	/*Populate: */
+	count=0;
+	for(i=0;i<3;i++){
+		nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);
+		count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
+	}
+
+	/*Assign output pointers:*/
+	*pdoflist=doflist;
+}
+/*}}}*/
+/*FUNCTION Tria::GetDofList1 {{{1*/
+void  Tria::GetDofList1(int* doflist){
+
+	int i;
+	for(i=0;i<3;i++) doflist[i]=nodes[i]->GetDofList1();
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetElementType {{{1*/
+int Tria::GetElementType(){
+
+	/*return TriaRef field*/
+	return this->element_type;
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetHorizontalNeighboorSids {{{1*/
+int* Tria::GetHorizontalNeighboorSids(){
+
+	/*return TriaRef field*/
+	return &this->horizontalneighborsids[0];
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetNodeIndex {{{1*/
+int Tria::GetNodeIndex(Node* node){
+
+	_assert_(nodes);
+	for(int i=0;i<NUMVERTICES;i++){
+		if(node==nodes[i])
+		 return i;
+	}
+	_error_("Node provided not found among element nodes");
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/
+void Tria::GetParameterListOnVertices(double* pvalue,int enumtype){
+
+	/*Intermediaries*/
+	double     value[NUMVERTICES];
+	GaussTria *gauss              = NULL;
+
+	/*Recover input*/
+	Input* input=inputs->GetInput(enumtype);
+	if (!input) _error_("Input %s not found in element",EnumToStringx(enumtype));
+
+	/*Checks in debugging mode*/
+	_assert_(pvalue);
+
+	/* Start looping on the number of vertices: */
+	gauss=new GaussTria();
+	for (int iv=0;iv<NUMVERTICES;iv++){
+		gauss->GaussVertex(iv);
+		input->GetParameterValue(&pvalue[iv],gauss);
+	}
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/
+void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){
+
+	double     value[NUMVERTICES];
+	GaussTria *gauss = NULL;
+	Input     *input = inputs->GetInput(enumtype);
+
+	/*Checks in debugging mode*/
+	_assert_(pvalue);
+
+	/* Start looping on the number of vertices: */
+	if (input){
+		gauss=new GaussTria();
+		for (int iv=0;iv<NUMVERTICES;iv++){
+			gauss->GaussVertex(iv);
+			input->GetParameterValue(&pvalue[iv],gauss);
+		}
+	}
+	else{
+		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
+	}
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index) TO BE REMOVED{{{1*/
+void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index){
+
+	double     value[NUMVERTICES];
+	GaussTria *gauss = NULL;
+	Input     *input = inputs->GetInput(enumtype);
+
+	/*Checks in debugging mode*/
+	_assert_(pvalue);
+
+	/* Start looping on the number of vertices: */
+	if (input){
+		gauss=new GaussTria();
+		for (int iv=0;iv<NUMVERTICES;iv++){
+			gauss->GaussVertex(iv);
+			input->GetParameterValue(&pvalue[iv],gauss,index);
+		}
+	}
+	else{
+		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
+	}
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/
+void Tria::GetParameterValue(double* pvalue,Node* node,int enumtype){
+
+	Input* input=inputs->GetInput(enumtype);
+	if(!input) _error_("No input of type %s found in tria",EnumToStringx(enumtype));
+
+	GaussTria* gauss=new GaussTria();
+	gauss->GaussVertex(this->GetNodeIndex(node));
+
+	input->GetParameterValue(pvalue,gauss);
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GetSidList {{{1*/
+void  Tria::GetSidList(int* sidlist){
+
+	int i;
+	for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetSolutionFromInputs{{{1*/
+void  Tria::GetSolutionFromInputs(Vec 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: */
+	if (analysis_type==DiagnosticHorizAnalysisEnum)
+	 GetSolutionFromInputsDiagnosticHoriz(solution);
+	else if (analysis_type==DiagnosticHutterAnalysisEnum)
+	 GetSolutionFromInputsDiagnosticHutter(solution);
+	else if (analysis_type==HydrologyAnalysisEnum)
+	 GetSolutionFromInputsHydrology(solution);
+	else
+	 _error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetSolutionFromInputsDiagnosticHoriz{{{1*/
+void  Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int          i;
+	int*         doflist=NULL;
+	double       vx,vy;
+	double       values[numdof];
+	GaussTria*   gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Get inputs*/
+	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 GaussTria();
+	for(i=0;i<NUMVERTICES;i++){
+
+		gauss->GaussVertex(i);
+
+		/*Recover vx and vy*/
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		values[i*NDOF2+0]=vx;
+		values[i*NDOF2+1]=vy;
+	}
+
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*FUNCTION Tria::GetSolutionFromInputsDiagnosticHutter{{{1*/
+void  Tria::GetSolutionFromInputsDiagnosticHutter(Vec solution){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int i,dummy;
+	int*         doflist=NULL;
+	double       vx,vy;
+	double       values[numdof];
+	GaussTria*   gauss=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
+
+	/*Get inputs*/
+	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 GaussTria();
+	for(i=0;i<NUMVERTICES;i++){
+
+		gauss->GaussVertex(i);
+
+		/*Recover vx and vy*/
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		values[i*NDOF2+0]=vx;
+		values[i*NDOF2+1]=vy;
+	}
+
+	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
+
+	/*Free ressources:*/
+	delete gauss;
+	xfree((void**)&doflist);
+}
+/*}}}*/
+/*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);
+
+	/*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:*/
+	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(){
+	
+	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);
+}
+/*}}}*/
+
+#ifdef _HAVE_CONTROL_
+/*FUNCTION Tria::InputControlUpdate{{{1*/
+void  Tria::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){
+			input=(Input*)matice->inputs->GetInput(control_type[i]); _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();
+
+	}
+
+	/*Clean up and return*/
+	xfree((void**)&control_type);
+}
+/*}}}*/
+/*FUNCTION Tria::ControlInputGetGradient{{{1*/
+void Tria::ControlInputGetGradient(Vec gradient,int enum_type){
+
+	int doflist1[NUMVERTICES];
+	Input* input=NULL;
+
+	if(enum_type==MaterialsRheologyBbarEnum){
+		input=(Input*)matice->inputs->GetInput(enum_type);
+	}
+	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 Tria::ControlInputScaleGradient{{{1*/
+void Tria::ControlInputScaleGradient(int enum_type,double scale){
+
+	Input* input=NULL;
+
+	if(enum_type==MaterialsRheologyBbarEnum){
+		input=(Input*)matice->inputs->GetInput(enum_type);
+	}
+	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 Tria::ControlInputSetGradient{{{1*/
+void Tria::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(enum_type);
+	}
+	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 TriaVertexInput(GradientEnum,grad_list);
+
+	((ControlInput*)input)->SetGradient(grad_input);
+
+}/*}}}*/
+/*FUNCTION Tria::Gradj {{{1*/
+void  Tria::Gradj(Vec gradient,int control_type){
+	/*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
+
+	/*If on water, grad = 0: */
+	if(IsOnWater()) return;
+
+	/*First deal with ∂/∂alpha(KU-F)*/
+	switch(control_type){
+		case FrictionCoefficientEnum:
+			GradjDragMacAyeal(gradient);
+			break;
+		case MaterialsRheologyBbarEnum:
+			GradjBMacAyeal(gradient);
+			break;
+		case BalancethicknessThickeningRateEnum:
+			GradjDhDtBalancedthickness(gradient);
+			break;
+		case VxEnum:
+			GradjVxBalancedthickness(gradient);
+			break;
+		case VyEnum:
+			GradjVyBalancedthickness(gradient);
+			break;
+		default:
+			_error_("%s%i","control type not supported yet: ",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]){
+		//FIXME: the control type should be checked somewhere (with respect to what variable are we taking the gradient!)
+
+		case ThicknessAbsMisfitEnum:
+		case ThicknessAbsGradientEnum:
+		case SurfaceAbsVelMisfitEnum:
+		case SurfaceRelVelMisfitEnum:
+		case SurfaceLogVelMisfitEnum:
+		case SurfaceLogVxVyMisfitEnum:
+		case SurfaceAverageVelMisfitEnum:
+			/*Nothing, J does not depends on the parameter being inverted for*/
+			break;
+		case DragCoefficientAbsGradientEnum:
+			GradjDragGradient(gradient,resp);
+			break;
+		case RheologyBbarAbsGradientEnum:
+			GradjBGradient(gradient,resp);
+			break;
+		default:
+			_error_("response %s not supported yet",EnumToStringx(responses[resp]));
+	}
+
+	xfree((void**)&responses);
+}
+/*}}}*/
+/*FUNCTION Tria::GradjBGradient{{{1*/
+void  Tria::GradjBGradient(Vec gradient, int weight_index){
+
+	int        i,ig;
+	int        doflist1[NUMVERTICES];
+	double     Jdet,weight;
+	double     xyz_list[NUMVERTICES][3];
+	double     dbasis[NDOF2][NUMVERTICES];
+	double     dk[NDOF2]; 
+	double     grade_g[NUMVERTICES]={0.0};
+	GaussTria  *gauss=NULL;
+
+	/*Retrieve all inputs we will be needing: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist1[0]);
+	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);                _assert_(weights_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);
+		GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss);
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+
+		/*Build alpha_complement_list: */
+		rheologyb_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[i]+=-weight*Jdet*gauss->weight*(dbasis[0][i]*dk[0]+dbasis[1][i]*dk[1]);
+	}
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GradjBMacAyeal{{{1*/
+void  Tria::GradjBMacAyeal(Vec gradient){
+
+	/*Intermediaries*/
+	int        i,ig;
+	int        doflist[NUMVERTICES];
+	double     vx,vy,lambda,mu,thickness,Jdet;
+	double     viscosity_complement;
+	double     dvx[NDOF2],dvy[NDOF2],dadjx[NDOF2],dadjy[NDOF2],dB[NDOF2]; 
+	double     xyz_list[NUMVERTICES][3];
+	double     basis[3],epsilon[3];
+	double     grad[NUMVERTICES]={0.0};
+	GaussTria *gauss = NULL;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist[0]);
+
+	/*Retrieve all inputs*/
+	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* adjointx_input=inputs->GetInput(AdjointxEnum);              _assert_(adjointx_input);
+	Input* adjointy_input=inputs->GetInput(AdjointyEnum);              _assert_(adjointy_input);
+	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		thickness_input->GetParameterValue(&thickness,gauss);
+		rheologyb_input->GetParameterDerivativeValue(&dB[0],&xyz_list[0][0],gauss);
+		vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
+		vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
+		adjointx_input->GetParameterDerivativeValue(&dadjx[0],&xyz_list[0][0],gauss);
+		adjointy_input->GetParameterDerivativeValue(&dadjy[0],&xyz_list[0][0],gauss);
+
+		this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
+		matice->GetViscosityComplement(&viscosity_complement,&epsilon[0]);
+
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctions(basis,gauss);
+
+		/*standard gradient dJ/dki*/
+		for (i=0;i<NUMVERTICES;i++) grad[i]+=-viscosity_complement*thickness*(
+					(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
+					)*Jdet*gauss->weight*basis[i];
+	}
+
+	VecSetValues(gradient,NUMVERTICES,doflist,(const double*)grad,ADD_VALUES);
+
+	/*clean-up*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GradjDragMacAyeal {{{1*/
+void  Tria::GradjDragMacAyeal(Vec gradient){
+
+	int        i,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     dk[NDOF2]; 
+	double     grade_g[NUMVERTICES]={0.0};
+	double     grade_g_gaussian[NUMVERTICES];
+	double     basis[3];
+	double     epsilon[3]; /* epsilon=[exx,eyy,exy];*/
+	Friction*  friction=NULL;
+	GaussTria  *gauss=NULL;
+
+	if(IsOnShelf())return;
+
+	/*retrive parameters: */
+	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist1[0]);
+
+	/*Build frictoin element, needed later: */
+	friction=new Friction("2d",inputs,matpar,analysis_type);
+
+	/*Retrieve all inputs we will be needing: */
+	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);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+		GetNodalFunctions(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];
+		}
+		
+		/*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];
+		}
+	}
+	/*Analytical gradient*/
+	//delete gauss;
+	//gauss=new GaussTria();
+	//for (int iv=0;iv<NUMVERTICES;iv++){
+	//	gauss->GaussVertex(iv);
+	//	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);
+	//	grade_g[iv]=-2*drag*alpha_complement*((lambda*vx+mu*vy));
+	//	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,INSERT_VALUES);
+	//}
+	/*End Analytical gradient*/
+
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+	delete friction;
+}
+/*}}}*/
+/*FUNCTION Tria::GradjDragGradient{{{1*/
+void  Tria::GradjDragGradient(Vec gradient, int weight_index){
+
+	int        i,ig;
+	int        doflist1[NUMVERTICES];
+	double     Jdet,weight;
+	double     xyz_list[NUMVERTICES][3];
+	double     dbasis[NDOF2][NUMVERTICES];
+	double     dk[NDOF2]; 
+	double     grade_g[NUMVERTICES]={0.0};
+	GaussTria  *gauss=NULL;
+
+	/*Retrieve all inputs we will be needing: */
+	if(IsOnShelf())return;
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist1[0]);
+	Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);                 _assert_(weights_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);
+		GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss);
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+
+		/*Build alpha_complement_list: */
+		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[i]+=-weight*Jdet*gauss->weight*(dbasis[0][i]*dk[0]+dbasis[1][i]*dk[1]);
+			_assert_(!isnan(grade_g[i]));
+		}
+	}
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GradjDhDtBalancedthickness{{{1*/
+void  Tria::GradjDhDtBalancedthickness(Vec gradient){
+
+	/*Intermediaries*/
+	int    doflist1[NUMVERTICES];
+	double lambda[NUMVERTICES];
+	double gradient_g[NUMVERTICES];
+
+	GetDofList1(&doflist1[0]);
+
+	/*Compute Gradient*/
+	GetParameterListOnVertices(&lambda[0],AdjointEnum);
+	for(int i=0;i<NUMVERTICES;i++) gradient_g[i]=-lambda[i];
+
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)gradient_g,INSERT_VALUES);
+}
+/*}}}*/
+/*FUNCTION Tria::GradjVxBalancedthickness{{{1*/
+void  Tria::GradjVxBalancedthickness(Vec gradient){
+
+	/*Intermediaries*/
+	int        i,ig;
+	int        doflist1[NUMVERTICES];
+	double     thickness,Jdet;
+	double     basis[3];
+	double     Dlambda[2],dp[2];
+	double     xyz_list[NUMVERTICES][3];
+	double     grade_g[NUMVERTICES] = {0.0};
+	GaussTria *gauss                = NULL;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist1[0]);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* adjoint_input=inputs->GetInput(AdjointEnum);     _assert_(adjoint_input);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_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);
+		
+		adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss);
+		thickness_input->GetParameterValue(&thickness, gauss);
+		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
+
+		for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
+	}
+
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::GradjVyBalancedthickness{{{1*/
+void  Tria::GradjVyBalancedthickness(Vec gradient){
+
+	/*Intermediaries*/
+	int        i,ig;
+	int        doflist1[NUMVERTICES];
+	double     thickness,Jdet;
+	double     basis[3];
+	double     Dlambda[2],dp[2];
+	double     xyz_list[NUMVERTICES][3];
+	double     grade_g[NUMVERTICES] = {0.0};
+	GaussTria *gauss                = NULL;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	GetDofList1(&doflist1[0]);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* adjoint_input=inputs->GetInput(AdjointEnum);     _assert_(adjoint_input);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_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);
+
+		adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss);
+		thickness_input->GetParameterValue(&thickness, gauss);
+		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
+
+		for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
+	}
+	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
+
+	/*Clean up and return*/
+	delete gauss;
+}
+/*}}}*/
+/*FUNCTION Tria::RheologyBbarAbsGradient{{{1*/
+double Tria::RheologyBbarAbsGradient(bool process_units,int weight_index){
+
+	/* Intermediaries */
+	int        ig;
+	double     Jelem = 0;
+	double     weight;
+	double     Jdet;
+	double     xyz_list[NUMVERTICES][3];
+	double     dp[NDOF2];
+	GaussTria *gauss = NULL;
+
+	/*retrieve parameters and inputs*/
+
+	/*If on water, return 0: */
+	if(IsOnWater()) return 0;
+
+	/*Retrieve all inputs we will be needing: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* weights_input  =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);              _assert_(weights_input);
+	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
+
+	/* Start looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		rheologyb_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
+
+		/*Tikhonov regularization: J = 1/2 ((dp/dx)^2 + (dp/dy)^2) */ 
+		//Jelem+=weight*1/2*(pow(dp[0],2.)+pow(dp[1],2.))*Jdet*gauss->weight;
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceAverageVelMisfit {{{1*/
+double Tria::SurfaceAverageVelMisfit(bool process_units,int weight_index){
+
+	const int    numdof=2*NUMVERTICES;
+
+	int        i,ig;
+	double     Jelem=0,S,Jdet;
+	double     misfit;
+	double     vx,vy,vxobs,vyobs,weight;
+	double     xyz_list[NUMVERTICES][3];
+	GaussTria *gauss=NULL;
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Retrieve all inputs we will be needing: */
+	inputs->GetParameterValue(&S,SurfaceAreaEnum);
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
+	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
+	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
+	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(3);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vxobs_input->GetParameterValue(&vxobs,gauss);
+		vyobs_input->GetParameterValue(&vyobs,gauss);
+
+		/*Compute SurfaceAverageVelMisfitEnum:
+		 *
+		 *      1                    2              2
+		 * J = ---  sqrt(  (u - u   )  +  (v - v   )  )
+		 *      S                obs            obs
+		 */
+		misfit=1/S*pow( pow(vx-vxobs,2.) + pow(vy-vyobs,2.) ,0.5);
+
+		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceAverageVelMisfitEnum);
+
+		/*Add to cost function*/
+		Jelem+=misfit*weight*Jdet*gauss->weight;
+	}
+
+	/*clean-up and Return: */
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceLogVelMisfit {{{1*/
+double Tria::SurfaceLogVelMisfit(bool process_units,int weight_index){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int        i,ig;
+	double     Jelem=0;
+	double     misfit,Jdet;
+	double     epsvel=2.220446049250313e-16;
+	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
+	double     velocity_mag,obs_velocity_mag;
+	double     xyz_list[NUMVERTICES][3];
+	double     vx,vy,vxobs,vyobs,weight;
+	GaussTria *gauss=NULL;
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
+	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
+	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
+	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vxobs_input->GetParameterValue(&vxobs,gauss);
+		vyobs_input->GetParameterValue(&vyobs,gauss);
+
+		/*Compute SurfaceLogVelMisfit:
+		 *                 [        vel + eps     ] 2
+		 * J = 4 \bar{v}^2 | log ( -----------  ) |  
+		 *                 [       vel   + eps    ]
+		 *                            obs
+		 */
+		velocity_mag    =sqrt(pow(vx,   2.)+pow(vy,   2.))+epsvel;
+		obs_velocity_mag=sqrt(pow(vxobs,2.)+pow(vyobs,2.))+epsvel;
+		misfit=4*pow(meanvel,2.)*pow(log(velocity_mag/obs_velocity_mag),2.);
+
+		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceLogVelMisfitEnum);
+
+		/*Add to cost function*/
+		Jelem+=misfit*weight*Jdet*gauss->weight;
+	}
+
+	/*clean-up and Return: */
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceLogVxVyMisfit {{{1*/
+double Tria::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int        i,ig;
+	int        fit=-1;
+	double     Jelem=0, S=0;
+	double     epsvel=2.220446049250313e-16;
+	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
+	double     misfit, Jdet;
+	double     vx,vy,vxobs,vyobs,weight;
+	double     xyz_list[NUMVERTICES][3];
+	GaussTria *gauss=NULL;
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
+	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
+	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
+	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
+	
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vxobs_input->GetParameterValue(&vxobs,gauss);
+		vyobs_input->GetParameterValue(&vyobs,gauss);
+
+		/*Compute SurfaceRelVelMisfit:
+		 *
+		 *      1            [        |u| + eps     2          |v| + eps     2  ]
+		 * J = --- \bar{v}^2 | log ( -----------  )   +  log ( -----------  )   |  
+		 *      2            [       |u    |+ eps              |v    |+ eps     ]
+		 *                              obs                       obs
+		 */
+		misfit=0.5*pow(meanvel,2.)*(
+					pow(log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)),2.) +
+					pow(log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)),2.) );
+
+		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceLogVxVyMisfitEnum);
+
+		/*Add to cost function*/
+		Jelem+=misfit*weight*Jdet*gauss->weight;
+	}
+
+	/*clean-up and Return: */
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceAbsVelMisfit {{{1*/
+double Tria::SurfaceAbsVelMisfit(bool process_units,int weight_index){
+
+	const int    numdof=NDOF2*NUMVERTICES;
+
+	int        i,ig;
+	double     Jelem=0;
+	double     misfit,Jdet;
+	double     vx,vy,vxobs,vyobs,weight;
+	double     xyz_list[NUMVERTICES][3];
+	GaussTria *gauss=NULL;
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
+	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
+	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
+	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vxobs_input->GetParameterValue(&vxobs,gauss);
+		vyobs_input->GetParameterValue(&vyobs,gauss);
+
+		/*Compute SurfaceAbsVelMisfitEnum:
+		 *
+		 *      1  [           2              2 ]
+		 * J = --- | (u - u   )  +  (v - v   )  |
+		 *      2  [       obs            obs   ]
+		 *
+		 */
+		misfit=0.5*( pow(vx-vxobs,2.) + pow(vy-vyobs,2.) );
+
+		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceAverageVelMisfitEnum);
+
+		/*Add to cost function*/
+		Jelem+=misfit*weight*Jdet*gauss->weight;
+	}
+
+	/*clean up and Return: */
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceRelVelMisfit {{{1*/
+double Tria::SurfaceRelVelMisfit(bool process_units,int weight_index){
+	const int  numdof=2*NUMVERTICES;
+
+	int        i,ig;
+	double     Jelem=0;
+	double     scalex=1,scaley=1;
+	double     misfit,Jdet;
+	double     epsvel=2.220446049250313e-16;
+	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
+	double     vx,vy,vxobs,vyobs,weight;
+	double     xyz_list[NUMVERTICES][3];
+	GaussTria *gauss=NULL;
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+
+	/*Retrieve all inputs we will be needing: */
+	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
+	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
+	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
+	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(4);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		vx_input->GetParameterValue(&vx,gauss);
+		vy_input->GetParameterValue(&vy,gauss);
+		vxobs_input->GetParameterValue(&vxobs,gauss);
+		vyobs_input->GetParameterValue(&vyobs,gauss);
+
+		/*Compute SurfaceRelVelMisfit:
+		 *                        
+		 *      1  [     \bar{v}^2             2   \bar{v}^2              2 ]
+		 * J = --- | -------------  (u - u   ) + -------------  (v - v   )  |
+		 *      2  [  (u   + eps)^2       obs    (v   + eps)^2       obs    ]
+		 *              obs                        obs                      
+		 */
+		scalex=pow(meanvel/(vxobs+epsvel),2.); if(vxobs==0)scalex=0;
+		scaley=pow(meanvel/(vyobs+epsvel),2.); if(vyobs==0)scaley=0;
+		misfit=0.5*(scalex*pow((vx-vxobs),2.)+scaley*pow((vy-vyobs),2.));
+		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceRelVelMisfitEnum);
+
+		/*Add to cost function*/
+		Jelem+=misfit*weight*Jdet*gauss->weight;
+	}
+
+	/*clean up and Return: */
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::ThicknessAbsGradient{{{1*/
+double Tria::ThicknessAbsGradient(bool process_units,int weight_index){
+
+	/* Intermediaries */
+	int        ig;
+	double     Jelem = 0;
+	double     weight;
+	double     Jdet;
+	double     xyz_list[NUMVERTICES][3];
+	double     dp[NDOF2];
+	GaussTria *gauss = NULL;
+
+	/*retrieve parameters and inputs*/
+
+	/*If on water, return 0: */
+	if(IsOnWater()) return 0;
+
+	/*Retrieve all inputs we will be needing: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* weights_input  =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
+	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
+
+	/* Start looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get all parameters at gaussian point*/
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
+
+		/*Tikhonov regularization: J = 1/2 ((dp/dx)^2 + (dp/dy)^2) */ 
+		Jelem+=weight*1/2*(pow(dp[0],2.)+pow(dp[1],2.))*Jdet*gauss->weight;
+	}
+
+	/*Clean up and return*/
+	delete gauss;
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::ThicknessAbsMisfit {{{1*/
+double Tria::ThicknessAbsMisfit(bool process_units,int weight_index){
+
+	/*Intermediaries*/
+	int        i,ig;
+	double     thickness,thicknessobs,weight;
+	double     Jdet;
+	double     Jelem = 0;
+	double     xyz_list[NUMVERTICES][3];
+	GaussTria *gauss = NULL;
+	double     dH[2];
+
+	/*If on water, return 0: */
+	if(IsOnWater())return 0;
+
+	/*Retrieve all inputs we will be needing: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
+	Input* thickness_input   =inputs->GetInput(ThicknessEnum);   _assert_(thickness_input);
+	Input* thicknessobs_input=inputs->GetInput(InversionThicknessObsEnum);_assert_(thicknessobs_input);
+	Input* weights_input     =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);     _assert_(weights_input);
+
+	/* Start  looping on the number of gaussian points: */
+	gauss=new GaussTria(2);
+	for (ig=gauss->begin();ig<gauss->end();ig++){
+
+		gauss->GaussPoint(ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
+
+		/*Get parameters at gauss point*/
+		thickness_input->GetParameterValue(&thickness,gauss);
+		thickness_input->GetParameterDerivativeValue(&dH[0],&xyz_list[0][0],gauss);
+		thicknessobs_input->GetParameterValue(&thicknessobs,gauss);
+		weights_input->GetParameterValue(&weight,gauss,weight_index);
+
+		/*compute ThicknessAbsMisfit*/
+		Jelem+=0.5*pow(thickness-thicknessobs,2.0)*weight*Jdet*gauss->weight;
+	}
+
+	/* clean up and Return: */
+	delete gauss;
+	return Jelem;
 }
 /*}}}*/
@@ -1854,402 +3542,4 @@
 }
 /*}}}*/
-/*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){
-
-	switch(GetElementType()){
-		case P1Enum:
-			return CreatePVectorPrognostic_CG();
-		case P1DGEnum:
-			return CreatePVectorPrognostic_DG();
-		default:
-			_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;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorPrognostic_CG {{{1*/
-ElementVector* Tria::CreatePVectorPrognostic_CG(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     Jdettria,dt;
-	double     surface_mass_balance_g,basal_melting_g,basal_melting_correction_g,thickness_g;
-	double     xyz_list[NUMVERTICES][3];
-	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);
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	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* basal_melting_correction_input=inputs->GetInput(BasalforcingsMeltingRateCorrectionEnum);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum);                             _assert_(thickness_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);
-		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
-
-		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
-		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
-		thickness_input->GetParameterValue(&thickness_g,gauss);
-		if(basal_melting_correction_input) basal_melting_correction_input->GetParameterValue(&basal_melting_correction_g,gauss);
-
-		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(surface_mass_balance_g-basal_melting_g-basal_melting_correction_g))*L[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorPrognostic_DG {{{1*/
-ElementVector* Tria::CreatePVectorPrognostic_DG(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-
-	/*Intermediaries */
-	int        i,j,ig;
-	double     Jdettria,dt;
-	double     surface_mass_balance_g,basal_melting_g,thickness_g;
-	double     xyz_list[NUMVERTICES][3];
-	double     L[NUMVERTICES];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	this->parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-	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* thickness_input=inputs->GetInput(ThicknessEnum);                             _assert_(thickness_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);
-		GetL(&L[0], &xyz_list[0][0], gauss,NDOF1);
-
-		surface_mass_balance_input->GetParameterValue(&surface_mass_balance_g,gauss);
-		basal_melting_input->GetParameterValue(&basal_melting_g,gauss);
-		thickness_input->GetParameterValue(&thickness_g,gauss);
-
-		for(i=0;i<numdof;i++) pe->values[i]+=Jdettria*gauss->weight*(thickness_g+dt*(surface_mass_balance_g-basal_melting_g))*L[i];
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::CreatePVectorSlope {{{1*/
-ElementVector* Tria::CreatePVectorSlope(void){
-
-	/*Constants*/
-	const int    numdof=NDOF1*NUMVERTICES;
-	
-	/*Intermediaries */
-	int        i,j,ig;
-	int        analysis_type;
-	double     Jdet;
-	double     xyz_list[NUMVERTICES][3];
-	double     slope[2];
-	double     basis[3];
-	GaussTria* gauss=NULL;
-
-	/*Initialize Element vector*/
-	ElementVector* pe=new ElementVector(nodes,NUMVERTICES,this->parameters);
-
-	/*Retrieve all inputs and parameters*/
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* slope_input=NULL;
-	if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==SurfaceSlopeYAnalysisEnum)){
-		slope_input=inputs->GetInput(SurfaceEnum); _assert_(slope_input);
-	}
-	if ( (analysis_type==BedSlopeXAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){
-		slope_input=inputs->GetInput(BedEnum);     _assert_(slope_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);
-
-		slope_input->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss);
-
-		if ( (analysis_type==SurfaceSlopeXAnalysisEnum) || (analysis_type==BedSlopeXAnalysisEnum)){
-			for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[0]*basis[i];
-		}
-		if ( (analysis_type==SurfaceSlopeYAnalysisEnum) || (analysis_type==BedSlopeYAnalysisEnum)){
-			for(i=0;i<numdof;i++) pe->values[i]+=Jdet*gauss->weight*slope[1]*basis[i];
-		}
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return pe;
-}
-/*}}}*/
-/*FUNCTION Tria::ComputeBasalStress {{{1*/
-void  Tria::ComputeBasalStress(Vec eps){
-	_error_("Not Implemented yet");
-}
-/*}}}*/
-/*FUNCTION Tria::ComputeStrainRate {{{1*/
-void  Tria::ComputeStrainRate(Vec eps){
-	_error_("Not Implemented yet");
-}
-/*}}}*/
-/*FUNCTION Tria::Configure {{{1*/
-void  Tria::Configure(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];
-
-	/*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 
-	 * datasets, using internal ids and offsets hidden in hooks: */
-	if(this->hnodes[analysis_counter]) this->hnodes[analysis_counter]->configure(nodesin);
-	this->hmatice->configure(materialsin);
-	this->hmatpar->configure(materialsin);
-
-	/*Now, go pick up the objects inside the hooks: */
-	if(this->hnodes[analysis_counter]) this->nodes=(Node**)this->hnodes[analysis_counter]->deliverp();
-	else this->nodes=NULL;
-	this->matice=(Matice*)this->hmatice->delivers();
-	this->matpar=(Matpar*)this->hmatpar->delivers();
-
-	/*point parameters to real dataset: */
-	this->parameters=parametersin;
-
-	/*get inputs configured too: */
-	this->inputs->Configure(parameters);
-
-}
-/*}}}*/
-/*FUNCTION Tria::ControlInputGetGradient{{{1*/
-void Tria::ControlInputGetGradient(Vec gradient,int enum_type){
-
-	int doflist1[NUMVERTICES];
-	Input* input=NULL;
-
-	if(enum_type==MaterialsRheologyBbarEnum){
-		input=(Input*)matice->inputs->GetInput(enum_type);
-	}
-	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 Tria::ControlInputScaleGradient{{{1*/
-void Tria::ControlInputScaleGradient(int enum_type,double scale){
-
-	Input* input=NULL;
-
-	if(enum_type==MaterialsRheologyBbarEnum){
-		input=(Input*)matice->inputs->GetInput(enum_type);
-	}
-	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 Tria::ControlInputSetGradient{{{1*/
-void Tria::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(enum_type);
-	}
-	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 TriaVertexInput(GradientEnum,grad_list);
-
-	((ControlInput*)input)->SetGradient(grad_input);
-
-}/*}}}*/
-/*FUNCTION Tria::DeepEcho{{{1*/
-void Tria::DeepEcho(void){
-
-	printf("Tria:\n");
-	printf("   id: %i\n",id);
-	if(nodes){
-		nodes[0]->DeepEcho();
-		nodes[1]->DeepEcho();
-		nodes[2]->DeepEcho();
-	}
-	else printf("nodes = NULL\n");
-
-	if (matice) matice->DeepEcho();
-	else printf("matice = NULL\n");
-
-	if (matpar) matpar->DeepEcho();
-	else printf("matpar = NULL\n");
-
-	printf("   parameters\n");
-	if (parameters) parameters->DeepEcho();
-	else printf("parameters = NULL\n");
-
-	printf("   inputs\n");
-	if (inputs) inputs->DeepEcho();
-	else printf("inputs=NULL\n");
-
-	if (results) results->DeepEcho();
-	else printf("results=NULL\n");
-
-	printf("neighboor sids: \n");
-	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
-	
-	return;
-}
-/*}}}*/
-/*FUNCTION Tria::DeleteResults {{{1*/
-void  Tria::DeleteResults(void){
-
-	/*Delete and reinitialize results*/
-	delete this->results;
-	this->results=new Results();
-
-}
-/*}}}*/
 /*FUNCTION Tria::DragCoefficientAbsGradient{{{1*/
 double Tria::DragCoefficientAbsGradient(bool process_units,int weight_index){
@@ -2296,840 +3586,6 @@
 }
 /*}}}*/
-/*FUNCTION Tria::Echo{{{1*/
-void Tria::Echo(void){
-	printf("Tria:\n");
-	printf("   id: %i\n",id);
-	if(nodes){
-		nodes[0]->Echo();
-		nodes[1]->Echo();
-		nodes[2]->Echo();
-	}
-	else printf("nodes = NULL\n");
-
-	if (matice) matice->Echo();
-	else printf("matice = NULL\n");
-
-	if (matpar) matpar->Echo();
-	else printf("matpar = NULL\n");
-
-	printf("   parameters\n");
-	if (parameters) parameters->Echo();
-	else printf("parameters = NULL\n");
-
-	printf("   inputs\n");
-	if (inputs) inputs->Echo();
-	else printf("inputs=NULL\n");
-
-	if (results) results->Echo();
-	else printf("results=NULL\n");
-
-	printf("neighboor sids: \n");
-	printf(" %i %i %i\n",horizontalneighborsids[0],horizontalneighborsids[1],horizontalneighborsids[2]);
-}
-/*}}}*/
-/*FUNCTION Tria::Enum {{{1*/
-int Tria::Enum(void){
-
-	return TriaEnum;
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetArea {{{1*/
-double Tria::GetArea(void){
-
-	double area=0;
-	double xyz_list[NUMVERTICES][3];
-	double x1,y1,x2,y2,x3,y3;
-
-	/*Get xyz list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	x1=xyz_list[0][0]; y1=xyz_list[0][1];
-	x2=xyz_list[1][0]; y2=xyz_list[1][1];
-	x3=xyz_list[2][0]; y3=xyz_list[2][1];
- 
-	return (x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1)/2;
-}
-/*}}}*/
-/*FUNCTION Tria::GetDofList {{{1*/
-void  Tria::GetDofList(int** pdoflist, int approximation_enum,int setenum){
-
-	int i,j;
-	int count=0;
-	int numberofdofs=0;
-	int* doflist=NULL;
-
-	/*First, figure out size of doflist and create it: */
-	for(i=0;i<3;i++) numberofdofs+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
-	doflist=(int*)xmalloc(numberofdofs*sizeof(int));
-
-	/*Populate: */
-	count=0;
-	for(i=0;i<3;i++){
-		nodes[i]->GetDofList(doflist+count,approximation_enum,setenum);
-		count+=nodes[i]->GetNumberOfDofs(approximation_enum,setenum);
-	}
-
-	/*Assign output pointers:*/
-	*pdoflist=doflist;
-}
-/*}}}*/
-/*FUNCTION Tria::GetDofList1 {{{1*/
-void  Tria::GetDofList1(int* doflist){
-
-	int i;
-	for(i=0;i<3;i++) doflist[i]=nodes[i]->GetDofList1();
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetElementType {{{1*/
-int Tria::GetElementType(){
-
-	/*return TriaRef field*/
-	return this->element_type;
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetHorizontalNeighboorSids {{{1*/
-int* Tria::GetHorizontalNeighboorSids(){
-
-	/*return TriaRef field*/
-	return &this->horizontalneighborsids[0];
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetNodeIndex {{{1*/
-int Tria::GetNodeIndex(Node* node){
-
-	_assert_(nodes);
-	for(int i=0;i<NUMVERTICES;i++){
-		if(node==nodes[i])
-		 return i;
-	}
-	_error_("Node provided not found among element nodes");
-}
-/*}}}*/
-/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype) {{{1*/
-void Tria::GetParameterListOnVertices(double* pvalue,int enumtype){
-
-	/*Intermediaries*/
-	double     value[NUMVERTICES];
-	GaussTria *gauss              = NULL;
-
-	/*Recover input*/
-	Input* input=inputs->GetInput(enumtype);
-	if (!input) _error_("Input %s not found in element",EnumToStringx(enumtype));
-
-	/*Checks in debugging mode*/
-	_assert_(pvalue);
-
-	/* Start looping on the number of vertices: */
-	gauss=new GaussTria();
-	for (int iv=0;iv<NUMVERTICES;iv++){
-		gauss->GaussVertex(iv);
-		input->GetParameterValue(&pvalue[iv],gauss);
-	}
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue) {{{1*/
-void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue){
-
-	double     value[NUMVERTICES];
-	GaussTria *gauss = NULL;
-	Input     *input = inputs->GetInput(enumtype);
-
-	/*Checks in debugging mode*/
-	_assert_(pvalue);
-
-	/* Start looping on the number of vertices: */
-	if (input){
-		gauss=new GaussTria();
-		for (int iv=0;iv<NUMVERTICES;iv++){
-			gauss->GaussVertex(iv);
-			input->GetParameterValue(&pvalue[iv],gauss);
-		}
-	}
-	else{
-		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
-	}
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index) TO BE REMOVED{{{1*/
-void Tria::GetParameterListOnVertices(double* pvalue,int enumtype,double defaultvalue,int index){
-
-	double     value[NUMVERTICES];
-	GaussTria *gauss = NULL;
-	Input     *input = inputs->GetInput(enumtype);
-
-	/*Checks in debugging mode*/
-	_assert_(pvalue);
-
-	/* Start looping on the number of vertices: */
-	if (input){
-		gauss=new GaussTria();
-		for (int iv=0;iv<NUMVERTICES;iv++){
-			gauss->GaussVertex(iv);
-			input->GetParameterValue(&pvalue[iv],gauss,index);
-		}
-	}
-	else{
-		for (int iv=0;iv<NUMVERTICES;iv++) pvalue[iv]=defaultvalue;
-	}
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GetParameterValue(double* pvalue,Node* node,int enumtype) {{{1*/
-void Tria::GetParameterValue(double* pvalue,Node* node,int enumtype){
-
-	Input* input=inputs->GetInput(enumtype);
-	if(!input) _error_("No input of type %s found in tria",EnumToStringx(enumtype));
-
-	GaussTria* gauss=new GaussTria();
-	gauss->GaussVertex(this->GetNodeIndex(node));
-
-	input->GetParameterValue(pvalue,gauss);
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GetSidList {{{1*/
-void  Tria::GetSidList(int* sidlist){
-
-	int i;
-	for(i=0;i<NUMVERTICES;i++) sidlist[i]=nodes[i]->GetSidList();
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetSolutionFromInputs{{{1*/
-void  Tria::GetSolutionFromInputs(Vec 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: */
-	if (analysis_type==DiagnosticHorizAnalysisEnum)
-	 GetSolutionFromInputsDiagnosticHoriz(solution);
-	else if (analysis_type==DiagnosticHutterAnalysisEnum)
-	 GetSolutionFromInputsDiagnosticHutter(solution);
-	else if (analysis_type==HydrologyAnalysisEnum)
-	 GetSolutionFromInputsHydrology(solution);
-	else
-	 _error_("analysis: %s not supported yet",EnumToStringx(analysis_type));
-
-}
-/*}}}*/
-/*FUNCTION Tria::GetSolutionFromInputsDiagnosticHoriz{{{1*/
-void  Tria::GetSolutionFromInputsDiagnosticHoriz(Vec solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int          i;
-	int*         doflist=NULL;
-	double       vx,vy;
-	double       values[numdof];
-	GaussTria*   gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Get inputs*/
-	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 GaussTria();
-	for(i=0;i<NUMVERTICES;i++){
-
-		gauss->GaussVertex(i);
-
-		/*Recover vx and vy*/
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		values[i*NDOF2+0]=vx;
-		values[i*NDOF2+1]=vy;
-	}
-
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Tria::GetSolutionFromInputsDiagnosticHutter{{{1*/
-void  Tria::GetSolutionFromInputsDiagnosticHutter(Vec solution){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int i,dummy;
-	int*         doflist=NULL;
-	double       vx,vy;
-	double       values[numdof];
-	GaussTria*   gauss=NULL;
-
-	/*Get dof list: */
-	GetDofList(&doflist,NoneApproximationEnum,GsetEnum);
-
-	/*Get inputs*/
-	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 GaussTria();
-	for(i=0;i<NUMVERTICES;i++){
-
-		gauss->GaussVertex(i);
-
-		/*Recover vx and vy*/
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		values[i*NDOF2+0]=vx;
-		values[i*NDOF2+1]=vy;
-	}
-
-	VecSetValues(solution,numdof,doflist,(const double*)values,INSERT_VALUES);
-
-	/*Free ressources:*/
-	delete gauss;
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*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);
-
-	/*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:*/
-	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::Gradj {{{1*/
-void  Tria::Gradj(Vec gradient,int control_type){
-	/*dJ/dalpha = ∂L/∂alpha = ∂J/∂alpha + ∂/∂alpha(KU-F)*/
-
-	/*If on water, grad = 0: */
-	if(IsOnWater()) return;
-
-	/*First deal with ∂/∂alpha(KU-F)*/
-	switch(control_type){
-		case FrictionCoefficientEnum:
-			GradjDragMacAyeal(gradient);
-			break;
-		case MaterialsRheologyBbarEnum:
-			GradjBMacAyeal(gradient);
-			break;
-		case BalancethicknessThickeningRateEnum:
-			GradjDhDtBalancedthickness(gradient);
-			break;
-		case VxEnum:
-			GradjVxBalancedthickness(gradient);
-			break;
-		case VyEnum:
-			GradjVyBalancedthickness(gradient);
-			break;
-		default:
-			_error_("%s%i","control type not supported yet: ",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]){
-		//FIXME: the control type should be checked somewhere (with respect to what variable are we taking the gradient!)
-
-		case ThicknessAbsMisfitEnum:
-		case ThicknessAbsGradientEnum:
-		case SurfaceAbsVelMisfitEnum:
-		case SurfaceRelVelMisfitEnum:
-		case SurfaceLogVelMisfitEnum:
-		case SurfaceLogVxVyMisfitEnum:
-		case SurfaceAverageVelMisfitEnum:
-			/*Nothing, J does not depends on the parameter being inverted for*/
-			break;
-		case DragCoefficientAbsGradientEnum:
-			GradjDragGradient(gradient,resp);
-			break;
-		case RheologyBbarAbsGradientEnum:
-			GradjBGradient(gradient,resp);
-			break;
-		default:
-			_error_("response %s not supported yet",EnumToStringx(responses[resp]));
-	}
-
-	xfree((void**)&responses);
-}
-/*}}}*/
-/*FUNCTION Tria::GradjBGradient{{{1*/
-void  Tria::GradjBGradient(Vec gradient, int weight_index){
-
-	int        i,ig;
-	int        doflist1[NUMVERTICES];
-	double     Jdet,weight;
-	double     xyz_list[NUMVERTICES][3];
-	double     dbasis[NDOF2][NUMVERTICES];
-	double     dk[NDOF2]; 
-	double     grade_g[NUMVERTICES]={0.0};
-	GaussTria  *gauss=NULL;
-
-	/*Retrieve all inputs we will be needing: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist1[0]);
-	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);                _assert_(weights_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);
-		GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss);
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-
-		/*Build alpha_complement_list: */
-		rheologyb_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[i]+=-weight*Jdet*gauss->weight*(dbasis[0][i]*dk[0]+dbasis[1][i]*dk[1]);
-	}
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GradjBMacAyeal{{{1*/
-void  Tria::GradjBMacAyeal(Vec gradient){
-
-	/*Intermediaries*/
-	int        i,ig;
-	int        doflist[NUMVERTICES];
-	double     vx,vy,lambda,mu,thickness,Jdet;
-	double     viscosity_complement;
-	double     dvx[NDOF2],dvy[NDOF2],dadjx[NDOF2],dadjy[NDOF2],dB[NDOF2]; 
-	double     xyz_list[NUMVERTICES][3];
-	double     basis[3],epsilon[3];
-	double     grad[NUMVERTICES]={0.0};
-	GaussTria *gauss = NULL;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist[0]);
-
-	/*Retrieve all inputs*/
-	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* adjointx_input=inputs->GetInput(AdjointxEnum);              _assert_(adjointx_input);
-	Input* adjointy_input=inputs->GetInput(AdjointyEnum);              _assert_(adjointy_input);
-	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		thickness_input->GetParameterValue(&thickness,gauss);
-		rheologyb_input->GetParameterDerivativeValue(&dB[0],&xyz_list[0][0],gauss);
-		vx_input->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],gauss);
-		vy_input->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],gauss);
-		adjointx_input->GetParameterDerivativeValue(&dadjx[0],&xyz_list[0][0],gauss);
-		adjointy_input->GetParameterDerivativeValue(&dadjy[0],&xyz_list[0][0],gauss);
-
-		this->GetStrainRate2d(&epsilon[0],&xyz_list[0][0],gauss,vx_input,vy_input);
-		matice->GetViscosityComplement(&viscosity_complement,&epsilon[0]);
-
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctions(basis,gauss);
-
-		/*standard gradient dJ/dki*/
-		for (i=0;i<NUMVERTICES;i++) grad[i]+=-viscosity_complement*thickness*(
-					(2*dvx[0]+dvy[1])*2*dadjx[0]+(dvx[1]+dvy[0])*(dadjx[1]+dadjy[0])+(2*dvy[1]+dvx[0])*2*dadjy[1]
-					)*Jdet*gauss->weight*basis[i];
-	}
-
-	VecSetValues(gradient,NUMVERTICES,doflist,(const double*)grad,ADD_VALUES);
-
-	/*clean-up*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GradjDragMacAyeal {{{1*/
-void  Tria::GradjDragMacAyeal(Vec gradient){
-
-	int        i,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     dk[NDOF2]; 
-	double     grade_g[NUMVERTICES]={0.0};
-	double     grade_g_gaussian[NUMVERTICES];
-	double     basis[3];
-	double     epsilon[3]; /* epsilon=[exx,eyy,exy];*/
-	Friction*  friction=NULL;
-	GaussTria  *gauss=NULL;
-
-	if(IsOnShelf())return;
-
-	/*retrive parameters: */
-	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist1[0]);
-
-	/*Build frictoin element, needed later: */
-	friction=new Friction("2d",inputs,matpar,analysis_type);
-
-	/*Retrieve all inputs we will be needing: */
-	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);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-		GetNodalFunctions(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];
-		}
-		
-		/*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];
-		}
-	}
-	/*Analytical gradient*/
-	//delete gauss;
-	//gauss=new GaussTria();
-	//for (int iv=0;iv<NUMVERTICES;iv++){
-	//	gauss->GaussVertex(iv);
-	//	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);
-	//	grade_g[iv]=-2*drag*alpha_complement*((lambda*vx+mu*vy));
-	//	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,INSERT_VALUES);
-	//}
-	/*End Analytical gradient*/
-
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-	delete friction;
-}
-/*}}}*/
-/*FUNCTION Tria::GradjDragGradient{{{1*/
-void  Tria::GradjDragGradient(Vec gradient, int weight_index){
-
-	int        i,ig;
-	int        doflist1[NUMVERTICES];
-	double     Jdet,weight;
-	double     xyz_list[NUMVERTICES][3];
-	double     dbasis[NDOF2][NUMVERTICES];
-	double     dk[NDOF2]; 
-	double     grade_g[NUMVERTICES]={0.0};
-	GaussTria  *gauss=NULL;
-
-	/*Retrieve all inputs we will be needing: */
-	if(IsOnShelf())return;
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist1[0]);
-	Input* dragcoefficient_input=inputs->GetInput(FrictionCoefficientEnum); _assert_(dragcoefficient_input);
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);                 _assert_(weights_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);
-		GetNodalFunctionsDerivatives(&dbasis[0][0],&xyz_list[0][0],gauss);
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-
-		/*Build alpha_complement_list: */
-		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[i]+=-weight*Jdet*gauss->weight*(dbasis[0][i]*dk[0]+dbasis[1][i]*dk[1]);
-			_assert_(!isnan(grade_g[i]));
-		}
-	}
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GradjDhDtBalancedthickness{{{1*/
-void  Tria::GradjDhDtBalancedthickness(Vec gradient){
-
-	/*Intermediaries*/
-	int    doflist1[NUMVERTICES];
-	double lambda[NUMVERTICES];
-	double gradient_g[NUMVERTICES];
-
-	GetDofList1(&doflist1[0]);
-
-	/*Compute Gradient*/
-	GetParameterListOnVertices(&lambda[0],AdjointEnum);
-	for(int i=0;i<NUMVERTICES;i++) gradient_g[i]=-lambda[i];
-
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)gradient_g,INSERT_VALUES);
-}
-/*}}}*/
-/*FUNCTION Tria::GradjVxBalancedthickness{{{1*/
-void  Tria::GradjVxBalancedthickness(Vec gradient){
-
-	/*Intermediaries*/
-	int        i,ig;
-	int        doflist1[NUMVERTICES];
-	double     thickness,Jdet;
-	double     basis[3];
-	double     Dlambda[2],dp[2];
-	double     xyz_list[NUMVERTICES][3];
-	double     grade_g[NUMVERTICES] = {0.0};
-	GaussTria *gauss                = NULL;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist1[0]);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* adjoint_input=inputs->GetInput(AdjointEnum);     _assert_(adjoint_input);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_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);
-		
-		adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss);
-		thickness_input->GetParameterValue(&thickness, gauss);
-		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
-
-		for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[0]*Jdet*gauss->weight*basis[i];
-	}
-
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-}
-/*}}}*/
-/*FUNCTION Tria::GradjVyBalancedthickness{{{1*/
-void  Tria::GradjVyBalancedthickness(Vec gradient){
-
-	/*Intermediaries*/
-	int        i,ig;
-	int        doflist1[NUMVERTICES];
-	double     thickness,Jdet;
-	double     basis[3];
-	double     Dlambda[2],dp[2];
-	double     xyz_list[NUMVERTICES][3];
-	double     grade_g[NUMVERTICES] = {0.0};
-	GaussTria *gauss                = NULL;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	GetDofList1(&doflist1[0]);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* adjoint_input=inputs->GetInput(AdjointEnum);     _assert_(adjoint_input);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_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);
-
-		adjoint_input->GetParameterDerivativeValue(&Dlambda[0],&xyz_list[0][0],gauss);
-		thickness_input->GetParameterValue(&thickness, gauss);
-		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
-
-		for(i=0;i<NUMVERTICES;i++) grade_g[i]+=thickness*Dlambda[1]*Jdet*gauss->weight*basis[i];
-	}
-	VecSetValues(gradient,NUMVERTICES,doflist1,(const double*)grade_g,ADD_VALUES);
-
-	/*Clean up and return*/
-	delete gauss;
-}
-/*}}}*/
-/*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::InputControlUpdate{{{1*/
-void  Tria::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){
-			input=(Input*)matice->inputs->GetInput(control_type[i]); _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();
-
-	}
-
-	/*Clean up and return*/
-	xfree((void**)&control_type);
-}
-/*}}}*/
+#endif
+
 /*FUNCTION Tria::InputConvergence{{{1*/
 bool Tria::InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums){
@@ -3226,5 +3682,7 @@
 	 * 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
 }
 /*}}}*/
@@ -3282,4 +3740,5 @@
 
 	/*Control Inputs*/
+	#ifdef _HAVE_CONTROL_
 	if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
 		for(i=0;i<num_control_type;i++){
@@ -3324,4 +3783,5 @@
 		}
 	}
+	#endif
 
 	/*DatasetInputs*/
@@ -3355,7 +3815,12 @@
 			InputUpdateFromSolutionDiagnosticHoriz( solution);
 			break;
+		#ifdef _HAVE_CONTROL_
 		case AdjointHorizAnalysisEnum:
 			InputUpdateFromSolutionAdjointHoriz( solution);
 			break;
+		case AdjointBalancethicknessAnalysisEnum:
+			InputUpdateFromSolutionAdjointBalancethickness( solution);
+			break;
+		#endif
 		case BedSlopeXAnalysisEnum:
 			InputUpdateFromSolutionOneDof(solution,BedSlopeXEnum);
@@ -3379,74 +3844,7 @@
 			InputUpdateFromSolutionOneDof(solution,ThicknessEnum);
 			break;
-		case AdjointBalancethicknessAnalysisEnum:
-			InputUpdateFromSolutionAdjointBalancethickness( solution);
-			break;
 		default:
 			_error_("analysis %i (%s) not supported yet",analysis_type,EnumToStringx(analysis_type));
 	}
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionAdjointBalancethickness {{{1*/
-void  Tria::InputUpdateFromSolutionAdjointBalancethickness(double* solution){
-
-	const int numdof=NDOF1*NUMVERTICES;
-
-	int       i;
-	int*      doflist=NULL;
-	double    values[numdof];
-	double    lambda[NUMVERTICES];
-
-	/*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<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(AdjointEnum,lambda));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
-}
-/*}}}*/
-/*FUNCTION Tria::InputUpdateFromSolutionAdjointHoriz {{{1*/
-void  Tria::InputUpdateFromSolutionAdjointHoriz(double* solution){
-
-	const int numdof=NDOF2*NUMVERTICES;
-
-	int       i;
-	int*      doflist=NULL;
-	double    values[numdof];
-	double    lambdax[NUMVERTICES];
-	double    lambday[NUMVERTICES];
-
-	/*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 TriaVertexInput(AdjointxEnum,lambdax));
-	this->inputs->AddInput(new TriaVertexInput(AdjointyEnum,lambday));
-
-	/*Free ressources:*/
-	xfree((void**)&doflist);
 }
 /*}}}*/
@@ -3751,4 +4149,7 @@
 }
 /*}}}*/
+
+
+#ifdef _HAVE_DAKOTA_
 /*FUNCTION Tria::InputUpdateFromVectorDakota(double* vector, int name, int type);{{{1*/
 void  Tria::InputUpdateFromVectorDakota(double* vector, int name, int type){
@@ -3863,4 +4264,5 @@
 }
 /*}}}*/
+#endif
 /*FUNCTION Tria::InputCreate(double scalar,int enum,int code);{{{1*/
 void Tria::InputCreate(double scalar,int name,int code){
@@ -4480,48 +4882,4 @@
 }
 /*}}}*/
-/*FUNCTION Tria::RheologyBbarAbsGradient{{{1*/
-double Tria::RheologyBbarAbsGradient(bool process_units,int weight_index){
-
-	/* Intermediaries */
-	int        ig;
-	double     Jelem = 0;
-	double     weight;
-	double     Jdet;
-	double     xyz_list[NUMVERTICES][3];
-	double     dp[NDOF2];
-	GaussTria *gauss = NULL;
-
-	/*retrieve parameters and inputs*/
-
-	/*If on water, return 0: */
-	if(IsOnWater()) return 0;
-
-	/*Retrieve all inputs we will be needing: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* weights_input  =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);              _assert_(weights_input);
-	Input* rheologyb_input=matice->inputs->GetInput(MaterialsRheologyBbarEnum); _assert_(rheologyb_input);
-
-	/* Start looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		rheologyb_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
-
-		/*Tikhonov regularization: J = 1/2 ((dp/dx)^2 + (dp/dy)^2) */ 
-		//Jelem+=weight*1/2*(pow(dp[0],2.)+pow(dp[1],2.))*Jdet*gauss->weight;
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
 /*FUNCTION Tria::RequestedOutput{{{1*/
 void Tria::RequestedOutput(int output_enum,int step,double time){
@@ -4698,65 +5056,4 @@
 	}
 /*}}}*/
-/*FUNCTION Tria::SurfaceAbsVelMisfit {{{1*/
-double Tria::SurfaceAbsVelMisfit(bool process_units,int weight_index){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int        i,ig;
-	double     Jelem=0;
-	double     misfit,Jdet;
-	double     vx,vy,vxobs,vyobs,weight;
-	double     xyz_list[NUMVERTICES][3];
-	GaussTria *gauss=NULL;
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
-	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
-	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
-	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vxobs_input->GetParameterValue(&vxobs,gauss);
-		vyobs_input->GetParameterValue(&vyobs,gauss);
-
-		/*Compute SurfaceAbsVelMisfitEnum:
-		 *
-		 *      1  [           2              2 ]
-		 * J = --- | (u - u   )  +  (v - v   )  |
-		 *      2  [       obs            obs   ]
-		 *
-		 */
-		misfit=0.5*( pow(vx-vxobs,2.) + pow(vy-vyobs,2.) );
-
-		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceAverageVelMisfitEnum);
-
-		/*Add to cost function*/
-		Jelem+=misfit*weight*Jdet*gauss->weight;
-	}
-
-	/*clean up and Return: */
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
 /*FUNCTION Tria::SurfaceArea {{{1*/
 double Tria::SurfaceArea(void){
@@ -4788,196 +5085,4 @@
 }
 /*}}}*/
-/*FUNCTION Tria::SurfaceAverageVelMisfit {{{1*/
-double Tria::SurfaceAverageVelMisfit(bool process_units,int weight_index){
-
-	const int    numdof=2*NUMVERTICES;
-
-	int        i,ig;
-	double     Jelem=0,S,Jdet;
-	double     misfit;
-	double     vx,vy,vxobs,vyobs,weight;
-	double     xyz_list[NUMVERTICES][3];
-	GaussTria *gauss=NULL;
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Retrieve all inputs we will be needing: */
-	inputs->GetParameterValue(&S,SurfaceAreaEnum);
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
-	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
-	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
-	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(3);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vxobs_input->GetParameterValue(&vxobs,gauss);
-		vyobs_input->GetParameterValue(&vyobs,gauss);
-
-		/*Compute SurfaceAverageVelMisfitEnum:
-		 *
-		 *      1                    2              2
-		 * J = ---  sqrt(  (u - u   )  +  (v - v   )  )
-		 *      S                obs            obs
-		 */
-		misfit=1/S*pow( pow(vx-vxobs,2.) + pow(vy-vyobs,2.) ,0.5);
-
-		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceAverageVelMisfitEnum);
-
-		/*Add to cost function*/
-		Jelem+=misfit*weight*Jdet*gauss->weight;
-	}
-
-	/*clean-up and Return: */
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
-/*FUNCTION Tria::SurfaceLogVelMisfit {{{1*/
-double Tria::SurfaceLogVelMisfit(bool process_units,int weight_index){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int        i,ig;
-	double     Jelem=0;
-	double     misfit,Jdet;
-	double     epsvel=2.220446049250313e-16;
-	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
-	double     velocity_mag,obs_velocity_mag;
-	double     xyz_list[NUMVERTICES][3];
-	double     vx,vy,vxobs,vyobs,weight;
-	GaussTria *gauss=NULL;
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
-	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
-	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
-	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vxobs_input->GetParameterValue(&vxobs,gauss);
-		vyobs_input->GetParameterValue(&vyobs,gauss);
-
-		/*Compute SurfaceLogVelMisfit:
-		 *                 [        vel + eps     ] 2
-		 * J = 4 \bar{v}^2 | log ( -----------  ) |  
-		 *                 [       vel   + eps    ]
-		 *                            obs
-		 */
-		velocity_mag    =sqrt(pow(vx,   2.)+pow(vy,   2.))+epsvel;
-		obs_velocity_mag=sqrt(pow(vxobs,2.)+pow(vyobs,2.))+epsvel;
-		misfit=4*pow(meanvel,2.)*pow(log(velocity_mag/obs_velocity_mag),2.);
-
-		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceLogVelMisfitEnum);
-
-		/*Add to cost function*/
-		Jelem+=misfit*weight*Jdet*gauss->weight;
-	}
-
-	/*clean-up and Return: */
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
-/*FUNCTION Tria::SurfaceLogVxVyMisfit {{{1*/
-double Tria::SurfaceLogVxVyMisfit(bool process_units,int weight_index){
-
-	const int    numdof=NDOF2*NUMVERTICES;
-
-	int        i,ig;
-	int        fit=-1;
-	double     Jelem=0, S=0;
-	double     epsvel=2.220446049250313e-16;
-	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
-	double     misfit, Jdet;
-	double     vx,vy,vxobs,vyobs,weight;
-	double     xyz_list[NUMVERTICES][3];
-	GaussTria *gauss=NULL;
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
-	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
-	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
-	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
-	
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vxobs_input->GetParameterValue(&vxobs,gauss);
-		vyobs_input->GetParameterValue(&vyobs,gauss);
-
-		/*Compute SurfaceRelVelMisfit:
-		 *
-		 *      1            [        |u| + eps     2          |v| + eps     2  ]
-		 * J = --- \bar{v}^2 | log ( -----------  )   +  log ( -----------  )   |  
-		 *      2            [       |u    |+ eps              |v    |+ eps     ]
-		 *                              obs                       obs
-		 */
-		misfit=0.5*pow(meanvel,2.)*(
-					pow(log((fabs(vx)+epsvel)/(fabs(vxobs)+epsvel)),2.) +
-					pow(log((fabs(vy)+epsvel)/(fabs(vyobs)+epsvel)),2.) );
-
-		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceLogVxVyMisfitEnum);
-
-		/*Add to cost function*/
-		Jelem+=misfit*weight*Jdet*gauss->weight;
-	}
-
-	/*clean-up and Return: */
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
 /*FUNCTION Tria::SurfaceNormal{{{1*/
 void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
@@ -5002,157 +5107,4 @@
 	*(surface_normal+1)=normal[1]/normal_norm;
 	*(surface_normal+2)=normal[2]/normal_norm;
-}
-/*}}}*/
-/*FUNCTION Tria::SurfaceRelVelMisfit {{{1*/
-double Tria::SurfaceRelVelMisfit(bool process_units,int weight_index){
-	const int  numdof=2*NUMVERTICES;
-
-	int        i,ig;
-	double     Jelem=0;
-	double     scalex=1,scaley=1;
-	double     misfit,Jdet;
-	double     epsvel=2.220446049250313e-16;
-	double     meanvel=3.170979198376458e-05; /*1000 m/yr*/
-	double     vx,vy,vxobs,vyobs,weight;
-	double     xyz_list[NUMVERTICES][3];
-	GaussTria *gauss=NULL;
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/* Get node coordinates and dof list: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-
-	/*Retrieve all inputs we will be needing: */
-	Input* weights_input=inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* vx_input     =inputs->GetInput(VxEnum);        _assert_(vx_input);
-	Input* vy_input     =inputs->GetInput(VyEnum);        _assert_(vy_input);
-	Input* vxobs_input  =inputs->GetInput(InversionVxObsEnum);     _assert_(vxobs_input);
-	Input* vyobs_input  =inputs->GetInput(InversionVyObsEnum);     _assert_(vyobs_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(4);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		vx_input->GetParameterValue(&vx,gauss);
-		vy_input->GetParameterValue(&vy,gauss);
-		vxobs_input->GetParameterValue(&vxobs,gauss);
-		vyobs_input->GetParameterValue(&vyobs,gauss);
-
-		/*Compute SurfaceRelVelMisfit:
-		 *                        
-		 *      1  [     \bar{v}^2             2   \bar{v}^2              2 ]
-		 * J = --- | -------------  (u - u   ) + -------------  (v - v   )  |
-		 *      2  [  (u   + eps)^2       obs    (v   + eps)^2       obs    ]
-		 *              obs                        obs                      
-		 */
-		scalex=pow(meanvel/(vxobs+epsvel),2.); if(vxobs==0)scalex=0;
-		scaley=pow(meanvel/(vyobs+epsvel),2.); if(vyobs==0)scaley=0;
-		misfit=0.5*(scalex*pow((vx-vxobs),2.)+scaley*pow((vy-vyobs),2.));
-		if(process_units)UnitConversion(misfit,IuToExtEnum,SurfaceRelVelMisfitEnum);
-
-		/*Add to cost function*/
-		Jelem+=misfit*weight*Jdet*gauss->weight;
-	}
-
-	/*clean up and Return: */
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
-/*FUNCTION Tria::ThicknessAbsGradient{{{1*/
-double Tria::ThicknessAbsGradient(bool process_units,int weight_index){
-
-	/* Intermediaries */
-	int        ig;
-	double     Jelem = 0;
-	double     weight;
-	double     Jdet;
-	double     xyz_list[NUMVERTICES][3];
-	double     dp[NDOF2];
-	GaussTria *gauss = NULL;
-
-	/*retrieve parameters and inputs*/
-
-	/*If on water, return 0: */
-	if(IsOnWater()) return 0;
-
-	/*Retrieve all inputs we will be needing: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* weights_input  =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);   _assert_(weights_input);
-	Input* thickness_input=inputs->GetInput(ThicknessEnum); _assert_(thickness_input);
-
-	/* Start looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get all parameters at gaussian point*/
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-		thickness_input->GetParameterDerivativeValue(&dp[0],&xyz_list[0][0],gauss);
-
-		/*Tikhonov regularization: J = 1/2 ((dp/dx)^2 + (dp/dy)^2) */ 
-		Jelem+=weight*1/2*(pow(dp[0],2.)+pow(dp[1],2.))*Jdet*gauss->weight;
-	}
-
-	/*Clean up and return*/
-	delete gauss;
-	return Jelem;
-}
-/*}}}*/
-/*FUNCTION Tria::ThicknessAbsMisfit {{{1*/
-double Tria::ThicknessAbsMisfit(bool process_units,int weight_index){
-
-	/*Intermediaries*/
-	int        i,ig;
-	double     thickness,thicknessobs,weight;
-	double     Jdet;
-	double     Jelem = 0;
-	double     xyz_list[NUMVERTICES][3];
-	GaussTria *gauss = NULL;
-	double     dH[2];
-
-	/*If on water, return 0: */
-	if(IsOnWater())return 0;
-
-	/*Retrieve all inputs we will be needing: */
-	GetVerticesCoordinates(&xyz_list[0][0], nodes, NUMVERTICES);
-	Input* thickness_input   =inputs->GetInput(ThicknessEnum);   _assert_(thickness_input);
-	Input* thicknessobs_input=inputs->GetInput(InversionThicknessObsEnum);_assert_(thicknessobs_input);
-	Input* weights_input     =inputs->GetInput(InversionCostFunctionsCoefficientsEnum);     _assert_(weights_input);
-
-	/* Start  looping on the number of gaussian points: */
-	gauss=new GaussTria(2);
-	for (ig=gauss->begin();ig<gauss->end();ig++){
-
-		gauss->GaussPoint(ig);
-
-		/* Get Jacobian determinant: */
-		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss);
-
-		/*Get parameters at gauss point*/
-		thickness_input->GetParameterValue(&thickness,gauss);
-		thickness_input->GetParameterDerivativeValue(&dH[0],&xyz_list[0][0],gauss);
-		thicknessobs_input->GetParameterValue(&thicknessobs,gauss);
-		weights_input->GetParameterValue(&weight,gauss,weight_index);
-
-		/*compute ThicknessAbsMisfit*/
-		Jelem+=0.5*pow(thickness-thicknessobs,2.0)*weight*Jdet*gauss->weight;
-	}
-
-	/* clean up and Return: */
-	delete gauss;
-	return Jelem;
 }
 /*}}}*/
Index: /issm/trunk/src/c/objects/Elements/Tria.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.h	(revision 9760)
+++ /issm/trunk/src/c/objects/Elements/Tria.h	(revision 9761)
@@ -62,7 +62,9 @@
 		void  InputUpdateFromVector(int* vector, int name, int type);
 		void  InputUpdateFromVector(bool* vector, int name, int type);
+		#ifdef _HAVE_DAKOTA_
 		void  InputUpdateFromVectorDakota(double* vector, int name, int type);
 		void  InputUpdateFromVectorDakota(int* vector, int name, int type);
 		void  InputUpdateFromVectorDakota(bool* vector, int name, int type);
+		#endif
 		void  InputUpdateFromConstant(double constant, int name);
 		void  InputUpdateFromConstant(int constant, int name);
@@ -78,5 +80,4 @@
 		void   CreateKMatrix(Mat Kff, Mat Kfs,Vec df);
 		void   CreatePVector(Vec pf);
-		double DragCoefficientAbsGradient(bool process_units,int weight_index);
 		int    GetNodeIndex(Node* node);
 		int    Sid();
@@ -88,4 +89,6 @@
 		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);
@@ -97,6 +100,19 @@
 		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);
-		void   InputControlUpdate(double scalar,bool save_parameter);
 		bool   InputConvergence(double* eps, int* enums,int num_enums,int* criterionenums,double* criterionvalues,int num_criterionenums);
 		void   InputCreate(double scalar,int name,int code);
@@ -105,8 +121,5 @@
 		void   InputDuplicate(int original_enum,int new_enum);
 		void   InputScale(int enum_type,double scale_factor);
-		void   ControlInputGetGradient(Vec gradient,int enum_type);
-		void   ControlInputScaleGradient(int enum_type,double scale);
-		void   ControlInputSetGradient(double* gradient,int enum_type);
-		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");};
@@ -129,12 +142,4 @@
 		void   MinVz(double* pminvz, bool process_units);
 		void   RequestedOutput(int output_enum,int step,double time);
-		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   PatchFill(int* pcount, Patch* patch);
 		void   PatchSize(int* pnumrows, int* pnumvertices,int* pnumnodes);
Index: /issm/trunk/src/c/objects/ExternalResults/PetscVecExternalResult.cpp
===================================================================
--- /issm/trunk/src/c/objects/ExternalResults/PetscVecExternalResult.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/ExternalResults/PetscVecExternalResult.cpp	(revision 9761)
@@ -206,4 +206,5 @@
 	char   *name      = NULL;
 	double *serialvec = NULL;
+	extern int my_rank;
 
 	/*serialize: */
Index: /issm/trunk/src/c/objects/FemModel.cpp
===================================================================
--- /issm/trunk/src/c/objects/FemModel.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/FemModel.cpp	(revision 9761)
@@ -13,4 +13,5 @@
 #include "../Container/Container.h"
 #include "../modules/ModelProcessorx/ModelProcessorx.h"
+#include "../io/io.h"
 #include "./objects.h"
 #include "../include/include.h"
@@ -27,4 +28,5 @@
 	int analysis_type;
 	FILE* IOMODEL;
+	extern int my_rank;
 
 	/*Open input file on cpu 0: */
Index: /issm/trunk/src/c/objects/IoModel.cpp
===================================================================
--- /issm/trunk/src/c/objects/IoModel.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/IoModel.cpp	(revision 9761)
@@ -16,4 +16,5 @@
 
 #include "./objects.h"
+#include "../io/io.h"
 #include "./Container/Parameters.h"
 #include "../shared/shared.h"
Index: /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Attribute.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Attribute.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Attribute.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_ColorStyle.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_ColorStyle.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_ColorStyle.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Container.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Container.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Container.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Document.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Document.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Document.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Feature.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Feature.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Feature.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_File.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_File.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_File.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Folder.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Folder.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Folder.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_GroundOverlay.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_GroundOverlay.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_GroundOverlay.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Icon.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Icon.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Icon.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_LatLonBox.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_LatLonBox.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_LatLonBox.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_LineString.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_LineString.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_LineString.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_LineStyle.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_LineStyle.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_LineStyle.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_LinearRing.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_LinearRing.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_LinearRing.cpp	(revision 9761)
@@ -17,4 +17,5 @@
 #include "../../Container/Container.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../modules/Ll2xyx/Ll2xyx.h"
 /*}}}*/
Index: /issm/trunk/src/c/objects/KML/KML_MultiGeometry.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_MultiGeometry.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_MultiGeometry.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Object.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Object.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Object.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Overlay.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Overlay.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Overlay.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Placemark.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Placemark.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Placemark.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_PolyStyle.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_PolyStyle.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_PolyStyle.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Polygon.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Polygon.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Polygon.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/KML/KML_Style.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KML_Style.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/KML/KML_Style.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Materials/Matice.cpp
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 9761)
@@ -686,4 +686,5 @@
 
 		/*Control Inputs*/
+		#ifdef _HAVE_CONTROL_
 		if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
 			for(i=0;i<num_control_type;i++){
@@ -701,4 +702,5 @@
 			}
 		}
+		#endif
 	}
 
@@ -725,4 +727,5 @@
 
 		/*Control Inputs*/
+		#ifdef _HAVE_CONTROL_
 		if (control_analysis && iomodel->Data(InversionControlParametersEnum)){
 			for(i=0;i<num_control_type;i++){
@@ -740,4 +743,5 @@
 			}
 		}
+		#endif
 	}
 	else{
Index: /issm/trunk/src/c/objects/Options/Option.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/Option.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/Option.cpp	(revision 9761)
@@ -16,4 +16,5 @@
 #include "../../shared/shared.h"
 #include "../../Container/Container.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
 /*}}}*/
Index: /issm/trunk/src/c/objects/Options/OptionCell.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/OptionCell.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/OptionCell.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Options/OptionChar.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/OptionChar.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/OptionChar.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Options/OptionDouble.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/OptionDouble.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/OptionDouble.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Options/OptionLogical.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/OptionLogical.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/OptionLogical.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Options/OptionStruct.cpp
===================================================================
--- /issm/trunk/src/c/objects/Options/OptionStruct.cpp	(revision 9760)
+++ /issm/trunk/src/c/objects/Options/OptionStruct.cpp	(revision 9761)
@@ -15,4 +15,5 @@
 #include "../objects.h"
 #include "../../shared/shared.h"
+#include "../../io/io.h"
 #include "../../Container/Container.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/objects/Update.h
===================================================================
--- /issm/trunk/src/c/objects/Update.h	(revision 9760)
+++ /issm/trunk/src/c/objects/Update.h	(revision 9761)
@@ -17,8 +17,10 @@
 		virtual void  InputUpdateFromVector(double* vector, int name, int type)=0;
 		virtual void  InputUpdateFromVector(int* vector, int name, int type)=0;
-		virtual void  InputUpdateFromVector(bool* vector, int name, int type)=0;
+		virtual void  InputUpdateFromVector(bool* vector, int name, int type)=0; 
+		#ifdef _HAVE_DAKOTA_
 		virtual void  InputUpdateFromVectorDakota(double* vector, int name, int type)=0;
 		virtual void  InputUpdateFromVectorDakota(int* vector, int name, int type)=0;
 		virtual void  InputUpdateFromVectorDakota(bool* vector, int name, int type)=0;
+		#endif
 		virtual void  InputUpdateFromConstant(double constant, int name)=0;
 		virtual void  InputUpdateFromConstant(int constant, int name)=0;
Index: /issm/trunk/src/c/shared/Exceptions/Exceptions.cpp
===================================================================
--- /issm/trunk/src/c/shared/Exceptions/Exceptions.cpp	(revision 9760)
+++ /issm/trunk/src/c/shared/Exceptions/Exceptions.cpp	(revision 9761)
@@ -8,4 +8,5 @@
 #error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
 #endif
+
 #include "../shared.h"
 #include "../../include/include.h"
Index: /issm/trunk/src/c/shared/Matlab/matlabshared.h
===================================================================
--- /issm/trunk/src/c/shared/Matlab/matlabshared.h	(revision 9760)
+++ /issm/trunk/src/c/shared/Matlab/matlabshared.h	(revision 9761)
@@ -8,10 +8,8 @@
 #include "../../objects/objects.h"
 
-/*printf: */
-int PrintfFunction(char* format,...);
-int ModuleBoot(void);
 
 #ifdef _SERIAL_
 #include "mex.h"
+	int ModuleBoot(void);
 	mxArray* mxGetAssignedField(const mxArray* pmxa_array,int number, char* field);
 	int CheckNumMatlabArguments(int nlhs,int NLHS, int nrhs,int NRHS, char* THISFUNCTION, void (*function)( void ));
Index: /issm/trunk/src/c/shared/Matrix/MatrixUtils.cpp
===================================================================
--- /issm/trunk/src/c/shared/Matrix/MatrixUtils.cpp	(revision 9760)
+++ /issm/trunk/src/c/shared/Matrix/MatrixUtils.cpp	(revision 9761)
@@ -14,4 +14,5 @@
 #include <float.h>    /*  DBL_EPSILON  */
 #include "../../include/include.h"
+#include "../../io/io.h"
 /*}}}*/
 
Index: /issm/trunk/src/c/shared/Numerics/BrentSearch.cpp
===================================================================
--- /issm/trunk/src/c/shared/Numerics/BrentSearch.cpp	(revision 9760)
+++ /issm/trunk/src/c/shared/Numerics/BrentSearch.cpp	(revision 9761)
@@ -12,4 +12,5 @@
 #include "../../objects/objects.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../../shared/shared.h"
 #include <float.h>
Index: /issm/trunk/src/c/shared/Numerics/GaussPoints.cpp
===================================================================
--- /issm/trunk/src/c/shared/Numerics/GaussPoints.cpp	(revision 9760)
+++ /issm/trunk/src/c/shared/Numerics/GaussPoints.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../Alloc/alloc.h"
 #include "../../include/include.h"
+#include "../../io/io.h"
 #include "../Exceptions/exceptions.h"
 #include <math.h>
Index: /issm/trunk/src/c/shared/Numerics/OptimalSearch.cpp
===================================================================
--- /issm/trunk/src/c/shared/Numerics/OptimalSearch.cpp	(revision 9760)
+++ /issm/trunk/src/c/shared/Numerics/OptimalSearch.cpp	(revision 9761)
@@ -11,4 +11,5 @@
 #include "./numerics.h"
 #include "../../objects/objects.h"
+#include "../../io/io.h"
 #include "../../include/include.h"
 #include "../../shared/shared.h"
Index: /issm/trunk/src/c/shared/shared.h
===================================================================
--- /issm/trunk/src/c/shared/shared.h	(revision 9760)
+++ /issm/trunk/src/c/shared/shared.h	(revision 9761)
@@ -6,6 +6,6 @@
 #define _SHARED_H_
 
+
 #include "Alloc/alloc.h"
-#include "Matlab/matlabshared.h"
 #include "Exceptions/exceptions.h"
 #include "Exp/exp.h"
@@ -16,7 +16,7 @@
 #include "Numerics/numerics.h"
 #include "Dofs/dofs.h"
-#include "String/sharedstring.h" //to avoid confusion with <string.h> standard header file
 #include "Threads/issm_threads.h"
 #include "Bamg/shared.h"
+#include "Matlab/matlabshared.h"
 
 #endif
Index: /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp
===================================================================
--- /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/CorePointerFromSolutionEnum.cpp	(revision 9761)
@@ -20,14 +20,6 @@
 void CorePointerFromSolutionEnum(void (**psolutioncore)(FemModel*),Parameters* parameters,int solutiontype){
 
-	/*intermediary: */
-	bool control_analysis=false;
-	bool dakota_analysis=false;
-	
 	/*output: */
 	void (*solutioncore)(FemModel*)=NULL;
-
-	/*retrieve some parameters: */
-	parameters->FindParam(&control_analysis,InversionIscontrolEnum);
-	parameters->FindParam(&dakota_analysis,QmuIsdakotaEnum);
 
 	switch(solutiontype){
@@ -40,8 +32,16 @@
 			break;
 		case ThermalSolutionEnum:
+			#ifdef _HAVE_THERMAL_
 			solutioncore=&thermal_core;
+			#else
+			_error_("ISSM was not compiled with thermal capabilities. Exiting");
+			#endif
 			break;
 		case EnthalpySolutionEnum:
+			#ifdef _HAVE_THERMAL_
 			solutioncore=&enthalpy_core;
+			#else
+			_error_("ISSM was not compiled with thermal capabilities. Exiting");
+			#endif
 			break;
 		case PrognosticSolutionEnum:
Index: /issm/trunk/src/c/solutions/ResetBoundaryConditions.cpp
===================================================================
--- /issm/trunk/src/c/solutions/ResetBoundaryConditions.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/ResetBoundaryConditions.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../objects/objects.h"
 #include "../modules/modules.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 
Index: /issm/trunk/src/c/solutions/adjointbalancethickness_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/adjointbalancethickness_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/adjointbalancethickness_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/adjointdiagnostic_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/adjointdiagnostic_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/adjointdiagnostic_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/balancethickness_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/balancethickness_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/balancethickness_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../include/include.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/solutions/bedslope_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/bedslope_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/bedslope_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "../modules/modules.h"
Index: /issm/trunk/src/c/solutions/control_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/control_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/control_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/controlconvergence.cpp
===================================================================
--- /issm/trunk/src/c/solutions/controlconvergence.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/controlconvergence.cpp	(revision 9761)
@@ -10,4 +10,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../Container/Container.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
Index: /issm/trunk/src/c/solutions/controltao_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/controltao_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/controltao_core.cpp	(revision 9761)
@@ -2,5 +2,14 @@
  * \brief: core of the control solution 
  */ 
-#include "../issm.h"
+#include "../toolkits/toolkits.h"
+#include "../objects/objects.h"
+#include "../shared/shared.h"
+#include "../io/io.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "./solutions.h"
+#include "../modules/modules.h"
+#include "../include/include.h"
+#include "../solvers/solvers.h"
+
 
 #ifdef _HAVE_TAO_
Index: /issm/trunk/src/c/solutions/convergence.cpp
===================================================================
--- /issm/trunk/src/c/solutions/convergence.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/convergence.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../objects/objects.h"
 #include "../modules/modules.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 
Index: /issm/trunk/src/c/solutions/diagnostic_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/diagnostic_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/diagnostic_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/enthalpy_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/enthalpy_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/enthalpy_core.cpp	(revision 9761)
@@ -10,4 +10,5 @@
 #include "../modules/modules.h"
 #include "../include/include.h"
+#include "../io/io.h"
 #include "../solvers/solvers.h"
 
Index: /issm/trunk/src/c/solutions/gradient_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/gradient_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/gradient_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/groundinglinemigration2d_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/groundinglinemigration2d_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/groundinglinemigration2d_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/hydrology_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/hydrology_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/hydrology_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/hydrology_core_step.cpp
===================================================================
--- /issm/trunk/src/c/solutions/hydrology_core_step.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/hydrology_core_step.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/issm.cpp
===================================================================
--- /issm/trunk/src/c/solutions/issm.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/issm.cpp	(revision 9761)
@@ -3,5 +3,6 @@
  */ 
 
-#include "./issm.h"
+#include "../issm.h"
+#include "../include/globals.h"
 
 int main(int argc,char  **argv){
@@ -97,12 +98,19 @@
 	MPI_Barrier(MPI_COMM_WORLD); start_core=MPI_Wtime( );
 	if(dakota_analysis){
+		#ifdef _HAVE_DAKOTA_
 		Dakotax(femmodel);
+		#else
+		_error_("ISSM was not compiled with dakota support, cannot carry out dakota analysis!");
+		#endif
 	}
 	else if(control_analysis){
+		#ifdef _HAVE_CONTROL_
 		#ifdef _HAVE_TAO_
-		//controltao_core(femmodel);
-		control_core(femmodel);
+		controltao_core(femmodel);
 		#else
 		control_core(femmodel);
+		#endif
+		#else
+		_error_("ISSM was not compiled with control support, cannot carry out dakota analysis!");
 		#endif
 	}
Index: /issm/trunk/src/c/solutions/prognostic_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/prognostic_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/prognostic_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/steadystate_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/steadystate_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/steadystate_core.cpp	(revision 9761)
@@ -3,7 +3,14 @@
  */ 
 
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
@@ -39,5 +46,9 @@
 	
 		_printf_(VerboseSolution(),"%s%i\n","   computing temperature and velocity for step: ",step);
+		#ifdef _HAVE_THERMAL_
 		thermal_core(femmodel);
+		#else
+		_error_("ISSM was not compiled with thermal capabilities. Exiting");
+		#endif
 
 		_printf_(VerboseSolution(),"%s\n","   computing new velocity");
Index: /issm/trunk/src/c/solutions/surfaceslope_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/surfaceslope_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/surfaceslope_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "../solvers/solvers.h"
Index: /issm/trunk/src/c/solutions/thermal_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/thermal_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/thermal_core.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/thermal_core_step.cpp
===================================================================
--- /issm/trunk/src/c/solutions/thermal_core_step.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/thermal_core_step.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
Index: /issm/trunk/src/c/solutions/transient_core.cpp
===================================================================
--- /issm/trunk/src/c/solutions/transient_core.cpp	(revision 9760)
+++ /issm/trunk/src/c/solutions/transient_core.cpp	(revision 9761)
@@ -3,7 +3,14 @@
  */ 
 
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
 #include "../shared/shared.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "./solutions.h"
@@ -65,5 +72,9 @@
 		if(isthermal && dim==3){
 			_printf_(VerboseSolution(),"   computing temperatures:\n");
+			#ifdef _HAVE_THERMAL_
 			thermal_core_step(femmodel,step,time);
+			#else
+			_error_("ISSM was not compiled with thermal capabilities. Exiting");
+			#endif
 		}
 
Index: /issm/trunk/src/c/solvers/solver_nonlinear.cpp
===================================================================
--- /issm/trunk/src/c/solvers/solver_nonlinear.cpp	(revision 9760)
+++ /issm/trunk/src/c/solvers/solver_nonlinear.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "../modules/modules.h"
Index: /issm/trunk/src/c/solvers/solver_stokescoupling_nonlinear.cpp
===================================================================
--- /issm/trunk/src/c/solvers/solver_stokescoupling_nonlinear.cpp	(revision 9760)
+++ /issm/trunk/src/c/solvers/solver_stokescoupling_nonlinear.cpp	(revision 9761)
@@ -6,4 +6,5 @@
 #include "../objects/objects.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
+#include "../io/io.h"
 #include "../modules/modules.h"
 #include "../solutions/solutions.h"
Index: /issm/trunk/src/c/solvers/solver_thermal_nonlinear.cpp
===================================================================
--- /issm/trunk/src/c/solvers/solver_thermal_nonlinear.cpp	(revision 9760)
+++ /issm/trunk/src/c/solvers/solver_thermal_nonlinear.cpp	(revision 9761)
@@ -5,4 +5,5 @@
 #include "../toolkits/toolkits.h"
 #include "../objects/objects.h"
+#include "../io/io.h"
 #include "../EnumDefinitions/EnumDefinitions.h"
 #include "../modules/modules.h"
