Index: /issm/trunk/src/c/objects/Bamg/BamgGeom.cpp
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgGeom.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgGeom.cpp	(revision 3683)
@@ -0,0 +1,18 @@
+#include "stdio.h"
+#include "../objects.h"
+
+void BamgGeomInit(BamgGeom* bamggeom){
+
+	bamggeom->VerticesSize[0]=0,  bamggeom->VerticesSize[1]=0;  bamggeom->Vertices=NULL;
+	bamggeom->EdgesSize[0]=0,     bamggeom->EdgesSize[1]=0;     bamggeom->Edges=NULL;
+	bamggeom->hVertices=NULL;
+	bamggeom->MetricVertices=NULL;
+	bamggeom->h1h2VpVertices=NULL;
+	bamggeom->TangentAtEdgesSize[0]=0,    bamggeom->TangentAtEdgesSize[1]=0;    bamggeom->TangentAtEdges=NULL;
+	bamggeom->CornersSize[0]=0,           bamggeom->CornersSize[1]=0;           bamggeom->Corners=NULL;
+	bamggeom->RequiredVerticesSize[0]=0,  bamggeom->RequiredVerticesSize[1]=0;  bamggeom->RequiredVertices=NULL;
+	bamggeom->RequiredEdgesSize[0]=0,     bamggeom->RequiredEdgesSize[1]=0;     bamggeom->RequiredEdges=NULL;
+	bamggeom->CrackedEdgesSize[0]=0,      bamggeom->CrackedEdgesSize[1]=0;      bamggeom->CrackedEdges=NULL;
+	bamggeom->SubDomainsSize[0]=0,        bamggeom->SubDomainsSize[1]=0;        bamggeom->SubDomains=NULL;
+
+}
Index: /issm/trunk/src/c/objects/Bamg/BamgGeom.h
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgGeom.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgGeom.h	(revision 3683)
@@ -0,0 +1,40 @@
+/*!\file:  BamgGeom.h
+ */ 
+
+#ifndef _BAMGGEOM_H_
+#define _BAMGGEOM_H_
+
+struct BamgGeom{
+
+	int     VerticesSize[2];
+	double* Vertices;
+
+	int     EdgesSize[2];
+	double* Edges;
+
+	double* hVertices;
+	double* MetricVertices;
+	double* h1h2VpVertices;
+
+	int     TangentAtEdgesSize[2];
+	double* TangentAtEdges;
+
+	int     CornersSize[2];
+	double* Corners;
+
+	int     RequiredVerticesSize[2];
+	double* RequiredVertices;
+
+	int     RequiredEdgesSize[2];
+	double* RequiredEdges;
+
+	int     CrackedEdgesSize[2];
+	double* CrackedEdges;
+
+	int     SubDomainsSize[2];
+	double* SubDomains;
+};
+
+void BamgGeomInit(BamgGeom* bamggeom);
+
+#endif
Index: /issm/trunk/src/c/objects/Bamg/BamgMesh.cpp
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgMesh.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgMesh.cpp	(revision 3683)
@@ -0,0 +1,24 @@
+#include "stdio.h"
+#include "../objects.h"
+
+void BamgMeshInit(BamgMesh* bamgmesh){
+
+	bamgmesh->TrianglesSize[0]=0,     bamgmesh->TrianglesSize[1]=0;      bamgmesh->Triangles=NULL;
+	bamgmesh->VerticesSize[0]=0,      bamgmesh->VerticesSize[1]=0;       bamgmesh->Vertices=NULL;
+	bamgmesh->EdgesSize[0]=0,         bamgmesh->EdgesSize[1]=0;          bamgmesh->Edges=NULL;
+	bamgmesh->ElementEdgesSize[0]=0,  bamgmesh->ElementEdgesSize[1]=0;   bamgmesh->ElementEdges=NULL;
+	bamgmesh->SegmentsSize[0]=0,      bamgmesh->SegmentsSize[1]=0;       bamgmesh->Segments=NULL;
+	bamgmesh->QuadrilateralsSize[0]=0,bamgmesh->QuadrilateralsSize[1]=0; bamgmesh->Quadrilaterals=NULL;
+	bamgmesh->VerticesOnGeometricVertexSize[0]=0, bamgmesh->VerticesOnGeometricVertexSize[1]=0;bamgmesh->VerticesOnGeometricVertex=NULL;
+	bamgmesh->VerticesOnGeometricEdgeSize[0]=0,   bamgmesh->VerticesOnGeometricEdgeSize[1]=0;  bamgmesh->VerticesOnGeometricEdge=NULL;
+	bamgmesh->EdgesOnGeometricEdgeSize[0]=0,      bamgmesh->EdgesOnGeometricEdgeSize[1]=0;     bamgmesh->EdgesOnGeometricEdge=NULL;
+	bamgmesh->SubDomainsSize[0]=0,         bamgmesh->SubDomainsSize[1]=0;          bamgmesh->SubDomains=NULL;
+	bamgmesh->SubDomainsFromGeomSize[0]=0, bamgmesh->SubDomainsFromGeomSize[1]=0;  bamgmesh->SubDomainsFromGeom=NULL;
+	bamgmesh->hVertices=NULL;
+	bamgmesh->ElementConnectivitySize[0]=0,      bamgmesh->ElementConnectivitySize[1]=0;      bamgmesh->ElementConnectivity=NULL;
+	bamgmesh->NodalConnectivitySize[0]=0,        bamgmesh->NodalConnectivitySize[1]=0;        bamgmesh->NodalConnectivity=NULL;
+	bamgmesh->NodalElementConnectivitySize[0]=0, bamgmesh->NodalElementConnectivitySize[1]=0; bamgmesh->NodalElementConnectivity=NULL;
+	bamgmesh->CrackedVerticesSize[0]=0, bamgmesh->CrackedVerticesSize[1]=0; bamgmesh->CrackedVertices=NULL;
+	bamgmesh->CrackedEdgesSize[0]=0, bamgmesh->CrackedEdgesSize[1]=0; bamgmesh->CrackedEdges=NULL;
+
+}
Index: /issm/trunk/src/c/objects/Bamg/BamgMesh.h
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgMesh.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgMesh.h	(revision 3683)
@@ -0,0 +1,62 @@
+/*!\file:  BamgMesh.h
+ */ 
+
+#ifndef _BAMGMESH_H_
+#define _BAMGMESH_H_
+
+struct BamgMesh{
+
+	int     TrianglesSize[2];
+	double* Triangles;
+
+	int     VerticesSize[2];
+	double* Vertices;
+
+	int     EdgesSize[2];
+	double* Edges;
+
+	int     ElementEdgesSize[2];
+	double* ElementEdges;
+
+	int     SegmentsSize[2];
+	double* Segments;
+
+	int     QuadrilateralsSize[2];
+	double* Quadrilaterals;
+
+	int     VerticesOnGeometricVertexSize[2];
+	double* VerticesOnGeometricVertex;
+
+	int     VerticesOnGeometricEdgeSize[2];
+	double* VerticesOnGeometricEdge;
+
+	int     EdgesOnGeometricEdgeSize[2];
+	double* EdgesOnGeometricEdge;
+
+	int     SubDomainsSize[2];
+	double* SubDomains;
+
+	int     SubDomainsFromGeomSize[2];
+	double* SubDomainsFromGeom;
+
+	double* hVertices;
+
+	int     ElementConnectivitySize[2];
+	double* ElementConnectivity;
+
+	int     NodalConnectivitySize[2];
+	double* NodalConnectivity;
+
+	int     NodalElementConnectivitySize[2];
+	double* NodalElementConnectivity;
+
+	int     CrackedVerticesSize[2];
+	double* CrackedVertices;
+
+	int     CrackedEdgesSize[2];
+	double* CrackedEdges;
+};
+
+void BamgMeshInit(BamgMesh* bamgmesh);
+
+#endif
Index: /issm/trunk/src/c/objects/Bamg/BamgOpts.cpp
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgOpts.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgOpts.cpp	(revision 3683)
@@ -0,0 +1,60 @@
+#include "stdio.h"
+#include "../../shared/shared.h"
+#include "../../include/macros.h"
+#include "../objects.h"
+
+void BamgOptsInit(BamgOpts* bamgopts){
+
+	bamgopts->iso=0;
+	bamgopts->maxnbv=0;
+	bamgopts->MaximalAngleOfCorner=0;
+	bamgopts->Hessiantype=0;
+	bamgopts->Metrictype=0;
+	bamgopts->KeepVertices=0;
+	bamgopts->Crack=0;
+	bamgopts->maxsubdiv=0;
+	bamgopts->power=0;
+	bamgopts->anisomax=0;
+	bamgopts->NbSmooth=0;
+	bamgopts->nbjacobi=0;
+	bamgopts->omega=0;
+	bamgopts->hmin=0;
+	bamgopts->hmax=0;
+	bamgopts->hminVertices=NULL;
+	bamgopts->hmaxVertices=NULL;
+	bamgopts->gradation=0;
+	bamgopts->cutoff=0;
+	bamgopts->splitcorners=0;
+	bamgopts->geometricalmetric=0;
+	bamgopts->verbose=0;
+	bamgopts->err=NULL;
+	bamgopts->errg=0;
+	bamgopts->coef=0;
+	bamgopts->metric=NULL;
+	bamgopts->field=NULL;
+	bamgopts->numfields=0;
+
+}
+
+void BamgOptsCheck(BamgOpts* bamgopts){
+
+	int i;
+
+	if (bamgopts->coef==0) ISSMERROR("'coef' should be positive");
+	if (bamgopts->maxsubdiv<=1) ISSMERROR("'maxsubdiv' should be >1");
+	if (bamgopts->Crack!=0  && bamgopts->Crack!=1) ISSMERROR("'Crack' supported options are 0 and 1");
+	if (bamgopts->Hessiantype!=0  && bamgopts->Hessiantype!=1) ISSMERROR("'Hessiantype' supported options are 0 and 1");
+	if (bamgopts->Metrictype!=0   && bamgopts->Metrictype!=1 && bamgopts->Metrictype!=2) ISSMERROR("'Metrictype' supported options are 0, 1 and 2");
+	if (bamgopts->KeepVertices!=0 && bamgopts->KeepVertices!=1) ISSMERROR("'KeepVertices' supported options are 0 and 1");
+	if (bamgopts->errg<0) ISSMERROR("'errg' option should be >0");
+	if (bamgopts->nbjacobi<=0) ISSMERROR("'nbjacobi' option should be >0");
+	if (bamgopts->geometricalmetric!=0  && bamgopts->geometricalmetric!=1) ISSMERROR("'geometricalmetric' supported options are 0 and 1");
+	if (bamgopts->NbSmooth<=0) ISSMERROR("'NbSmooth' option should be >0");
+	if (bamgopts->maxnbv<3) ISSMERROR("'maxnbv' option should be >3");
+	if (bamgopts->hmin<=0) ISSMERROR("'hmin' option should be >0");
+	if (bamgopts->hmax<=0 || bamgopts->hmax<bamgopts->hmin) ISSMERROR("'hmax' option should be between 0 and hmin=%g",bamgopts->hmin);
+	if (bamgopts->anisomax<1) ISSMERROR("'anisomax' option should be >=1");
+	if (bamgopts->gradation<1) ISSMERROR("'gradation' option should be >=1");
+	for (i=0;i<bamgopts->numfields;i++) {if (bamgopts->err[i]<=0) ISSMERROR("'err' option should be >0");};
+
+}
Index: /issm/trunk/src/c/objects/Bamg/BamgOpts.h
===================================================================
--- /issm/trunk/src/c/objects/Bamg/BamgOpts.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Bamg/BamgOpts.h	(revision 3683)
@@ -0,0 +1,45 @@
+/*!\file:  BamgOpts.h
+ * \brief place holder for optimization function arguments
+ */ 
+
+#ifndef _BAMGOPTS_H_
+#define _BAMGOPTS_H_
+
+struct BamgOpts{
+
+	int     iso;
+	int     maxnbv;
+	double  MaximalAngleOfCorner;
+	int     Crack;
+	int     Hessiantype;
+	int     Metrictype;
+	int     KeepVertices;
+	double  maxsubdiv;
+	double  power;
+	double  anisomax;
+	int     NbSmooth;
+	int     nbjacobi;
+	double  omega;
+	double  hmin;
+	double  hmax;
+	double* hminVertices;
+	double* hmaxVertices;
+	double  gradation;
+	double  cutoff;
+	int     splitcorners;
+	int     geometricalmetric;
+	int     verbose;
+	double* err;
+	double  errg;
+	double  coef;
+	double* metric;
+	double* field;
+	int     numfields;
+
+};
+
+void BamgOptsInit(BamgOpts* bamgopts);
+
+void BamgOptsCheck(BamgOpts* bamgopts);
+
+#endif
Index: /issm/trunk/src/c/objects/Constraints/Rgb.cpp
===================================================================
--- /issm/trunk/src/c/objects/Constraints/Rgb.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Constraints/Rgb.cpp	(revision 3683)
@@ -0,0 +1,161 @@
+/*!\file Rgb.c
+ * \brief: implementation of the Rgb object
+ */
+
+
+#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 "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../DataSet/DataSet.h"
+#include "../../shared/shared.h"
+#include "../../include/macros.h"
+#include "../objects.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION Rgb::constructor {{{1*/
+Rgb::Rgb(){
+	return;
+}
+/*}}}1*/
+/*FUNCTION Rgb::creation {{{1*/
+Rgb::Rgb(int rgb_id,int rgb_nodeid1,int rgb_nodeid2, int rgb_dof){
+
+	id=rgb_id;
+	nodeid1=rgb_nodeid1;
+	nodeid2=rgb_nodeid2;
+	dof=rgb_dof;
+
+	return;
+}
+/*}}}1*/
+/*FUNCTION Rgb::destructor {{{1*/
+Rgb::~Rgb(){
+	return;
+}
+/*}}}1*/
+		
+/*Object marshall*/
+/*FUNCTION Rgb::Marshall {{{1*/
+void  Rgb::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Rgb: */
+	enum_type=RgbEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Rgb data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(marshalled_dataset,&nodeid1,sizeof(nodeid1));marshalled_dataset+=sizeof(nodeid1);
+	memcpy(marshalled_dataset,&nodeid2,sizeof(nodeid2));marshalled_dataset+=sizeof(nodeid2);
+	memcpy(marshalled_dataset,&dof,sizeof(dof));marshalled_dataset+=sizeof(dof);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+/*FUNCTION Rgb::MarshallSize {{{1*/
+int   Rgb::MarshallSize(){
+
+	return sizeof(id)+
+		sizeof(nodeid1)+
+		sizeof(nodeid2)+
+		sizeof(dof)+
+		sizeof(int); //sizeof(int) for enum type
+}
+/*}}}1*/
+/*FUNCTION Rgb::Demarshall {{{1*/
+void  Rgb::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(&nodeid1,marshalled_dataset,sizeof(nodeid1));marshalled_dataset+=sizeof(nodeid1);
+	memcpy(&nodeid2,marshalled_dataset,sizeof(nodeid2));marshalled_dataset+=sizeof(nodeid2);
+	memcpy(&dof,marshalled_dataset,sizeof(dof));marshalled_dataset+=sizeof(dof);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Rgb::copy {{{1*/
+Object* Rgb::copy() {
+	return new Rgb(*this); 
+}
+/*}}}1*/
+/*FUNCTION Rgb::DeepEcho {{{1*/
+void Rgb::DeepEcho(void){
+
+	printf("Rgb:\n");
+	printf("   id: %i\n",id);
+	printf("   nodeid1: %i\n",nodeid1);
+	printf("   nodeid2: %i\n",nodeid2);
+	printf("   dof: %i\n",dof);
+	return;
+}		
+/*}}}1*/
+/*FUNCTION Rgb::Echo {{{1*/
+void Rgb::Echo(void){
+
+	printf("Rgb:\n");
+	printf("   id: %i\n",id);
+	printf("   nodeid1: %i\n",nodeid1);
+	printf("   nodeid2: %i\n",nodeid2);
+	printf("   dof: %i\n",dof);
+	return;
+}
+/*}}}1*/
+/*FUNCTION Rgb::Enum {{{1*/
+int Rgb::Enum(void){
+
+	return RgbEnum;
+
+}
+/*}}}1*/
+/*FUNCTION Rgb::Id {{{1*/
+int    Rgb::Id(void){ return id; }
+/*}}}1*/
+/*FUNCTION Rgb::GetNodeId1{{{1*/
+int   Rgb::GetNodeId1(){
+	
+	return nodeid1;
+}
+/*}}}1*/
+/*FUNCTION Rgb::GetNodeId2 {{{1*/
+int   Rgb::GetNodeId2(){
+	
+	return nodeid2;
+}
+/*}}}1*/
+/*FUNCTION Rgb::GetDof {{{1*/
+int Rgb::GetDof(){
+	return dof;
+}
+/*}}}1*/
+/*FUNCTION Rgb::MyRank {{{1*/
+int    Rgb::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Constraints/Rgb.h
===================================================================
--- /issm/trunk/src/c/objects/Constraints/Rgb.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Constraints/Rgb.h	(revision 3683)
@@ -0,0 +1,45 @@
+/*!\file Rgb.h
+ * \brief: header file for rgb object
+ */
+
+#ifndef _RGB_H_
+#define _RGB_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "../Object.h"
+class DataSet;
+/*}}}*/
+
+class Rgb: public Object{
+
+	private: 
+		int	id; /*! id, to track it*/
+		int	nodeid1; 
+		int	nodeid2; 
+		int dof; /*!component*/
+
+	public:
+
+		Rgb();
+		Rgb(int rgb_id,int rgb_nodeid1,int rgb_nodeid2, int rgb_dof);
+		~Rgb();
+
+		void   Echo();
+		void   DeepEcho();
+		void   Marshall(char** pmarshalled_dataset);
+		int    MarshallSize();
+		void   Demarshall(char** pmarshalled_dataset);
+		int    Enum();
+		int    Id(); 
+		int    MyRank();
+
+		/*non virtual: */
+		int    GetNodeId1();
+		int    GetNodeId2();
+		int    GetDof();
+		Object* copy();
+
+};
+
+#endif  /* _RGB_H_ */
Index: /issm/trunk/src/c/objects/Constraints/Spc.cpp
===================================================================
--- /issm/trunk/src/c/objects/Constraints/Spc.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Constraints/Spc.cpp	(revision 3683)
@@ -0,0 +1,160 @@
+/*!\file Spc.c
+ * \brief: implementation of the Spc object
+ */
+
+
+#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 "../../include/macros.h"
+#include "../../shared/shared.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../DataSet/DataSet.h"
+#include "../objects.h"
+
+		
+/*Object constructors and destructor*/
+/*FUNCTION Spc::constructor {{{1*/
+Spc::Spc(){
+	return;
+}
+/*}}}1*/
+/*FUNCTION Spc::creation {{{1*/
+Spc::Spc(int spc_sid,int spc_nodeid, int spc_dof,double spc_value){
+
+	sid=spc_sid;
+	nodeid=spc_nodeid;
+	dof=spc_dof;
+	value=spc_value;
+
+	return;
+}
+/*}}}1*/
+/*FUNCTION Spc::destructor {{{1*/
+Spc::~Spc(){
+	return;
+}
+/*}}}1*/
+		
+/*Object marshall*/
+/*FUNCTION Spc::Marshall {{{1*/
+void  Spc::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Spc: */
+	enum_type=SpcEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Spc data: */
+	memcpy(marshalled_dataset,&sid,sizeof(sid));marshalled_dataset+=sizeof(sid);
+	memcpy(marshalled_dataset,&nodeid,sizeof(nodeid));marshalled_dataset+=sizeof(nodeid);
+	memcpy(marshalled_dataset,&dof,sizeof(dof));marshalled_dataset+=sizeof(dof);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+/*FUNCTION Spc::MarshallSize {{{1*/
+int   Spc::MarshallSize(){
+
+	return sizeof(sid)+sizeof(nodeid)+sizeof(dof)+sizeof(value)+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}1*/
+/*FUNCTION Spc::Demarshall {{{1*/
+void  Spc::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&sid,marshalled_dataset,sizeof(sid));marshalled_dataset+=sizeof(sid);
+	memcpy(&nodeid,marshalled_dataset,sizeof(nodeid));marshalled_dataset+=sizeof(nodeid);
+	memcpy(&dof,marshalled_dataset,sizeof(dof));marshalled_dataset+=sizeof(dof);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Spc::copy {{{1*/
+Object* Spc::copy() {
+	return new Spc(*this); 
+}
+/*}}}1*/
+/*FUNCTION Spc::DeepEcho {{{1*/
+void Spc::DeepEcho(void){
+
+	printf("Spc:\n");
+	printf("   sid: %i\n",sid);
+	printf("   nodeid: %i\n",nodeid);
+	printf("   dof: %i\n",dof);
+	printf("   value: %g\n",value);
+	return;
+}		
+/*}}}1*/
+/*FUNCTION Spc::DistributeNumDofs {{{1*/
+void  Spc::DistributeNumDofs(int* numdofspernode,int analysis_type){return;}
+/*}}}1*/
+/*FUNCTION Spc::Echo {{{1*/
+void Spc::Echo(void){
+
+	printf("Spc:\n");
+	printf("   sid: %i\n",sid);
+	printf("   nodeid: %i\n",nodeid);
+	printf("   dof: %i\n",dof);
+	printf("   value: %g\n",value);
+	return;
+}
+/*}}}1*/
+/*FUNCTION Spc::Enum {{{1*/
+int Spc::Enum(void){
+
+	return SpcEnum;
+
+}
+/*}}}1*/
+/*FUNCTION Spc::GetDof {{{1*/
+int Spc::GetDof(){
+	return dof;
+}
+/*}}}1*/
+/*FUNCTION Spc::Id {{{1*/
+int    Spc::Id(void){ return sid; }
+/*}}}1*/
+/*FUNCTION Spc::GetNodeId {{{1*/
+int   Spc::GetNodeId(){
+	
+	return nodeid;
+}
+/*}}}1*/
+/*FUNCTION Spc::GetValue {{{1*/
+double Spc::GetValue(){
+	return value;
+}
+/*}}}1*/
+/*FUNCTION Spc::MyRank {{{1*/
+int    Spc::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Constraints/Spc.h
===================================================================
--- /issm/trunk/src/c/objects/Constraints/Spc.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Constraints/Spc.h	(revision 3683)
@@ -0,0 +1,44 @@
+/*!\file Spc.h
+ * \brief: header file for spc object
+ */
+
+#ifndef _SPC_H_
+#define _SPC_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "../Object.h"
+class DataSet;
+/*}}}*/
+
+class Spc: public Object{
+
+	private: 
+		int	sid; /*! id, to track it*/
+		int	nodeid; /*!node id*/
+		int dof; /*!component*/
+		double value; /*value*/
+
+	public:
+
+		Spc();
+		Spc(int sid,int nodeid, int dof,double value);
+		~Spc();
+
+		void   Echo();
+		void   DeepEcho();
+		void   Marshall(char** pmarshalled_dataset);
+		int    MarshallSize();
+		void   Demarshall(char** pmarshalled_dataset);
+		int    Enum();
+		int    Id(); 
+		int    MyRank();
+		void   DistributeNumDofs(int* numdofspernode,int analysis_type);
+		int    GetNodeId();
+		int    GetDof();
+		double GetValue();
+		Object* copy();
+
+};
+
+#endif  /* _SPC_H_ */
Index: /issm/trunk/src/c/objects/Elements/Beam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Beam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Beam.cpp	(revision 3683)
@@ -0,0 +1,715 @@
+/*!\file Beam.c
+ * \brief: implementation of the Beam object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION Beam::Beam(){{{1*/
+Beam::Beam(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+	return;
+}
+/*}}}*/
+/*FUNCTION Beam::Beam(int id, int* node_ids, int matice_id, int matpar_id){{{1*/
+Beam::Beam(int beam_id,int* beam_node_ids, int beam_matice_id, int beam_matpar_id):
+	hnodes(beam_node_ids,2),
+	hmatice(&beam_matice_id,1),
+	hmatpar(&beam_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=beam_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+}
+/*}}}*/
+/*FUNCTION Beam::Beam(int id, Hook* hnodes, Hook* hmatice, Hook* hmatpar, Parameters* beam_parameters, ElementProperties* properties){{{1*/
+Beam::Beam(int beam_id,Hook* beam_hnodes, Hook* beam_hmatice, Hook* beam_hmatpar, Parameters* beam_parameters, Inputs* beam_inputs):
+	hnodes(beam_hnodes),
+	hmatice(beam_hmatice),
+	hmatpar(beam_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=beam_id;
+	if(beam_inputs){
+		this->inputs=(Inputs*)beam_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=beam_parameters;
+}
+/*}}}*/
+/*FUNCTION Beam::Beam(int id, int i, IoModel* iomodel){{{1*/
+Beam::Beam(int beam_id, int index,IoModel* iomodel){
+
+	int i;
+
+	/*beam constructor input: */
+	int   beam_matice_id;
+	int   beam_matpar_id;
+	int   beam_node_ids[2];
+	double nodeinputs[2];
+
+	/*id: */
+	this->id=beam_id;
+
+	/*hooks: */
+	beam_matice_id=index+1; //refers to the corresponding material property card
+	beam_matpar_id=iomodel->numberofvertices2d*(iomodel->numlayers-1)+1;//refers to the corresponding matpar property card
+	beam_node_ids[0]=index+1;
+	beam_node_ids[1]=(int)iomodel->uppernodes[index]; //grid that lays right on top
+	
+	this->hnodes.Init(beam_node_ids,2);
+	this->hmatice.Init(&beam_matice_id,1);
+	this->hmatpar.Init(&beam_matpar_id,1);
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+
+	if (iomodel->thickness) {
+		nodeinputs[0]=iomodel->thickness[index];
+		nodeinputs[1]=iomodel->thickness[(int)(iomodel->uppernodes[index]-1)];
+		this->inputs->AddInput(new BeamVertexInput(ThicknessEnum,nodeinputs));
+	}
+	if (iomodel->surface) {
+		nodeinputs[0]=iomodel->surface[index];
+		nodeinputs[1]=iomodel->surface[(int)(iomodel->uppernodes[index]-1)];
+		this->inputs->AddInput(new BeamVertexInput(SurfaceEnum,nodeinputs));
+	}	
+	if (iomodel->bed) {
+		nodeinputs[0]=iomodel->bed[index];
+		nodeinputs[1]=iomodel->bed[(int)(iomodel->uppernodes[index]-1)];
+		this->inputs->AddInput(new BeamVertexInput(BedEnum,nodeinputs));
+	}	
+	if (iomodel->drag_coefficient) {
+		nodeinputs[0]=iomodel->drag_coefficient[index];
+		nodeinputs[1]=iomodel->drag_coefficient[(int)(iomodel->uppernodes[index]-1)];
+		this->inputs->AddInput(new BeamVertexInput(DragCoefficientEnum,nodeinputs));
+	}	
+	if (iomodel->gridonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->gridonbed[index]));
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+
+
+}
+/*}}}*/
+/*FUNCTION Beam::~Beam(){{{1*/
+Beam::~Beam(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION Beam::Configure{{{1*/
+void  Beam::Configure(DataSet* loadsin, DataSet* nodesin, DataSet* materialsin, Parameters* parametersin){
+
+	int i;
+	
+	/*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: */
+	hnodes.configure(nodesin);
+	hmatice.configure(materialsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION Beam::copy{{{1*/
+Object* Beam::copy() {
+	
+	return new Beam(this->id,&this->hnodes,&this->hmatice,&this->hmatpar,this->parameters,this->inputs);
+
+}
+/*}}}*/
+/*FUNCTION Beam::DeepEcho{{{1*/
+void Beam::DeepEcho(void){
+
+	printf("Beam:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	hmatice.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Beam::Demarshall{{{1*/
+void  Beam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	hmatice.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Beam::Echo {{{1*/
+void Beam::Echo(void){
+
+	printf("Beam:\n");
+	printf("   id: %i\n",id);
+	hnodes.Echo();
+	hmatice.Echo();
+	hmatpar.Echo();
+	printf("   parameters\n");
+	parameters->Echo();
+	printf("   inputs\n");
+	inputs->Echo();
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Beam::Marshall{{{1*/
+void  Beam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Beam: */
+	enum_type=BeamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Beam data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	hmatice.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+	
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Beam::MarshallSize{{{1*/
+int   Beam::MarshallSize(){
+	
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+hmatice.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Beam::UpdateInputs {{{1*/
+void  Beam::UpdateInputs(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION Beam::ComputeBasalStress{{{1*/
+void  Beam::ComputeBasalStress(Vec eps,int analysis_type,int sub_analysis_type){
+
+	ISSMERROR("Not implemented yet");
+
+}
+/*}}}*/
+/*FUNCTION Beam::ComputePressure{{{1*/
+void  Beam::ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type){
+
+	int i;
+	const int numgrids=2;
+	int doflist[numgrids];
+	double pressure[numgrids];
+	double surface[numgrids];
+	double rho_ice,g;
+	double xyz_list[numgrids][3];
+	double gauss[numgrids][numgrids]={{1,0},{0,1}};
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+	
+	/*Get dof list on which we will plug the pressure values: */
+	GetDofList1(&doflist[0]);
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+        
+	/*Get dof list on which we will plug the pressure values: */
+	GetDofList1(&doflist[0]);
+
+	/*pressure is lithostatic: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+
+	/*recover value of surface at gauss points (0,1) and (1,0): */
+	inputs->GetParameterValues(&surface[0],&gauss[0][0],2,SurfaceEnum);
+	for(i=0;i<numgrids;i++){
+		pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+	}
+
+	/*plug local pressure values into global pressure vector: */
+	VecSetValues(p_g,numgrids,doflist,(const double*)pressure,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Beam::ComputeStrainRate{{{1*/
+void  Beam::ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type){
+
+	ISSMERROR("Not implemented yet");
+
+}
+/*}}}*/
+/*FUNCTION Beam::CostFunction{{{1*/
+double Beam::CostFunction(int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::CreateKMatrix{{{1*/
+
+void  Beam::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==DiagnosticAnalysisEnum) {
+	
+		if (sub_analysis_type==HutterAnalysisEnum) {
+
+			CreateKMatrixDiagnosticHutter( Kgg,analysis_type,sub_analysis_type);
+		}
+		else 
+			ISSMERROR("%s%i%s\n","sub_analysis_type: ",sub_analysis_type," not supported yet");
+	}
+	else{
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Beam::CreateKMatrixDiagnosticHutter{{{1*/
+
+void  Beam::CreateKMatrixDiagnosticHutter(Mat Kgg,int analysis_type,int sub_analysis_type){
+	
+	
+	const int numgrids=2;
+	const int NDOF2=2;
+	const int numdofs=NDOF2*numgrids;
+	int       doflist[numdofs];
+	double    Ke_gg[numdofs][numdofs]={{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};
+	int       numberofdofspernode;
+	bool onbed;
+	
+	
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	if (onbed){
+		Ke_gg[0][0]=1;
+		Ke_gg[1][1]=1;
+		Ke_gg[2][0]=-1;
+		Ke_gg[2][2]=1;
+		Ke_gg[3][1]=-1;
+		Ke_gg[3][3]=1;
+	}
+	else{
+		Ke_gg[2][0]=-1;
+		Ke_gg[2][2]=1;
+		Ke_gg[3][1]=-1;
+		Ke_gg[3][3]=1;
+	}
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdofs,doflist,numdofs,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Beam::CreatePVector{{{1*/
+void  Beam::CreatePVector(Vec pg,int analysis_type,int sub_analysis_type){
+	
+	/*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==DiagnosticAnalysisEnum) {
+		if (sub_analysis_type==HutterAnalysisEnum) {
+			CreatePVectorDiagnosticHutter( pg,analysis_type,sub_analysis_type);
+		}
+		else
+			ISSMERROR("%s%i%s"," analysis ",analysis_type," not supported yet");
+	}
+	else{
+		ISSMERROR("%s%i%s"," analysis ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Beam::CreatePVectorDiagnosticHutter{{{1*/
+
+void Beam::CreatePVectorDiagnosticHutter( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int i,j,k;
+	
+	const int numgrids=2;
+	const int NDOF2=2;
+	const int numdofs=NDOF2*numgrids;
+	int       doflist[numdofs];
+	double    pe_g[4]={0,0,0,0};
+	double    pe_g_gaussian[4]={0,0,0,0};
+	int       found=0;
+	int       dofs[1]={0};
+	double    xyz_list[numgrids][3];
+	double    z_list[numgrids];
+	double    constant_part;
+	int       numberofdofspernode;
+
+	/*gaussian points: */
+	int      num_gauss;
+	double*  segment_gauss_coord=NULL;
+	double   gauss_coord;
+	double*  gauss_weights=NULL;
+	double   gauss_weight;
+	double   gauss1[2]={1,0};
+	int      ig;
+	double   l1l2[2];
+	double   slope[2];
+	double   slope2;
+
+	double   z_g;
+	double   rho_ice,gravity,n,B;
+	double   Jdet;
+	double   ub,vb;
+	double   surface,thickness;
+	
+	bool onbed;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*recover doflist: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*recover parameters: */
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	n=matice->GetN();
+	B=matice->GetB();
+
+	//recover extra inputs
+	inputs->GetParameterValue(&slope[0],&gauss1[0],SurfaceSlopexEnum);
+	inputs->GetParameterValue(&slope[1],&gauss1[0],SurfaceSlopeyEnum);
+	inputs->GetParameterValue(&surface,&gauss1[0],SurfaceEnum);
+	inputs->GetParameterValue(&thickness,&gauss1[0],ThicknessEnum);
+
+	//Get all element grid data:
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	for(i=0;i<numgrids;i++)z_list[i]=xyz_list[i][2];
+	
+	//compute slope2 slopex and slopy
+	slope2=pow(slope[0],2)+pow(slope[1],2);
+
+	//%compute constant_part
+	constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
+
+	//Get gaussian points and weights. order 2 since we have a product of 2 nodal functions
+	num_gauss=3;
+	GaussSegment(&segment_gauss_coord, &gauss_weights, num_gauss);
+
+	//Start  looping on the number of gaussian points:
+	for(ig=0;ig<num_gauss;ig++){
+
+		//Pick up the gaussian point and its weight:
+		gauss_weight=gauss_weights[ig];
+		gauss_coord=segment_gauss_coord[ig];
+
+		//compute constant_part
+		GetParameterValue(&z_g, &z_list[0],gauss_coord);
+
+		//Get Jacobian determinant:
+		GetJacobianDeterminant(&Jdet, &z_list[0],gauss_coord);
+		
+		for(j=0;j<NDOF2;j++){
+			pe_g_gaussian[NDOF2+j]=constant_part*pow((surface-z_g)/B,n)*slope[j]*Jdet*gauss_weight;
+		}
+		
+		//add pe_gaussian vector to pe:
+		for(j=0;j<numdofs;j++){
+			pe_g[j]+=pe_g_gaussian[j];
+		}
+	} //for(ig=0;ig<num_gauss;ig++)
+
+	//Deal with lower surface
+	if (onbed){
+
+		//compute ub
+		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];
+
+		//Add to pe: 
+		pe_g[0]+=ub;
+		pe_g[1]+=vb;
+	}
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdofs,doflist,(const double*)pe_g,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&segment_gauss_coord);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
+/*FUNCTION Beam::Du{{{1*/
+void  Beam::Du(Vec,int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::Enum{{{1*/
+int Beam::Enum(void){
+
+	return BeamEnum;
+
+}
+/*}}}*/
+/*FUNCTION Beam::GetBedList{{{1*/
+void  Beam::GetBedList(double*){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::GetDofList{{{1*/
+void  Beam::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+	
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	for(i=0;i<2;i++){
+		nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+		for(j=0;j<numberofdofspernode;j++){
+			doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION Beam::GetDofList1{{{1*/
+void  Beam::GetDofList1(int* doflist){
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	int i;
+	for(i=0;i<2;i++){
+		doflist[i]=nodes[i]->GetDofList1();
+	}
+
+}
+/*}}}*/
+/*FUNCTION Beam::Id{{{1*/
+int    Beam::Id(void){ return id; }
+/*}}}*/
+/*FUNCTION Beam::GetJacobianDeterminant{{{1*/
+void Beam::GetJacobianDeterminant(double* pJdet,double* z_list, double gauss_coord){
+
+
+	double Jdet;
+
+	Jdet=1.0/2.0*(z_list[1]-z_list[0]);
+
+	if(Jdet<0){
+		ISSMERROR(" negative jacobian determinant!");
+	}
+	
+	*pJdet=Jdet;
+}
+/*}}}*/
+/*FUNCTION Beam::GetMatPar{{{1*/
+void* Beam::GetMatPar(){
+
+	/*dynamic objects pointed to by hooks: */
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	matpar=(Matpar*)hmatpar.delivers();
+
+	return matpar;
+}
+/*}}}*/
+/*FUNCTION Beam::GetNodalFunctions{{{1*/
+void Beam::GetNodalFunctions(double* l1l2, double gauss_coord){
+	
+	/*This routine returns the values of the nodal functions  at the gaussian point.*/
+
+	/*First nodal function: */
+	l1l2[0]=.5*gauss_coord+.5;
+
+	/*Second nodal function: */
+	l1l2[1]=-.5*gauss_coord+.5;
+}
+/*}}}*/
+/*FUNCTION Beam::GetNodes{{{1*/
+void  Beam::GetNodes(void** vpnodes){
+	int i;
+	Node** pnodes=NULL;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	
+	/*recover nodes: */
+	pnodes=(Node**)vpnodes;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	for(i=0;i<3;i++){
+		pnodes[i]=nodes[i];
+	}
+}
+/*}}}*/
+/*FUNCTION Beam::GetOnBed{{{1*/
+bool   Beam::GetOnBed(){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::GetParameterValue{{{1*/
+void Beam::GetParameterValue(double* pvalue, double* value_list,double gauss_coord){
+
+	double l1l2[2];
+	
+	GetNodalFunctions(&l1l2[0],gauss_coord);
+
+	*pvalue=l1l2[0]*value_list[0]+l1l2[1]*value_list[1];
+}
+/*}}}*/
+/*FUNCTION Beam::GetShelf{{{1*/
+bool   Beam::GetShelf(){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::GetThicknessList{{{1*/
+void  Beam::GetThicknessList(double* thickness_list){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::Gradj{{{1*/
+void  Beam::Gradj(Vec, int, int,char*){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::GradjB{{{1*/
+void  Beam::GradjB(Vec, int, int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::GradjDrag{{{1*/
+void  Beam::GradjDrag(Vec, int,int ){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::MassFlux{{{1*/
+double Beam::MassFlux( double* segment,double* ug){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::Misfit{{{1*/
+double Beam::Misfit(int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Beam::MyRank{{{1*/
+int    Beam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Beam::SurfaceArea{{{1*/
+double Beam::SurfaceArea(int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+//*FUNCTION Beam::SetClone {{{1*/
+void  Beam::SetClone(int* minranks){
+
+	ISSMERROR("not implemented yet");
+}
+/*}}}1*/
+
Index: /issm/trunk/src/c/objects/Elements/Beam.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Beam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Beam.h	(revision 3683)
@@ -0,0 +1,93 @@
+/*! \file Beam.h 
+ *  \brief: header file for beam object
+ */
+
+#ifndef _BEAM_H_
+#define _BEAM_H_
+
+/*Headers:*/
+/*{{{1*/
+
+#include "./Element.h"
+class Hook;
+class Parameters;
+class Inputs;
+class IoModel;
+
+#include "../../shared/Exceptions/exceptions.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class Beam: public Element{
+
+	public:
+
+		/*ids:*/
+		int id;
+
+		Hook hnodes;  //hook to 2 nodes
+		Hook hmatice; //hook to 1 matice
+		Hook hmatpar; //hook to 1 matpar
+		
+		Parameters* parameters; //pointer to solution parameters
+		Inputs* inputs;
+	
+
+		/*constructors, destructors: {{{1*/
+		Beam();
+		Beam(int beam_id,int* beam_node_ids, int beam_matice_id, int beam_matpar_id);
+		Beam(int beam_id,Hook* beam_hnodes, Hook* beam_hmatice, Hook* beam_hmatpar, Parameters* beam_parameters, Inputs* beam_inputs);
+		Beam(int beam_id,int i, IoModel* iomodel);
+		~Beam();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  Echo();
+		void  DeepEcho();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   Id(); 
+		int   MyRank();
+		void  Configure(DataSet* loads,DataSet* nodes,DataSet* materials,Parameters* parameters);
+		Object* copy();
+		void  SetClone(int* minranks);
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+		void  UpdateInputs(double* solution, int analysis_type, int sub_analysis_type);
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  GetDofList1(int* doflist);
+		void  CreateKMatrixDiagnosticHutter(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3);
+		void  CreatePVectorDiagnosticHutter(Vec pg,int analysis_type,int sub_analysis_type);
+		void* GetMatPar();
+
+		void  ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type);
+		void  ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type);
+		void  ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type);
+		void  GetNodes(void** vpnodes);
+		/*}}}*/
+		/*not implemented: {{{1*/
+		bool  GetShelf();
+		bool  GetOnBed();
+		void  GetBedList(double*);
+		void  GetThicknessList(double* thickness_list);
+		void  Du(Vec, int,int);
+		void  Gradj(Vec,  int, int,char*);
+		void  GradjDrag(Vec,  int,int );
+		void  GradjB(Vec,  int,int );
+		double Misfit(int,int);
+		double SurfaceArea(int,int);
+		double CostFunction(int,int);
+		void  GetNodalFunctions(double* l1l2, double gauss_coord);
+		void  GetParameterValue(double* pvalue, double* value_list,double gauss_coord);
+		void  GetJacobianDeterminant(double* pJdet,double* z_list, double gauss_coord);
+		double MassFlux(double* segment,double* ug);
+		void AddInput(double value, int enum_type){ISSMERROR("not supporte yet!");}
+		/*}}}*/
+
+};
+#endif  /* _BEAM_H */
Index: /issm/trunk/src/c/objects/Elements/Element.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Element.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Element.h	(revision 3683)
@@ -0,0 +1,53 @@
+/*!\file:  Element.h
+ * \brief abstract class for Element object
+ * This class is a place holder for the Tria and the Penta elements. 
+ * It is derived from Element, so DataSets can contain them.
+ */ 
+
+
+#ifndef _ELEMENT_H_
+#define _ELEMENT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "../Object.h"
+
+class DataSet;
+class Parameters;
+
+#include "../../toolkits/toolkits.h"
+/*}}}*/
+
+class Element: public Object{
+
+	public: 
+		
+		virtual        ~Element(){};
+		virtual void   Configure(DataSet* loads,DataSet* nodes,DataSet* materials,Parameters* parameters)=0;
+		
+		virtual void   CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type)=0;
+		virtual void   CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type)=0;
+		virtual void   UpdateInputs(double* solution, int analysis_type, int sub_analysis_type)=0;
+		virtual void   GetNodes(void** nodes)=0;
+		virtual void*  GetMatPar()=0;
+		virtual bool   GetShelf()=0; 
+		virtual bool   GetOnBed()=0;
+		virtual void   GetThicknessList(double* thickness_list)=0;
+		virtual void   GetBedList(double* bed_list)=0;
+		virtual void   Du(Vec du_g,int analysis_type,int sub_analysis_type)=0;
+		virtual void   Gradj(Vec grad_g,int analysis_type,int sub_analysis_type,char* control_type)=0;
+		virtual void   GradjDrag(Vec grad_g,int analysis_type,int sub_analysis_type)=0;
+		virtual void   GradjB(Vec grad_g,int analysis_type,int sub_analysis_type)=0;
+		virtual double Misfit(int analysis_type,int sub_analysis_type)=0;
+		virtual double CostFunction(int analysis_type,int sub_analysis_type)=0;
+		virtual double SurfaceArea(int analysis_type,int sub_analysis_type)=0;
+		virtual void   ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type)=0;
+		virtual void   ComputePressure(Vec p_g,       int analysis_type,int sub_analysis_type)=0;
+		virtual void   ComputeStrainRate(Vec eps,     int analysis_type,int sub_analysis_type)=0;
+		virtual double MassFlux(double* segment,double* ug)=0;
+		virtual void   AddInput(double value, int enum_type)=0;
+
+		/*Implementation: */
+
+};
+#endif
Index: /issm/trunk/src/c/objects/Elements/Penta.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Penta.cpp	(revision 3683)
@@ -0,0 +1,4417 @@
+/*!\file Penta.cpp
+ * \brief: implementation of the Penta object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+#include "../../DataSet/DataSet.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION Penta::Penta(){{{1*/
+Penta::Penta(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Penta::Penta(int penta_id,int* penta_node_ids, int penta_matice_id, int penta_matpar_id) {{{1*/
+Penta::Penta(int penta_id,int* penta_node_ids, int penta_matice_id, int penta_matpar_id):
+	hnodes(penta_node_ids,6),
+	hmatice(&penta_matice_id,1),
+	hmatpar(&penta_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=penta_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+}
+/*}}}*/
+/*FUNCTION Penta::Penta(int id, Hook* hnodes, Hook* hmatice, Hook* hmatpar, Parameters* parameters, Inputs* penta_inputs) {{{1*/
+Penta::Penta(int penta_id,Hook* penta_hnodes, Hook* penta_hmatice, Hook* penta_hmatpar, Parameters* penta_parameters, Inputs* penta_inputs):
+	hnodes(penta_hnodes),
+	hmatice(penta_hmatice),
+	hmatpar(penta_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=penta_id;
+	if(penta_inputs){
+		this->inputs=(Inputs*)penta_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=penta_parameters;
+}
+/*}}}*/
+/*FUNCTION Penta::Penta(int id, int index, IoModel* iomodel) {{{1*/
+Penta::Penta(int penta_id, int index, IoModel* iomodel){ //i is the element index
+
+	IssmInt i;
+	int penta_node_ids[6];
+	int penta_matice_id;
+	int penta_matpar_id;
+	double nodeinputs[6];
+	bool collapse;
+
+	/*id: */
+	this->id=penta_id;
+
+	/*hooks: */
+	for(i=0;i<6;i++){ //go recover node ids, needed to initialize the node hook.
+		penta_node_ids[i]=(int)*(iomodel->elements+6*index+i); //ids for vertices are in the elements array from Matlab
+	}
+	penta_matice_id=index+1; //refers to the corresponding ice material object
+	penta_matpar_id=iomodel->numberofelements+1; //refers to the constant material parameters object
+
+	this->hnodes.Init(&penta_node_ids[0],6);
+	this->hmatice.Init(&penta_matice_id,1);
+	this->hmatpar.Init(&penta_matpar_id,1);
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+
+	if (iomodel->thickness) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->thickness[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(ThicknessEnum,nodeinputs));
+	}
+	if (iomodel->surface) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->surface[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(SurfaceEnum,nodeinputs));
+	}
+	if (iomodel->bed) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->bed[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(BedEnum,nodeinputs));
+	}
+	if (iomodel->drag_coefficient) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->drag_coefficient[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(DragCoefficientEnum,nodeinputs));
+
+		if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index]));
+		if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index]));
+		this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type));
+
+	}
+	if (iomodel->melting_rate) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->melting_rate[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(MeltingRateEnum,nodeinputs));
+	}
+	if (iomodel->accumulation_rate) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->accumulation_rate[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(AccumulationRateEnum,nodeinputs));
+	}
+	if (iomodel->geothermalflux) {
+		for(i=0;i<6;i++)nodeinputs[i]=iomodel->geothermalflux[penta_node_ids[i]-1];
+		this->inputs->AddInput(new PentaVertexInput(GeothermalFluxEnum,nodeinputs));
+	}	
+
+	if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index]));
+	if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index]));
+	if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index]));
+	if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index]));
+
+	//elements of type 3 are macayeal type penta. we collapse the formulation on their base.
+	if(iomodel->elements_type){
+		if (*(iomodel->elements_type+2*i+0)==MacAyealFormulationEnum){ 
+			collapse=1;
+		}
+		else{
+			collapse=0;
+		}
+	}
+	this->inputs->AddInput(new BoolInput(CollapseEnum,(IssmBool)collapse));
+
+}
+/*}}}*/
+/*FUNCTION Penta::~Penta(){{{1*/
+Penta::~Penta(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object management: */
+/*FUNCTION Penta::Configure {{{1*/
+void  Penta::Configure(DataSet* loadsin, DataSet* nodesin, DataSet* materialsin, Parameters* parametersin){
+
+	int i;
+
+	/*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: */
+	hnodes.configure(nodesin);
+	hmatice.configure(materialsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION copy {{{1*/
+Object* Penta::copy() {
+	return new Penta(this->id,&this->hnodes,&this->hmatice,&this->hmatpar,this->parameters,this->inputs);
+}
+/*}}}*/
+/*FUNCTION Demarshall {{{1*/
+void  Penta::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	hmatice.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION DeepEcho{{{1*/
+
+void Penta::DeepEcho(void){
+
+	printf("Penta:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	hmatice.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Echo{{{1*/
+
+void Penta::Echo(void){
+
+	printf("Penta:\n");
+	printf("   id: %i\n",id);
+	hnodes.Echo();
+	hmatice.Echo();
+	hmatpar.Echo();
+	printf("   parameters\n");
+	parameters->Echo();
+	printf("   inputs\n");
+	inputs->Echo();
+
+}
+/*}}}*/
+/*FUNCTION Enum {{{1*/
+int Penta::Enum(void){
+
+	return PentaEnum;
+
+}
+/*}}}*/
+/*FUNCTION Marshall {{{1*/
+void  Penta::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Penta: */
+	enum_type=PentaEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Penta data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	hmatice.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION MarshallSize {{{1*/
+int   Penta::MarshallSize(){
+	
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+hmatice.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION SpawnTria {{{1*/
+void*  Penta::SpawnTria(int g0, int g1, int g2){
+
+	/*out of grids g0,g1 and g2 from Penta, build a tria element: */
+	Tria* tria=NULL;
+	int indices[3];
+	int zero=0;
+	Hook* tria_hnodes=NULL;
+	Hook* tria_hmatice=NULL;
+	Hook* tria_hmatpar=NULL;
+	Parameters* tria_parameters=NULL;
+	Inputs* tria_inputs=NULL;
+
+	indices[0]=g0;
+	indices[1]=g1;
+	indices[2]=g2;
+
+	tria_hnodes =this->hnodes.Spawn(indices,3);
+	tria_hmatice=this->hmatice.Spawn(&zero,1);
+	tria_hmatpar=this->hmatpar.Spawn(&zero,1);
+	tria_parameters=this->parameters;
+	tria_inputs=(Inputs*)this->inputs->Spawn(indices,3);
+
+	tria=new Tria(this->id,tria_hnodes,tria_hmatice,tria_hmatpar,tria_parameters,tria_inputs);
+
+	delete tria_hnodes;
+	delete tria_hmatice;
+	delete tria_hmatpar;
+	delete tria_inputs;
+
+	return tria;
+}
+/*}}}*/
+
+/*updates: */
+/*FUNCTION UpdateFromDakota {{{1*/
+void  Penta::UpdateFromDakota(void* vinputs){
+
+	ISSMERROR("not supported yet!");
+
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputs {{{1*/
+void  Penta::UpdateInputs(double* solution, int analysis_type, int sub_analysis_type){
+
+	/*Just branch to the correct UpdateInputs generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+		
+		UpdateInputsDiagnosticHoriz( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+	
+		if (sub_analysis_type==HorizAnalysisEnum){
+
+			UpdateInputsDiagnosticHoriz( solution,analysis_type,sub_analysis_type);
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+
+		UpdateInputsSlopeCompute( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		UpdateInputsPrognostic( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Prognostic2AnalysisEnum){
+
+		UpdateInputsPrognostic2(solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		UpdateInputsBalancedthickness( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+
+		UpdateInputsBalancedthickness2( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		UpdateInputsBalancedvelocities( solution,analysis_type,sub_analysis_type);
+	}
+	else{
+
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}
+}
+/*Object functions*/
+/*FUNCTION Penta::UpdateInputsDiagnosticHoriz {{{1*/
+void  Penta::UpdateInputsDiagnosticHoriz(double* solution, int analysis_type, int sub_analysis_type){
+	
+	
+	int i;
+
+	const int    numvertices=6;
+	const int    numdofpervertex=2;
+	const int    numdof=numdofpervertex*numvertices;
+	
+	int          doflist[numdof];
+	double       values[numdof];
+	double       vx[numvertices];
+	double       vy[numvertices];
+
+	int          dummy;
+	
+	/*Get dof list: */
+	GetDofList(&doflist[0],&dummy);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+	}
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<numvertices;i++){
+		vx[i]=values[i*numdofpervertex+0];
+		vy[i]=values[i*numdofpervertex+1];
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new PentaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new PentaVertexInput(VyEnum,vy));
+}
+
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsSlopeCompute {{{1*/
+void  Penta::UpdateInputsSlopeCompute(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsPrognostic {{{1*/
+void  Penta::UpdateInputsPrognostic(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsPrognostic2 {{{1*/
+void  Penta::UpdateInputsPrognostic2(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsBalancedthickness {{{1*/
+void  Penta::UpdateInputsBalancedthickness(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsBalancedthickness2 {{{1*/
+void  Penta::UpdateInputsBalancedthickness2(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Penta::UpdateInputsBalancedvelocities {{{1*/
+void  Penta::UpdateInputsBalancedvelocities(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION ComputeBasalStress {{{1*/
+void  Penta::ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+	const int numgrids=6;
+	int    doflist[numgrids];
+	double xyz_list[numgrids][3];
+	double xyz_list_tria[3][3];
+
+	/*Parameters*/
+	double rho_ice,gravity;
+	double surface_normal[3];
+	double bed_normal[3];
+	double bed;
+	double basalforce[3];
+	double epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double devstresstensor[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double stresstensor[6]={0.0};
+	double viscosity;
+
+	int  dofv[3]={0,1,2};
+	int  dofp[1]={3};
+	double Jdet2d;
+	Tria* tria=NULL;
+
+	/*Gauss*/
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[4];
+
+	/*Output*/
+	double pressure;
+	double sigma_xx,sigma_yy,sigma_zz;
+	double sigma_xy,sigma_xz,sigma_yz;
+	double surface=0;
+	double value=0;
+	
+	/*flags: */
+	bool onbed;
+
+	/*parameters: */
+	double stokesreconditioning;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*Check analysis_types*/
+	if (analysis_type!=DiagnosticAnalysisEnum || sub_analysis_type!=StokesAnalysisEnum) ISSMERROR("Not supported yet!");
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);
+	
+	if(!onbed){
+		//put zero
+		VecSetValue(sigma_b,id-1,0.0,INSERT_VALUES);
+		return;
+	}
+
+	/*recovre material parameters: */
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	for(i=0;i<3;i++){
+		for(j=0;j<3;j++){
+			xyz_list_tria[i][j]=xyz_list[i][j];
+		}
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria(&num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights,2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+			/*Pick up the gaussian point: */
+			gauss_weight=*(gauss_weights+ig);
+			gauss_coord[0]=*(first_gauss_area_coord+ig); 
+			gauss_coord[1]=*(second_gauss_area_coord+ig);
+			gauss_coord[2]=*(third_gauss_area_coord+ig);
+			gauss_coord[3]=-1.0; //take the base
+
+			/*Compute strain rate viscosity and pressure: */
+			inputs->GetStrainRateStokes(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum,VzEnum);
+			matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+			inputs->GetParameterValue(&pressure, &gauss_coord[0],PressureEnum);
+
+			/*Compute Stress*/
+			sigma_xx=viscosity*epsilon[0]-pressure*stokesreconditioning; // sigma = nu eps - pressure
+			sigma_yy=viscosity*epsilon[1]-pressure*stokesreconditioning;
+			sigma_zz=viscosity*epsilon[2]-pressure*stokesreconditioning;
+			sigma_xy=viscosity*epsilon[3];
+			sigma_xz=viscosity*epsilon[4];
+			sigma_yz=viscosity*epsilon[5];
+
+			/*Get normal vector to the bed */
+			SurfaceNormal(&surface_normal[0],xyz_list_tria);
+			bed_normal[0] = - surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
+			bed_normal[1] = - surface_normal[1];
+			bed_normal[2] = - surface_normal[2];
+
+			/*basalforce*/
+			basalforce[0] += sigma_xx*bed_normal[0] + sigma_xy*bed_normal[1] + sigma_xz*bed_normal[2];
+			basalforce[1] += sigma_xy*bed_normal[0] + sigma_yy*bed_normal[1] + sigma_yz*bed_normal[2];
+			basalforce[2] += sigma_xz*bed_normal[0] + sigma_yz*bed_normal[1] + sigma_zz*bed_normal[2];
+
+			/*Get the Jacobian determinant */
+			tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0],gauss_coord);
+			value+=sigma_zz*Jdet2d*gauss_weight;
+			surface+=Jdet2d*gauss_weight;
+	}
+	value=value/surface;
+
+	/*Add value to output*/
+	VecSetValue(sigma_b,id-1,(const double)value,INSERT_VALUES);
+}
+/*}}}*/
+/*FUNCTION ComputePressure {{{1*/
+void  Penta::ComputePressure(Vec pg,int analysis_type,int sub_analysis_type){
+
+	int i;
+	const int numgrids=6;
+	int    doflist[numgrids];
+	double pressure[numgrids];
+	double rho_ice,g;
+	double surface[numgrids];
+	double xyz_list[numgrids][3];
+	double gauss[numgrids][numgrids]={{1,0,0,0},{0,1,0,0},{0,0,1,0},{1,0,0,1},{0,1,0,1},{0,0,1,1}};
+
+	/*inputs: */
+	bool onwater;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Get node data: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+
+	/*pressure is lithostatic: */
+	//md.pressure=md.rho_ice*md.g*(md.surface-md.z); a la matlab
+
+	/*Get dof list on which we will plug the pressure values: */
+	GetDofList1(&doflist[0]);
+
+	/*recover value of surface at grids: */
+	inputs->GetParameterValues(&surface[0],&gauss[0][0],6,SurfaceEnum);
+
+	/*pressure is lithostatic: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	for(i=0;i<numgrids;i++){
+		pressure[i]=rho_ice*g*(surface[i]-xyz_list[i][2]);
+	}
+
+	/*plug local pressure values into global pressure vector: */
+	VecSetValues(pg,numgrids,doflist,(const double*)pressure,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION ComputeStrainRate {{{1*/
+void  Penta::ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type){
+
+	ISSMERROR("Not implemented yet");
+
+}
+/*}}}*/
+/*FUNCTION CostFunction {{{1*/
+double Penta::CostFunction(int analysis_type,int sub_analysis_type){
+
+	double J;
+	Tria* tria=NULL;
+
+	/*flags: */
+	bool onbed;
+	bool onwater;
+	bool collapse;
+	bool onsurface;
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/*Bail out if this element if:
+	 * -> Non collapsed and not on the surface
+	 * -> collapsed (2d model) and not on bed) */
+	if ((!collapse && !onsurface) || (collapse && !onbed)){
+		return 0;
+	}
+	else if (collapse){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute CostFunction*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		J=tria->CostFunction(analysis_type,sub_analysis_type);
+		delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).
+		J=tria->CostFunction(analysis_type,sub_analysis_type);
+		delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION CreateKMatrix {{{1*/
+
+void  Penta::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+
+		CreateKMatrixDiagnosticHoriz( Kgg,analysis_type,sub_analysis_type);
+
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+
+		if (sub_analysis_type==HorizAnalysisEnum){
+
+			CreateKMatrixDiagnosticHoriz( Kgg,analysis_type,sub_analysis_type);
+		}
+		else if (sub_analysis_type==VertAnalysisEnum){
+
+			CreateKMatrixDiagnosticVert( Kgg,analysis_type,sub_analysis_type);
+		}
+		else if (sub_analysis_type==StokesAnalysisEnum){
+
+			CreateKMatrixDiagnosticStokes( Kgg,analysis_type,sub_analysis_type);
+
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+
+		CreateKMatrixSlopeCompute( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		CreateKMatrixPrognostic( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		CreateKMatrixBalancedthickness( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		CreateKMatrixBalancedvelocities( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==ThermalAnalysisEnum){
+
+		CreateKMatrixThermal( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==MeltingAnalysisEnum){
+
+		CreateKMatrixMelting( Kgg,analysis_type,sub_analysis_type);
+	}
+	else{
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixBalancedthickness {{{1*/
+
+void  Penta::CreateKMatrixBalancedthickness(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*flags: */
+	bool onwater;
+	bool onbed;
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreateKMatrix(Kgg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixBalancedvelocities {{{1*/
+
+void  Penta::CreateKMatrixBalancedvelocities(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*flags: */
+	bool onbed;
+	bool onwater;
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreateKMatrix(Kgg,analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticHoriz {{{1*/
+void Penta::CreateKMatrixDiagnosticHoriz( Mat Kgg,  int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=6;
+	const int    numdof=2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+
+	/* 3d gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* fourth_gauss_vert_coord  =  NULL;
+	double* area_gauss_weights           =  NULL;
+	double* vert_gauss_weights           =  NULL;
+	int     ig1,ig2;
+	double  gauss_weight1,gauss_weight2;
+	double  gauss_coord[4];
+	int     order_area_gauss;
+	int     num_vert_gauss;
+	int     num_area_gauss;
+	double  gauss_weight;
+
+	/* 2d gaussian point: */
+	int     num_gauss2d;
+	double* first_gauss_area_coord2d  =  NULL;
+	double* second_gauss_area_coord2d =  NULL;
+	double* third_gauss_area_coord2d  =  NULL;
+	double* gauss_weights2d=NULL;
+	double  gauss_l1l2l3[3];
+
+	/* material data: */
+	double viscosity; //viscosity
+	double oldviscosity; //viscosity
+	double newviscosity; //viscosity
+
+	/* strain rate: */
+	double epsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+	double oldepsilon[5]; /* epsilon=[exx,eyy,exy,exz,eyz];*/
+
+	/* matrices: */
+	double B[5][numdof];
+	double Bprime[5][numdof];
+	double L[2][numdof];
+	double D[5][5]={0.0};            // material matrix, simple scalar matrix.
+	double D_scalar;
+	double DL[2][2]={0.0}; //for basal drag
+	double DL_scalar;
+
+	/* local element matrices: */
+	double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix 
+
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
+	double Ke_gg_drag_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
+	double Jdet;
+
+	/*slope: */
+	double  slope[2]={0.0};
+	double  slope_magnitude;
+
+	/*friction: */
+	double  alpha2_list[3];
+	double  alpha2;
+
+	double MAXSLOPE=.06; // 6 %
+	double MOUNTAINKEXPONENT=10;
+
+	/*parameters: */
+	double viscosity_overshoot;
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matice=(Matice*)hmatice.delivers();
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);
+
+	/*If on water, skip stiffness: */
+	if(onwater)return;
+
+	/*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the 
+	  bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 
+	  the stiffness matrix. */
+
+
+	if ((collapse==1) && (onbed==0)){
+		/*This element should be collapsed, but this element is not on the bedrock, therefore all its 
+		 * dofs have already been frozen! Do nothing: */
+		return;
+	}
+	else if ((collapse==1) && (onbed==1)){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 *and use its CreateKMatrix functionality to fill the global stiffness matrix: */
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreateKMatrix(Kgg, analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else{
+
+		/*Implement standard penta element: */
+
+		/* Get node coordinates and dof list: */
+		GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+		GetDofList(&doflist[0],&numberofdofspernode);
+
+
+		/*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+		  get tria gaussian points as well as segment gaussian points. For tria gaussian 
+		  points, order of integration is 2, because we need to integrate the product tB*D*B' 
+		  which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+		  points, same deal, which yields 3 gaussian points.*/
+
+		order_area_gauss=5;
+		num_vert_gauss=5;
+
+		GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);
+
+		/* Start  looping on the number of gaussian points: */
+		for (ig1=0; ig1<num_area_gauss; ig1++){
+			for (ig2=0; ig2<num_vert_gauss; ig2++){
+
+				/*Pick up the gaussian point: */
+				gauss_weight1=*(area_gauss_weights+ig1);
+				gauss_weight2=*(vert_gauss_weights+ig2);
+				gauss_weight=gauss_weight1*gauss_weight2;
+
+
+				gauss_coord[0]=*(first_gauss_area_coord+ig1); 
+				gauss_coord[1]=*(second_gauss_area_coord+ig1);
+				gauss_coord[2]=*(third_gauss_area_coord+ig1);
+				gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);
+
+
+				/*Get strain rate from velocity: */
+				inputs->GetStrainRate(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum);
+				inputs->GetStrainRate(&oldepsilon[0],&xyz_list[0][0],gauss_coord,VxOldEnum,VyOldEnum);
+
+				/*Get viscosity: */
+				matice->GetViscosity3d(&viscosity, &epsilon[0]);
+				matice->GetViscosity3d(&oldviscosity, &oldepsilon[0]);
+
+				/*Get B and Bprime matrices: */
+				GetB(&B[0][0], &xyz_list[0][0], gauss_coord);
+				GetBPrime(&Bprime[0][0], &xyz_list[0][0], gauss_coord);
+
+				/* Get Jacobian determinant: */
+				GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+				/*Build the D matrix: we plug the gaussian weight, the viscosity, and the jacobian determinant 
+				  onto this scalar matrix, so that we win some computational time: */
+
+				newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+				D_scalar=newviscosity*gauss_weight*Jdet;
+				for (i=0;i<5;i++){
+					D[i][i]=D_scalar;
+				}
+
+				/*  Do the triple product tB*D*Bprime: */
+				TripleMultiply( &B[0][0],5,numdof,1,
+							&D[0][0],5,5,0,
+							&Bprime[0][0],5,numdof,0,
+							&Ke_gg_gaussian[0][0],0);
+
+				/* Add the Ke_gg_gaussian, and optionally Ke_gg_gaussian onto Ke_gg: */
+				for( i=0; i<numdof; i++){
+					for(j=0;j<numdof;j++){
+						Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+					}
+				}
+			} //for (ig2=0; ig2<num_vert_gauss; ig2++)
+		} //for (ig1=0; ig1<num_area_gauss; ig1++)
+
+
+		/*Add Ke_gg to global matrix Kgg: */
+		MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+		//Deal with 2d friction at the bedrock interface
+		if((onbed && !shelf)){
+
+			/*Build a tria element using the 3 grids of the base of the penta. Then use 
+			 * the tria functionality to build a friction stiffness matrix on these 3
+			 * grids: */
+
+			tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+			tria->CreateKMatrixDiagnosticHorizFriction(Kgg,analysis_type,sub_analysis_type);
+			delete tria;
+		}
+
+	} 
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&fourth_gauss_vert_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+	xfree((void**)&first_gauss_area_coord2d);
+	xfree((void**)&second_gauss_area_coord2d);
+	xfree((void**)&third_gauss_area_coord2d);
+	xfree((void**)&gauss_weights2d);
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticStokes {{{1*/
+void Penta::CreateKMatrixDiagnosticStokes( Mat Kgg,  int analysis_type,int sub_analysis_type){
+
+	int i,j;
+
+	const int numgrids=6;
+	const int DOFPERGRID=4;
+	const int numdof=numgrids*DOFPERGRID;
+	int doflist[numdof];
+	int numberofdofspernode;
+
+	const int numgrids2d=3;
+	const int numdof2d=numgrids2d*DOFPERGRID;
+
+	int   dofs[3]={0,1,2};
+
+	double K_terms[numdof][numdof]={0.0};
+
+	/*Material properties: */
+	double         gravity,rho_ice,rho_water;
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*Grid data: */
+	double        xyz_list[numgrids][3];
+
+	/*parameters: */
+	double		   xyz_list_tria[numgrids2d][3];
+	double		   surface_normal[3];
+	double		   bed_normal[3];
+	double         thickness;
+
+	/*matrices: */
+	double     Ke_temp[27][27]={0.0}; //for the six nodes and the bubble 
+	double     Ke_reduced[numdof][numdof]; //for the six nodes only
+	double     Ke_gaussian[27][27];
+	double     Ke_drag_gaussian[numdof2d][numdof2d];
+	double     B[8][27];
+	double     B_prime[8][27];
+	double     LStokes[14][numdof2d];
+	double     LprimeStokes[14][numdof2d];
+	double     Jdet;
+	double     Jdet2d;
+	double     D[8][8]={0.0};
+	double     D_scalar;
+	double     tBD[27][8];
+	double     DLStokes[14][14]={0.0};
+	double     tLDStokes[numdof2d][14];
+
+	/* gaussian points: */
+	int     num_area_gauss;
+	int     igarea,igvert;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* vert_gauss_coord = NULL;
+	double* area_gauss_weights  =  NULL;
+	double* vert_gauss_weights  =  NULL;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0,0},{0,1,0,0},{0,0,1,0},{1,0,0,1},{0,1,0,1},{0,0,1,1}};
+
+	/* specific gaussian point: */
+	double  gauss_weight,area_gauss_weight,vert_gauss_weight;
+	double  gauss_coord[4];
+	double  gauss_coord_tria[3];
+	int area_order=5;
+	int	num_vert_gauss=5;
+
+	double  epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double  viscosity;
+	double  alpha2_list[numgrids2d];
+	double  alpha2_gauss;
+
+	double  vx_list[numgrids];
+	double  vy_list[numgrids];
+	double  vz_list[numgrids];
+	double  thickness_list[numgrids];
+	double  bed_list[numgrids];
+	double  dragcoefficient_list[numgrids];
+	double  drag_p,drag_q;
+
+	/*parameters: */
+	double stokesreconditioning;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*If on water, skip stiffness: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+
+	/*recovre material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+		get tria gaussian points as well as segment gaussian points. For tria gaussian 
+		points, order of integration is 2, because we need to integrate the product tB*D*B' 
+		which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+		points, same deal, which yields 3 gaussian points.*/
+
+	area_order=5;
+	num_vert_gauss=5;
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (igarea=0; igarea<num_area_gauss; igarea++){
+		for (igvert=0; igvert<num_vert_gauss; igvert++){
+			/*Pick up the gaussian point: */
+			area_gauss_weight=*(area_gauss_weights+igarea);
+			vert_gauss_weight=*(vert_gauss_weights+igvert);
+			gauss_weight=area_gauss_weight*vert_gauss_weight;
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=*(vert_gauss_coord+igvert);
+
+			/*Compute strain rate: */
+			inputs->GetStrainRateStokes(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum,VzEnum);
+
+			/*Get viscosity: */
+			matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+			/*Get B and Bprime matrices: */
+			GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord); 
+			GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord); 
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],&gauss_coord[0]);
+
+			/* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant 
+			 * onto this scalar matrix, so that we win some computational time: */
+			D_scalar=gauss_weight*Jdet;
+			for (i=0;i<6;i++){
+				D[i][i]=D_scalar*viscosity;
+			}
+			for (i=6;i<8;i++){
+				D[i][i]=-D_scalar*stokesreconditioning;
+			}
+
+			/*  Do the triple product tB*D*Bprime: */
+			MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0);
+			MatrixMultiply(&tBD[0][0],27,8,0,&B_prime[0][0],8,27,0,&Ke_gaussian[0][0],0);
+
+			/*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */
+			for(i=0;i<27;i++){
+				for(j=0;j<27;j++){
+					Ke_temp[i][j]+=Ke_gaussian[i][j];
+				}
+			}
+		}
+	}
+
+	if((onbed==1) && (shelf==0)){
+
+		/*Build alpha2_list used by drag stiffness matrix*/
+		Friction* friction=NewFriction();
+
+		/*Initialize all fields: */
+		friction->element_type=(char*)xmalloc((strlen("2d")+1)*sizeof(char));
+		strcpy(friction->element_type,"2d");
+
+		inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],6,VxEnum);
+		inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],6,VyEnum);
+		inputs->GetParameterValues(&vz_list[0],&gaussgrids[0][0],6,VzEnum);
+		inputs->GetParameterValues(&dragcoefficient_list[0],&gaussgrids[0][0],6,DragCoefficientEnum);
+		inputs->GetParameterValues(&bed_list[0],&gaussgrids[0][0],6,BedEnum);
+		inputs->GetParameterValues(&thickness_list[0],&gaussgrids[0][0],6,ThicknessEnum);
+		inputs->GetParameterValue(&drag_p,DragPEnum);
+		inputs->GetParameterValue(&drag_q,DragQEnum);
+
+		friction->gravity=matpar->GetG();
+		friction->rho_ice=matpar->GetRhoIce();
+		friction->rho_water=matpar->GetRhoWater();
+		friction->K=&dragcoefficient_list[0];
+		friction->bed=&bed_list[0];
+		friction->thickness=&thickness_list[0];
+		friction->vx=&vx_list[0];
+		friction->vy=&vy_list[0];
+		friction->vz=&vz_list[0];
+		friction->p=drag_p;
+		friction->q=drag_q;
+
+		/*Compute alpha2_list: */
+		FrictionGetAlpha2(&alpha2_list[0],friction);
+
+		/*Erase friction object: */
+		DeleteFriction(&friction);
+
+		for(i=0;i<numgrids2d;i++){
+			for(j=0;j<3;j++){
+				xyz_list_tria[i][j]=xyz_list[i][j];
+			}
+		}
+
+		xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights);
+		GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2);
+
+		/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+		for (igarea=0; igarea<num_area_gauss; igarea++){
+			gauss_weight=*(area_gauss_weights+igarea);
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=-1;
+
+			gauss_coord_tria[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord_tria[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord_tria[2]=*(third_gauss_area_coord+igarea);
+
+			/*Get the Jacobian determinant */
+			tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria);
+
+			/*Get L matrix if viscous basal drag present: */
+			GetLStokes(&LStokes[0][0],  gauss_coord_tria);
+			GetLprimeStokes(&LprimeStokes[0][0], &xyz_list[0][0], gauss_coord_tria, gauss_coord);
+
+			/*Compute strain rate: */
+			inputs->GetStrainRateStokes(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum,VzEnum);
+
+			/*Get viscosity at last iteration: */
+			matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+			/*Get normal vecyor to the bed */
+			SurfaceNormal(&surface_normal[0],xyz_list_tria);
+
+			bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
+			bed_normal[1]=-surface_normal[1];
+			bed_normal[2]=-surface_normal[2];
+
+			/*Calculate DL on gauss point */
+			tria->GetParameterValue(&alpha2_gauss,&alpha2_list[0],gauss_coord_tria);
+
+			DLStokes[0][0]=alpha2_gauss*gauss_weight*Jdet2d;
+			DLStokes[1][1]=alpha2_gauss*gauss_weight*Jdet2d;
+			DLStokes[2][2]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2];
+			DLStokes[3][3]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2];
+			DLStokes[4][4]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[0]*bed_normal[2];
+			DLStokes[5][5]=-alpha2_gauss*gauss_weight*Jdet2d*bed_normal[1]*bed_normal[2];
+			DLStokes[6][6]=-viscosity*gauss_weight*Jdet2d*bed_normal[0];
+			DLStokes[7][7]=-viscosity*gauss_weight*Jdet2d*bed_normal[1];
+			DLStokes[8][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[2];
+			DLStokes[9][8]=-viscosity*gauss_weight*Jdet2d*bed_normal[0]/2.0;
+			DLStokes[10][10]=-viscosity*gauss_weight*Jdet2d*bed_normal[1]/2.0;
+			DLStokes[11][11]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[0];
+			DLStokes[12][12]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[1];
+			DLStokes[13][13]=stokesreconditioning*gauss_weight*Jdet2d*bed_normal[2];
+
+			/*  Do the triple product tL*D*L: */
+			MatrixMultiply(&LStokes[0][0],14,numdof2d,1,&DLStokes[0][0],14,14,0,&tLDStokes[0][0],0);
+			MatrixMultiply(&tLDStokes[0][0],numdof2d,14,0,&LprimeStokes[0][0],14,numdof2d,0,&Ke_drag_gaussian[0][0],0);
+
+			for(i=0;i<numdof2d;i++){
+				for(j=0;j<numdof2d;j++){
+					Ke_temp[i][j]+=Ke_drag_gaussian[i][j];
+				}
+			}
+		}
+	} //if ( (onbed==1) && (shelf==0))
+
+	/*Reduce the matrix */
+	ReduceMatrixStokes(&Ke_reduced[0][0], &Ke_temp[0][0]);
+
+	for(i=0;i<numdof;i++){
+		for(j=0;j<numdof;j++){
+			K_terms[i][j]+=Ke_reduced[i][j];
+		}
+	}
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
+
+
+	/*Free ressources:*/
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_coord);
+	xfree((void**)&vert_gauss_weights);
+
+	return;
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticVert {{{1*/
+void Penta::CreateKMatrixDiagnosticVert( Mat Kgg,  int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=6;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* 3d gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* fourth_gauss_vert_coord  =  NULL;
+	double* area_gauss_weights           =  NULL;
+	double* vert_gauss_weights           =  NULL;
+	int     ig1,ig2;
+	double  gauss_weight1,gauss_weight2;
+	double  gauss_coord[4];
+	int     order_area_gauss;
+	int     num_vert_gauss;
+	int     num_area_gauss;
+	double  gauss_weight;
+
+	/* matrices: */
+	double  Ke_gg[numdof][numdof]={0.0};
+	double  Ke_gg_gaussian[numdof][numdof];
+	double  Jdet;
+	double  B[NDOF1][numgrids];
+	double  Bprime[NDOF1][numgrids];
+	double  DL_scalar;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*inputs: */
+	bool onwater; 
+	bool onsurface;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);
+
+	/*If on water, skip stiffness: */
+	if(onwater)return;
+
+	/*If this element  is on the surface, we have a dynamic boundary condition that applies, as a stiffness 
+	 * matrix: */
+	if(onsurface){
+		tria=(Tria*)SpawnTria(3,4,5); //nodes 3,4 and 5 are on the surface
+		tria->CreateKMatrixDiagnosticSurfaceVert(Kgg, analysis_type,sub_analysis_type);
+		delete tria;
+	}
+
+	/*Now, onto the formulation for the vertical velocity: */
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+
+	/*Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+	  get tria gaussian points as well as segment gaussian points. For tria gaussian 
+	  points, order of integration is 2, because we need to integrate the product tB*D*B' 
+	  which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+	  points, same deal, which yields 3 gaussian points.*/
+
+	order_area_gauss=2;
+	num_vert_gauss=2;
+
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig1=0; ig1<num_area_gauss; ig1++){
+		for (ig2=0; ig2<num_vert_gauss; ig2++){
+
+			/*Pick up the gaussian point: */
+			gauss_weight1=*(area_gauss_weights+ig1);
+			gauss_weight2=*(vert_gauss_weights+ig2);
+			gauss_weight=gauss_weight1*gauss_weight2;
+
+			gauss_coord[0]=*(first_gauss_area_coord+ig1); 
+			gauss_coord[1]=*(second_gauss_area_coord+ig1);
+			gauss_coord[2]=*(third_gauss_area_coord+ig1);
+			gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);
+
+			/*Get B and Bprime matrices: */
+			GetB_vert(&B[0][0], &xyz_list[0][0], gauss_coord);
+			GetBPrime_vert(&Bprime[0][0], &xyz_list[0][0], gauss_coord);
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+			DL_scalar=gauss_weight*Jdet;
+
+			/*  Do the triple product tB*D*Bprime: */
+			TripleMultiply( &B[0][0],1,numgrids,1,
+						&DL_scalar,1,1,0,
+						&Bprime[0][0],1,numgrids,0,
+						&Ke_gg_gaussian[0][0],0);
+
+			/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+			for( i=0; i<numdof; i++){
+				for(j=0;j<numdof;j++){
+					Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+				}
+			}	
+		} //for (ig2=0; ig2<num_vert_gauss; ig2++)
+	} //for (ig1=0; ig1<num_area_gauss; ig1++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&fourth_gauss_vert_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixMelting {{{1*/
+void  Penta::CreateKMatrixMelting(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	if (!onbed){
+		return;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreateKMatrixMelting(Kgg, analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixPrognostic {{{1*/
+
+void  Penta::CreateKMatrixPrognostic(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreateKMatrix(Kgg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixSlopeCompute {{{1*/
+
+void  Penta::CreateKMatrixSlopeCompute(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreateKMatrix(Kgg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+
+}
+/*}}}*/
+/*FUNCTION CreateKMatrixThermal {{{1*/
+void  Penta::CreateKMatrixThermal(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int i,j;
+	int found=0;
+
+	/* node data: */
+	const int    numgrids=6;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double xyz_list[numgrids][3];
+	int    doflist[numdof];
+	int    numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_area_gauss,igarea,igvert;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* vert_gauss_coord = NULL;
+	double* area_gauss_weights  =  NULL;
+	double* vert_gauss_weights  =  NULL;
+	double  gauss_weight,area_gauss_weight,vert_gauss_weight;
+	double  gauss_coord[4];
+	double  gauss_l1l2l3[3];
+
+	int area_order=5;
+	int num_vert_gauss=5;
+
+	int     dofs[3]={0,1,2};
+	double  K[2][2]={0.0};
+
+	double  u,v,w;
+
+	/*matrices: */
+	double     K_terms[numdof][numdof]={0.0};
+	double     Ke_gaussian_conduct[numdof][numdof];
+	double     Ke_gaussian_advec[numdof][numdof];
+	double     Ke_gaussian_artdiff[numdof][numdof];
+	double     Ke_gaussian_transient[numdof][numdof];
+	double     B[3][numdof];
+	double     Bprime[3][numdof];
+	double     B_conduct[3][numdof];
+	double     B_advec[3][numdof];
+	double     B_artdiff[2][numdof];
+	double     Bprime_advec[3][numdof];
+	double     L[numdof];
+	double     D_scalar;
+	double     D[3][3];
+	double     l1l2l3[3];
+	double     tl1l2l3D[3];
+	double     tBD[3][numdof];
+	double     tBD_conduct[3][numdof];
+	double     tBD_advec[3][numdof];
+	double     tBD_artdiff[3][numdof];
+	double     tLD[numdof];
+
+	double     Jdet;
+
+	/*Material properties: */
+	double     gravity,rho_ice,rho_water;
+	double     heatcapacity,thermalconductivity;
+	double     mixed_layer_capacity,thermal_exchange_velocity;
+
+	/*parameters: */
+	double dt,artdiff,epsvel;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	// /*recovre material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	heatcapacity=matpar->GetHeatCapacity();
+	thermalconductivity=matpar->GetThermalConductivity();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+	this->parameters->FindParam(&artdiff,ArtDiffEnum);
+	this->parameters->FindParam(&epsvel,EpsVelEnum);
+
+	/* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+		get tria gaussian points as well as segment gaussian points. For tria gaussian 
+		points, order of integration is 2, because we need to integrate the product tB*D*B' 
+		which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+		points, same deal, which yields 3 gaussian points.: */
+
+	/*Get gaussian points: */
+	area_order=2;
+	num_vert_gauss=2;
+
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (igarea=0; igarea<num_area_gauss; igarea++){
+		for (igvert=0; igvert<num_vert_gauss; igvert++){
+			/*Pick up the gaussian point: */
+			area_gauss_weight=*(area_gauss_weights+igarea);
+			vert_gauss_weight=*(vert_gauss_weights+igvert);
+			gauss_weight=area_gauss_weight*vert_gauss_weight;
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=*(vert_gauss_coord+igvert);
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+			/*Conduction: */
+
+			/*Get B_conduct matrix: */
+			GetB_conduct(&B_conduct[0][0],&xyz_list[0][0],gauss_coord); 
+
+			/*Build D: */
+			D_scalar=gauss_weight*Jdet*(thermalconductivity/(rho_ice*heatcapacity));
+
+			if(dt){
+				D_scalar=D_scalar*dt;
+			}
+
+			D[0][0]=D_scalar; D[0][1]=0; D[0][2]=0;
+			D[1][0]=0; D[1][1]=D_scalar; D[1][2]=0;
+			D[2][0]=0; D[2][1]=0; D[2][2]=D_scalar;
+
+			/*  Do the triple product B'*D*B: */
+			MatrixMultiply(&B_conduct[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_conduct[0][0],0);
+			MatrixMultiply(&tBD_conduct[0][0],numdof,3,0,&B_conduct[0][0],3,numdof,0,&Ke_gaussian_conduct[0][0],0);
+
+			/*Advection: */
+
+			/*Get B_advec and Bprime_advec matrices: */
+			GetB_advec(&B_advec[0][0],&xyz_list[0][0],gauss_coord); 
+			GetBprime_advec(&Bprime_advec[0][0],&xyz_list[0][0],gauss_coord); 
+
+			//Build the D matrix
+			inputs->GetParameterValue(&u, gauss_coord,VxEnum);
+			inputs->GetParameterValue(&v, gauss_coord,VyEnum);
+			inputs->GetParameterValue(&w, gauss_coord,VzEnum);
+
+			D_scalar=gauss_weight*Jdet;
+
+			if(dt){
+				D_scalar=D_scalar*dt;
+			}
+
+			D[0][0]=D_scalar*u;D[0][1]=0;         D[0][2]=0;
+			D[1][0]=0;         D[1][1]=D_scalar*v;D[1][2]=0;
+			D[2][0]=0;         D[2][1]=0;         D[2][2]=D_scalar*w;
+
+			/*  Do the triple product B'*D*Bprime: */
+			MatrixMultiply(&B_advec[0][0],3,numdof,1,&D[0][0],3,3,0,&tBD_advec[0][0],0);
+			MatrixMultiply(&tBD_advec[0][0],numdof,3,0,&Bprime_advec[0][0],3,numdof,0,&Ke_gaussian_advec[0][0],0);
+
+			/*Transient: */
+			if(dt){
+				GetNodalFunctions(&L[0], gauss_coord);
+				D_scalar=gauss_weight*Jdet;
+				D_scalar=D_scalar;
+
+				/*  Do the triple product L'*D*L: */
+				MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0);
+				MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian_transient[0][0],0);
+			}
+			else{
+				for(i=0;i<numdof;i++){
+					for(j=0;j<numdof;j++){
+						Ke_gaussian_transient[i][j]=0;
+					}
+				}
+			}
+
+			/*Artifficial diffusivity*/
+			if(artdiff){
+				/*Build K: */
+				D_scalar=gauss_weight*Jdet/(pow(u,2)+pow(v,2)+epsvel);
+				if(dt){
+					D_scalar=D_scalar*dt;
+				}
+				K[0][0]=D_scalar*pow(u,2);       K[0][1]=D_scalar*fabs(u)*fabs(v);
+				K[1][0]=D_scalar*fabs(u)*fabs(v);K[1][1]=D_scalar*pow(v,2);
+
+				/*Get B_artdiff: */
+				GetB_artdiff(&B_artdiff[0][0],&xyz_list[0][0],gauss_coord); 
+
+				/*  Do the triple product B'*K*B: */
+				MatrixMultiply(&B_artdiff[0][0],2,numdof,1,&K[0][0],2,2,0,&tBD_artdiff[0][0],0);
+				MatrixMultiply(&tBD_artdiff[0][0],numdof,2,0,&B_artdiff[0][0],2,numdof,0,&Ke_gaussian_artdiff[0][0],0);
+			}
+			else{
+				for(i=0;i<numdof;i++){
+					for(j=0;j<numdof;j++){
+						Ke_gaussian_artdiff[i][j]=0;
+					}
+				}
+			}
+
+			/*Add Ke_gaussian to pKe: */
+			for(i=0;i<numdof;i++){
+				for(j=0;j<numdof;j++){
+					K_terms[i][j]+=Ke_gaussian_conduct[i][j]+Ke_gaussian_advec[i][j]+Ke_gaussian_transient[i][j]+Ke_gaussian_artdiff[i][j];
+				}
+			}
+		}
+	}
+
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+	xfree((void**)&vert_gauss_coord);
+
+	//Ice/ocean heat exchange flux on ice shelf base 
+	if(onbed && shelf){
+
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreateKMatrixThermal(Kgg, analysis_type,sub_analysis_type);
+		delete tria;
+	}
+}
+/*}}}*/
+/*FUNCTION CreatePVector {{{1*/
+void  Penta::CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+
+		CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+
+		if (sub_analysis_type==HorizAnalysisEnum){
+
+			CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+		}
+		else if (sub_analysis_type==VertAnalysisEnum){
+
+			CreatePVectorDiagnosticVert( pg,analysis_type,sub_analysis_type);
+		}
+		else if (sub_analysis_type==StokesAnalysisEnum){
+
+			CreatePVectorDiagnosticStokes( pg,analysis_type,sub_analysis_type);
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+
+		CreatePVectorSlopeCompute( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		CreatePVectorPrognostic( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		CreatePVectorBalancedthickness( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		CreatePVectorBalancedvelocities( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==ThermalAnalysisEnum){
+
+		CreatePVectorThermal( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==MeltingAnalysisEnum){
+
+		CreatePVectorMelting( pg,analysis_type,sub_analysis_type);
+	}
+	else{
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}	
+
+}
+/*}}}*/
+/*FUNCTION CreatePVectorBalancedthickness {{{1*/
+void Penta::CreatePVectorBalancedthickness( Vec pg, int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*flags: */
+	bool onbed;
+	bool onwater;
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreatePVector(pg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+}
+/*}}}*/
+/*FUNCTION CreatePVectorBalancedvelocities {{{1*/
+void Penta::CreatePVectorBalancedvelocities( Vec pg, int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*flags: */
+	bool onbed;
+	bool onwater;
+
+	/*recover some inputs: */
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreatePVector(pg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+}
+/*}}}*/
+/*FUNCTION CreatePVectorDiagnosticHoriz {{{1*/
+void Penta::CreatePVectorDiagnosticHoriz( Vec pg, int analysis_type,int sub_analysis_type){
+
+	int i,j;
+
+	/* node data: */
+	const int    numgrids=6;
+	const int    NDOF2=2;
+	const int    numdof=NDOF2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* parameters: */
+	double  slope[3]; //do not put 2! this goes into GetParameterDerivativeValue, which addresses slope[3] also!
+	double  driving_stress_baseline;
+	double  thickness;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* fourth_gauss_vert_coord  =  NULL;
+	double* area_gauss_weights      =  NULL;
+	double* vert_gauss_weights      =  NULL;
+	double  gauss_coord[4];
+	int     order_area_gauss;
+	int     num_vert_gauss;
+	int     num_area_gauss;
+	int     ig1,ig2;
+	double  gauss_weight1,gauss_weight2;
+	double  gauss_weight;
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l6[6];
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof]={0.0};
+	double  pe_g_gaussian[numdof];
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+
+	/*Spawning: */
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip load: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+
+
+	/*Figure out if this pentaelem is collapsed. If so, then bailout, except if it is at the 
+	  bedrock, in which case we spawn a tria element using the 3 first grids, and use it to build 
+	  the load vector. */
+
+	if ((collapse==1) && (onbed==0)){
+		/*This element should be collapsed, but this element is not on the bedrock, therefore all its 
+		 * dofs have already been frozen! Do nothing: */
+		return;
+	}
+	else if ((collapse==1) && (onbed==1)){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 *and use its CreatePVector functionality to return an elementary load vector: */
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreatePVector(pg, analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else{
+
+		/*Implement standard penta element: */
+
+		/* Get node coordinates and dof list: */
+		GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+		GetDofList(&doflist[0],&numberofdofspernode);
+
+		/*Get gaussian points and weights :*/
+		order_area_gauss=2;
+		num_vert_gauss=3;
+
+		GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);
+
+		/* Start  looping on the number of gaussian points: */
+		for (ig1=0; ig1<num_area_gauss; ig1++){
+			for (ig2=0; ig2<num_vert_gauss; ig2++){
+
+				/*Pick up the gaussian point: */
+				gauss_weight1=*(area_gauss_weights+ig1);
+				gauss_weight2=*(vert_gauss_weights+ig2);
+				gauss_weight=gauss_weight1*gauss_weight2;
+
+				gauss_coord[0]=*(first_gauss_area_coord+ig1); 
+				gauss_coord[1]=*(second_gauss_area_coord+ig1);
+				gauss_coord[2]=*(third_gauss_area_coord+ig1);
+				gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);
+
+				/*Compute thickness at gaussian point: */
+				inputs->GetParameterValue(&thickness, gauss_coord,ThicknessEnum);
+
+				/*Compute slope at gaussian point: */
+				inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],gauss_coord,SurfaceEnum);
+
+				/* Get Jacobian determinant: */
+				GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+				/*Get nodal functions: */
+				GetNodalFunctions(l1l6, gauss_coord);
+
+				/*Compute driving stress: */
+				driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG();
+
+				/*Build pe_g_gaussian vector: */
+				for (i=0;i<numgrids;i++){
+					for (j=0;j<NDOF2;j++){
+						pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l6[i];
+					}
+				}
+
+				/*Add pe_g_gaussian vector to pe_g: */
+				for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
+
+			} //for (ig2=0; ig2<num_vert_gauss; ig2++)
+		} //for (ig1=0; ig1<num_area_gauss; ig1++)
+
+	} //else if ((collapse==1) && (onbed==1))
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&fourth_gauss_vert_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION CreatePVectorDiagnosticStokes {{{1*/
+void Penta::CreatePVectorDiagnosticStokes( Vec pg, int analysis_type,int sub_analysis_type){
+
+	/*indexing: */
+	int i,j;
+
+	const int numgrids=6;
+	const int DOFPERGRID=4;
+	const int numdof=numgrids*DOFPERGRID;
+	const int numgrids2d=3;
+	int numdof2d=numgrids2d*DOFPERGRID;
+	int doflist[numdof];
+	int numberofdofspernode;
+
+	/*Material properties: */
+	double         gravity,rho_ice,rho_water;
+
+	/*parameters: */
+	double		   xyz_list_tria[numgrids2d][3];
+	double         xyz_list[numgrids][3];
+	double		   surface_normal[3];
+	double		   bed_normal[3];
+	double         bed;
+
+	/* gaussian points: */
+	int     num_area_gauss;
+	int     igarea,igvert;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* vert_gauss_coord = NULL;
+	double* area_gauss_weights  =  NULL;
+	double* vert_gauss_weights  =  NULL;
+
+	/* specific gaussian point: */
+	double  gauss_weight,area_gauss_weight,vert_gauss_weight;
+	double  gauss_coord[4];
+	double  gauss_coord_tria[3];
+
+	int     area_order=5;
+	int	  num_vert_gauss=5;
+
+	double  epsilon[6]; /* epsilon=[exx,eyy,ezz,exy,exz,eyz];*/
+	double  viscosity;
+	double  water_pressure;
+	int     dofs[3]={0,1,2};
+
+	/*matrices: */
+	double     Pe_temp[27]={0.0}; //for the six nodes and the bubble 
+	double     Pe_gaussian[27]={0.0}; //for the six nodes and the bubble 
+	double     Ke_temp[27][3]={0.0}; //for the six nodes and the bubble 
+	double     Pe_reduced[numdof]; //for the six nodes only
+	double     Ke_gaussian[27][3];
+	double     L[3]; //for the three nodes of the bed
+	double     l1l7[7]; //for the six nodes and the bubble 
+	double     B[8][27];
+	double     B_prime[8][27];
+	double     B_prime_bubble[8][3];
+	double     Jdet;
+	double     Jdet2d;
+	double     D[8][8]={0.0};
+	double     D_scalar;
+	double     tBD[27][8];
+	double     P_terms[numdof]={0.0};
+
+	Tria*            tria=NULL;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*parameters: */
+	double stokesreconditioning;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&stokesreconditioning,StokesReconditioningEnum);
+
+	/*If on water, skip load: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+
+	/*recovre material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+		get tria gaussian points as well as segment gaussian points. For tria gaussian 
+		points, order of integration is 2, because we need to integrate the product tB*D*B' 
+		which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+		points, same deal, which yields 3 gaussian points.*/
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (igarea=0; igarea<num_area_gauss; igarea++){
+		for (igvert=0; igvert<num_vert_gauss; igvert++){
+			/*Pick up the gaussian point: */
+			area_gauss_weight=*(area_gauss_weights+igarea);
+			vert_gauss_weight=*(vert_gauss_weights+igvert);
+			gauss_weight=area_gauss_weight*vert_gauss_weight;
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=*(vert_gauss_coord+igvert);
+
+			/*Compute strain rate and viscosity: */
+			inputs->GetStrainRateStokes(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum,VzEnum);
+			matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+			/* Get nodal functions */
+			GetNodalFunctionsStokes(&l1l7[0], gauss_coord);
+
+			/* Build gaussian vector */
+			for(i=0;i<numgrids+1;i++){
+				Pe_gaussian[i*DOFPERGRID+2]=-rho_ice*gravity*Jdet*gauss_weight*l1l7[i];
+			}
+
+			/*Add Pe_gaussian to terms in Pe_temp. Watch out for column orientation from matlab: */
+			for(i=0;i<27;i++){
+				Pe_temp[i]+=Pe_gaussian[i];
+			}
+
+			/*Get B and Bprime matrices: */
+			GetBStokes(&B[0][0],&xyz_list[0][0],gauss_coord); 
+			GetBprimeStokes(&B_prime[0][0],&xyz_list[0][0], gauss_coord); 
+
+			/*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];
+				}
+			}
+
+			/* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant 
+			 * onto this scalar matrix, so that we win some computational time: */
+			D_scalar=gauss_weight*Jdet;
+			for (i=0;i<6;i++){
+				D[i][i]=D_scalar*viscosity;
+			}
+			for (i=6;i<8;i++){
+				D[i][i]=-D_scalar*stokesreconditioning;
+			}
+
+			/*  Do the triple product tB*D*Bprime: */
+			MatrixMultiply(&B[0][0],8,27,1,&D[0][0],8,8,0,&tBD[0][0],0);
+			MatrixMultiply(&tBD[0][0],27,8,0,&B_prime_bubble[0][0],8,3,0,&Ke_gaussian[0][0],0);
+
+			/*Add Ke_gaussian and Ke_gaussian to terms in pKe. Watch out for column orientation from matlab: */
+			for(i=0;i<27;i++){
+				for(j=0;j<3;j++){
+					Ke_temp[i][j]+=Ke_gaussian[i][j];
+				}
+			}
+		}
+	}
+
+	/*Deal with 2d friction at the bedrock interface: */
+	if ( (onbed==1) && (shelf==1)){
+
+		for(i=0;i<numgrids2d;i++){
+			for(j=0;j<3;j++){
+				xyz_list_tria[i][j]=xyz_list[i][j];
+			}
+		}
+
+		xfree((void**)&first_gauss_area_coord); xfree((void**)&second_gauss_area_coord); xfree((void**)&third_gauss_area_coord); xfree((void**)&area_gauss_weights);
+		GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, 2);
+
+		/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+		for (igarea=0; igarea<num_area_gauss; igarea++){
+			gauss_weight=*(area_gauss_weights+igarea);
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=-1;
+
+			gauss_coord_tria[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord_tria[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord_tria[2]=*(third_gauss_area_coord+igarea);
+
+			/*Get the Jacobian determinant */
+			tria->GetJacobianDeterminant3d(&Jdet2d, &xyz_list_tria[0][0], gauss_coord_tria);
+
+			/* Get bed at gaussian point */
+			inputs->GetParameterValue(&bed, gauss_coord,BedEnum);
+
+			/*Get L matrix : */
+			tria->GetL(&L[0], &xyz_list[0][0], gauss_coord_tria,1);
+
+			/*Get water_pressure at gaussian point */
+			water_pressure=gravity*rho_water*bed;
+
+			/*Get normal vecyor to the bed */
+			SurfaceNormal(&surface_normal[0],xyz_list_tria);
+
+			bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
+			bed_normal[1]=-surface_normal[1];
+			bed_normal[2]=-surface_normal[2];
+
+			for(i=0;i<numgrids2d;i++){
+				for(j=0;j<3;j++){
+					Pe_temp[i*DOFPERGRID+j]+=water_pressure*gauss_weight*Jdet2d*L[i]*bed_normal[j];
+				}
+			}
+		}
+	} //if ( (onbed==1) && (shelf==1))
+
+	/*Reduce the matrix */
+	ReduceVectorStokes(&Pe_reduced[0], &Ke_temp[0][0], &Pe_temp[0]);
+
+	for(i=0;i<numdof;i++){
+		P_terms[i]+=Pe_reduced[i];
+	}
+
+	/*Add P_terms to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+
+	/*Free ressources:*/
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_coord);
+	xfree((void**)&vert_gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION CreatePVectorDiagnosticVert {{{1*/
+void  Penta::CreatePVectorDiagnosticVert( Vec pg, int analysis_type,int sub_analysis_type){
+
+	int i;
+
+
+	/* node data: */
+	const int    numgrids=6;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* fourth_gauss_vert_coord  =  NULL;
+	double* area_gauss_weights      =  NULL;
+	double* vert_gauss_weights      =  NULL;
+	double  gauss_coord[4];
+	int     order_area_gauss;
+	int     num_vert_gauss;
+	int     num_area_gauss;
+	int     ig1,ig2;
+	double  gauss_weight1,gauss_weight2;
+	double  gauss_weight;
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof]={0.0};
+	double  pe_g_gaussian[numdof];
+	double l1l6[6];
+
+	/*Spawning: */
+	Tria* tria=NULL;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double du[3];
+	double dv[3];
+	double dudx,dvdy;
+	int     dofs1[1]={0};
+	int     dofs2[1]={1};
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*If we are on the bedrock, spawn a tria on the bedrock, and use it to build the 
+	 *diagnostic base vertical stifness: */
+	if(onbed){
+		tria=(Tria*)SpawnTria(0,1,2); //nodes 0, 1 and 2 are on the bedrock
+		tria->CreatePVectorDiagnosticBaseVert(pg, analysis_type,sub_analysis_type);
+		delete tria;
+	}
+
+	/*Now, handle the standard penta element: */
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*Get gaussian points and weights :*/
+	order_area_gauss=2;
+	num_vert_gauss=2;
+
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights, &fourth_gauss_vert_coord,&vert_gauss_weights,order_area_gauss,num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig1=0; ig1<num_area_gauss; ig1++){
+		for (ig2=0; ig2<num_vert_gauss; ig2++){
+
+			/*Pick up the gaussian point: */
+			gauss_weight1=*(area_gauss_weights+ig1);
+			gauss_weight2=*(vert_gauss_weights+ig2);
+			gauss_weight=gauss_weight1*gauss_weight2;
+
+			gauss_coord[0]=*(first_gauss_area_coord+ig1); 
+			gauss_coord[1]=*(second_gauss_area_coord+ig1);
+			gauss_coord[2]=*(third_gauss_area_coord+ig1);
+			gauss_coord[3]=*(fourth_gauss_vert_coord+ig2);
+
+			/*Get velocity derivative, with respect to x and y: */
+
+			inputs->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss_coord,VxEnum);
+			inputs->GetParameterDerivativeValue(&du[0],&xyz_list[0][0],gauss_coord,VyEnum);
+			dudx=du[0];
+			dvdy=dv[1];
+
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+			/*Get nodal functions: */
+			GetNodalFunctions(l1l6, gauss_coord);
+
+			/*Build pe_g_gaussian vector: */
+			for (i=0;i<numgrids;i++){
+				pe_g_gaussian[i]=(dudx+dvdy)*Jdet*gauss_weight*l1l6[i];
+			}
+
+			/*Add pe_g_gaussian vector to pe_g: */
+			for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
+
+		} //for (ig2=0; ig2<num_vert_gauss; ig2++)
+	} //for (ig1=0; ig1<num_area_gauss; ig1++)
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&fourth_gauss_vert_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+}
+/*}}}*/
+/*FUNCTION CreatePVectorMelting {{{1*/
+void Penta::CreatePVectorMelting( Vec pg, int analysis_type,int sub_analysis_type){
+	return;
+}
+/*}}}*/
+/*FUNCTION CreatePVectorPrognostic {{{1*/
+
+void Penta::CreatePVectorPrognostic( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreatePVector(pg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+}
+/*}}}*/
+/*FUNCTION CreatePVectorSlopeCompute {{{1*/
+
+void Penta::CreatePVectorSlopeCompute( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Is this element on the bed? :*/
+	if(!onbed)return;
+
+	/*Spawn Tria element from the base of the Penta: */
+	tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+	tria->CreatePVector(pg, analysis_type,sub_analysis_type);
+	delete tria;
+	return;
+}
+/*}}}*/
+/*FUNCTION CreatePVectorThermal {{{1*/
+void Penta::CreatePVectorThermal( Vec pg, int analysis_type,int sub_analysis_type){
+
+
+	/*indexing: */
+	int i,j;
+	int found=0;
+
+	const int  numgrids=6;
+	const int  NDOF1=1;
+	const int  numdof=numgrids*NDOF1;
+	int        doflist[numdof];
+	int        numberofdofspernode;
+
+	/*Grid data: */
+	double        xyz_list[numgrids][3];
+
+	/* gaussian points: */
+	int     num_area_gauss,igarea,igvert;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* vert_gauss_coord = NULL;
+	double* area_gauss_weights  =  NULL;
+	double* vert_gauss_weights  =  NULL;
+	double  gauss_weight,area_gauss_weight,vert_gauss_weight;
+	double  gauss_coord[4];
+	int     area_order=2;
+	int	  num_vert_gauss=3;
+
+	double temperature_list[numgrids];
+	double temperature;
+
+	/*Material properties: */
+	double gravity,rho_ice,rho_water;
+	double mixed_layer_capacity,heatcapacity;
+	double beta,meltingpoint,thermal_exchange_velocity;
+
+	/* element parameters: */
+	int    friction_type;
+
+	int    dofs[3]={0,1,2};
+	int    dofs1[1]={0};
+
+	/*matrices: */
+	double P_terms[numdof]={0.0};
+	double L[numdof];
+	double l1l2l3[3];
+	double alpha2_list[3];
+	double basalfriction_list[3]={0.0};
+	double basalfriction;
+	double epsilon[6];
+	double epsilon_sqr[3][3];
+	double epsilon_matrix[3][3];
+
+	double Jdet;
+	double viscosity;
+	double epsilon_eff;
+	double phi;
+	double t_pmp;
+	double scalar;
+	double scalar_def;
+	double scalar_ocean;
+	double scalar_transient;
+
+	/*Collapsed formulation: */
+	Tria*  tria=NULL;
+
+	/*parameters: */
+	double dt;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*recovre material parameters: */
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	heatcapacity=matpar->GetHeatCapacity();
+	beta=matpar->GetBeta();
+	meltingpoint=matpar->GetMeltingPoint();
+
+	/* Get gaussian points and weights. Penta is an extrusion of a Tria, we therefore 
+		get tria gaussian points as well as segment gaussian points. For tria gaussian 
+		points, order of integration is 2, because we need to integrate the product tB*D*B' 
+		which is a polynomial of degree 3 (see GaussTria for more details). For segment gaussian 
+		points, same deal, which yields 3 gaussian points.: */
+
+	/*Get gaussian points: */
+	GaussPenta( &num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &area_gauss_weights,&vert_gauss_coord, &vert_gauss_weights, area_order, num_vert_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (igarea=0; igarea<num_area_gauss; igarea++){
+		for (igvert=0; igvert<num_vert_gauss; igvert++){
+			/*Pick up the gaussian point: */
+			area_gauss_weight=*(area_gauss_weights+igarea);
+			vert_gauss_weight=*(vert_gauss_weights+igvert);
+			gauss_weight=area_gauss_weight*vert_gauss_weight;
+			gauss_coord[0]=*(first_gauss_area_coord+igarea); 
+			gauss_coord[1]=*(second_gauss_area_coord+igarea);
+			gauss_coord[2]=*(third_gauss_area_coord+igarea);
+			gauss_coord[3]=*(vert_gauss_coord+igvert);
+
+			/*Compute strain rate and viscosity: */
+			inputs->GetStrainRateStokes(&epsilon[0],&xyz_list[0][0],gauss_coord,VxEnum,VyEnum,VzEnum);
+			matice->GetViscosity3dStokes(&viscosity,&epsilon[0]);
+
+			/* Get Jacobian determinant: */
+			GetJacobianDeterminant(&Jdet, &xyz_list[0][0],gauss_coord);
+
+			/* Get nodal functions */
+			GetNodalFunctions(&L[0], gauss_coord);
+
+			/*Build deformational heating: */
+			GetPhi(&phi, &epsilon[0], viscosity);
+
+			/*Build pe_gaussian */
+			scalar_def=phi/(rho_ice*heatcapacity)*Jdet*gauss_weight;
+			if(dt){
+				scalar_def=scalar_def*dt;
+			}
+
+			for(i=0;i<numgrids;i++){
+				P_terms[i]+=scalar_def*L[i];
+			}
+
+			/* Build transient now */
+			if(dt){
+				inputs->GetParameterValue(&temperature, gauss_coord,TemperatureEnum);
+				scalar_transient=temperature*Jdet*gauss_weight;
+				for(i=0;i<numgrids;i++){
+					P_terms[i]+=scalar_transient*L[i];
+				}
+			}
+		}
+	}
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+
+	/* Ice/ocean heat exchange flux on ice shelf base */
+	if(onbed && shelf){
+
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreatePVectorThermalShelf(pg, analysis_type,sub_analysis_type);
+		delete tria;
+	}
+
+	/* Geothermal flux on ice sheet base and basal friction */
+	if(onbed && !shelf){
+
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->CreatePVectorThermalSheet(pg, analysis_type,sub_analysis_type);
+		delete tria;
+	}
+	extern int my_rank;
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&vert_gauss_coord);
+	xfree((void**)&area_gauss_weights);
+	xfree((void**)&vert_gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Du {{{1*/
+void  Penta::Du(Vec du_g,int analysis_type,int sub_analysis_type){
+
+	int i;
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onsurface;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*Bail out if this element if:
+	 * -> Non collapsed and not on the surface
+	 * -> collapsed (2d model) and not on bed) */
+	if ((!collapse && !onsurface) || (collapse && !onbed)){
+		return;
+	}
+	else if (collapse){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute Du*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		tria->Du(du_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).
+		tria->Du(du_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+}
+/*}}}*/
+/*FUNCTION FieldExtrude {{{1*/
+void  Penta::FieldExtrude(Vec field,double* field_serial,char* field_name, int iscollapsed){
+
+	/* node data: */
+	const int    numgrids=6;
+	int          numberofdofspernode;
+	Node* node=NULL;
+	int   i;
+	int   extrude=0;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*inputs: */
+	bool collapse;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*Figure out if we should extrude for this element: */
+	if (iscollapsed){
+		/*From higher level, we are told to extrude only elements that have the collapse flag on: */
+		if (collapse)extrude=1;
+		else extrude=0;
+	}
+	else{
+		/*From higher level, we are told to extrude all elements: */
+		extrude=1;
+	}
+
+	/*Now, extrusion starts from the bed on, so double check this element is on 
+	 * the bedrock: */
+	if(onbed==0)extrude=0;
+
+	/*Go on and extrude field: */
+	if (extrude){
+
+		if (strcmp(field_name,"velocity")==0){
+
+			/* node data: */
+			const int    numdof=2*numgrids;
+			int          doflist[numdof];
+			int          nodedofs[2];
+			double       fieldel[2];
+
+
+			GetDofList(&doflist[0],&numberofdofspernode);
+
+			/*this penta is a collapsed macayeal. For each node on the base of this penta, 
+			 * we grab the field. Once we know the field, we follow the upper nodes, 
+			 * inserting the same field value into field, until we reach the surface: */
+			for(i=0;i<3;i++){
+
+				node=nodes[i]; //base nodes
+
+				/*get field for this base node: */
+				fieldel[0]=field_serial[doflist[numberofdofspernode*i+0]];
+				fieldel[1]=field_serial[doflist[numberofdofspernode*i+1]];
+
+				//go throfieldn all nodes which sit on top of this node, until we reach the surface, 
+				//and plfield  field in field
+				for(;;){
+
+					node->GetDofList(&nodedofs[0],&numberofdofspernode);
+					VecSetValues(field,1,&nodedofs[0],&fieldel[0],INSERT_VALUES);
+					VecSetValues(field,1,&nodedofs[1],&fieldel[1],INSERT_VALUES);
+
+					if (node->IsOnSurface())break;
+					/*get next node: */
+					node=node->GetUpperNode();
+				}
+			}
+		} //if (strcmp(field_name,"velocity")==0)
+		else if (strcmp(field_name,"gradj")==0){
+
+			/* node data: */
+			int          dof1;
+			double       fieldel;
+
+			/*this penta is a collapsed macayeal. For each node on the base of this penta, 
+			 * we grab the field. Once we know the field, we follow the upper nodes, 
+			 * inserting the same field value into field, until we reach the surface: */
+			for(i=0;i<3;i++){
+
+				node=nodes[i]; //base nodes
+				dof1=node->GetDofList1();
+
+				/*get field for this base node: */
+				fieldel=field_serial[dof1];
+
+				//go throfieldn all nodes which sit on top of this node, until we reach the surface, 
+				//and plfield  field in field
+				for(;;){
+
+					dof1=node->GetDofList1();
+					VecSetValues(field,1,&dof1,&fieldel,INSERT_VALUES);
+
+					if (node->IsOnSurface())break;
+					/*get next node: */
+					node=node->GetUpperNode();
+				}
+			}
+		}
+		else if ( 
+					(strcmp(field_name,"thickness")==0) ||
+					(strcmp(field_name,"surface")==0)  ||
+					(strcmp(field_name,"bed")==0)  ||
+					(strcmp(field_name,"slopex")==0)  ||
+					(strcmp(field_name,"slopey")==0)
+				  ){
+
+			/* node data: */
+			const int    numdof=1*numgrids;
+			int          doflist[numdof];
+			int          nodedofs;
+			double       fieldel;
+
+			GetDofList(&doflist[0],&numberofdofspernode);
+
+			/*this penta is on the bed. For each node on the base of this penta, 
+			 * we grab the thickness. Once we know the thickness, we follow the upper nodes, 
+			 * inserting the same thickness value into tg, until we reach the surface: */
+			for(i=0;i<3;i++){
+
+				node=nodes[i]; //base nodes
+
+				/*get velocity for this base node: */
+				fieldel=field_serial[doflist[numberofdofspernode*i+0]];
+
+				//go through all nodes which sit on top of this node, until we reach the surface, 
+				//and pltg  fieldel in field:
+				for(;;){
+
+					node->GetDofList(&nodedofs,&numberofdofspernode);
+					VecSetValues(field,1,&nodedofs,&fieldel,INSERT_VALUES);
+
+					if (node->IsOnSurface())break;
+					/*get next node: */
+					node=node->GetUpperNode();
+				}
+			}
+
+		}
+		else ISSMERROR("%s%s%s"," field ",field_name," not supported yet!");
+
+	} //if (extrude)
+}
+/*}}}*/
+/*FUNCTION GetB {{{1*/
+void Penta::GetB(double* B, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2. 
+	 * For grid i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ dh/dx          0      ]
+	 *                [   0           dh/dy   ]
+	 *                [ 1/2*dh/dy  1/2*dh/dx  ]
+	 *                [ 1/2*dh/dz      0      ]
+	 *                [  0         1/2*dh/dz  ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids)
+	 */
+
+	int i;
+	const int numgrids=6;
+	const int NDOF3=3;
+	const int NDOF2=2;
+
+	double dh1dh6[NDOF3][numgrids];
+
+	/*Get dh1dh6 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);
+
+	/*Build B: */
+	for (i=0;i<numgrids;i++){
+		*(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh6[0][i]; 
+		*(B+NDOF2*numgrids*0+NDOF2*i+1)=0.0;
+
+		*(B+NDOF2*numgrids*1+NDOF2*i)=0.0;
+		*(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh6[1][i];
+
+		*(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh6[1][i]; 
+		*(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh6[0][i]; 
+
+		*(B+NDOF2*numgrids*3+NDOF2*i)=(float).5*dh1dh6[2][i]; 
+		*(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0;
+
+		*(B+NDOF2*numgrids*4+NDOF2*i)=0.0;
+		*(B+NDOF2*numgrids*4+NDOF2*i+1)=(float).5*dh1dh6[2][i]; 
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetB_artdiff {{{1*/
+void Penta::GetB_artdiff(double* B_artdiff, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_artdiff=[ dh/dx ]
+	 *                       [ dh/dy ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 2x(DOFPERGRID*numgrids)
+	 */
+
+	int i;
+	const int calculationdof=3;
+	const int numgrids=6;
+	int DOFPERGRID=1;
+
+	/*Same thing in the actual coordinate system: */
+	double dh1dh6[calculationdof][numgrids];
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(B_artdiff+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 
+		*(B_artdiff+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION GetB_advec {{{1*/
+void Penta::GetB_advec(double* B_advec, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_advec =[ h ]
+	 *                       [ h ]
+	 *                       [ h ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)
+	 */
+
+	int i;
+	int calculationdof=3;
+	int numgrids=6;
+	int DOFPERGRID=1;
+
+	/*Same thing in the actual coordinate system: */
+	double l1l6[6];
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctions(l1l6, gauss_coord);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(B_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=l1l6[i]; 
+		*(B_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=l1l6[i]; 
+		*(B_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=l1l6[i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION GetB_conduct {{{1*/
+void Penta::GetB_conduct(double* B_conduct, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_conduct=[ dh/dx ]
+	 *                       [ dh/dy ]
+	 *                       [ dh/dz ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)
+	 */
+
+	int i;
+	const int calculationdof=3;
+	const int numgrids=6;
+	int DOFPERGRID=1;
+
+	/*Same thing in the actual coordinate system: */
+	double dh1dh6[calculationdof][numgrids];
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(B_conduct+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 
+		*(B_conduct+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 
+		*(B_conduct+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION GetB_vert {{{1*/
+void Penta::GetB_vert(double* B, double* xyz_list, double* gauss_coord){
+
+
+	/*	Compute B  matrix. B=[dh1/dz dh2/dz dh3/dz dh4/dz dh5/dz dh6/dz];
+		where hi is the interpolation function for grid i.*/
+
+	int i;
+	const int NDOF3=3;
+	const int numgrids=6;
+	double dh1dh6[NDOF3][numgrids];
+
+	/*Get dh1dh6 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);
+
+	/*Build B: */
+	for (i=0;i<numgrids;i++){
+		B[i]=dh1dh6[2][i];  
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetBedList {{{1*/
+void Penta::GetBedList(double* bedlist){
+
+	const int numgrids=6;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0,0},{0,1,0,0},{0,0,1,0},{1,0,0,1},{0,1,0,1},{0,0,1,1}};
+	
+	inputs->GetParameterValues(bedlist,&gaussgrids[0][0],6,BedEnum);
+
+}
+/*}}}*/
+/*FUNCTION GetBPrime {{{1*/
+void Penta::GetBPrime(double* B, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  prime matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*NDOF2. 
+	 * For grid i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ 2*dh/dx     dh/dy   ]
+	 *                [   dh/dx    2*dh/dy  ]
+	 *                [ dh/dy      dh/dx    ]
+	 *                [ dh/dz         0     ]
+	 *                [  0         dh/dz    ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 5x(NDOF2*numgrids)
+	 */
+
+	int i;
+	const int NDOF3=3;
+	const int NDOF2=2;
+	const int numgrids=6;
+
+	double dh1dh6[NDOF3][numgrids];
+
+	/*Get dh1dh6 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);
+
+	/*Build BPrime: */
+	for (i=0;i<numgrids;i++){
+		*(B+NDOF2*numgrids*0+NDOF2*i)=2.0*dh1dh6[0][i]; 
+		*(B+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh6[1][i];
+
+		*(B+NDOF2*numgrids*1+NDOF2*i)=dh1dh6[0][i];
+		*(B+NDOF2*numgrids*1+NDOF2*i+1)=2.0*dh1dh6[1][i];
+
+		*(B+NDOF2*numgrids*2+NDOF2*i)=dh1dh6[1][i]; 
+		*(B+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh6[0][i]; 
+
+		*(B+NDOF2*numgrids*3+NDOF2*i)=dh1dh6[2][i]; 
+		*(B+NDOF2*numgrids*3+NDOF2*i+1)=0.0;
+
+		*(B+NDOF2*numgrids*4+NDOF2*i)=0.0;
+		*(B+NDOF2*numgrids*4+NDOF2*i+1)=dh1dh6[2][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION GetBprime_advec {{{1*/
+void Penta::GetBprime_advec(double* Bprime_advec, double* xyz_list, double* gauss_coord){
+
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 5*DOFPERGRID. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Biprime_advec=[ dh/dx ]
+	 *                       [ dh/dy ]
+	 *                       [ dh/dz ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(DOFPERGRID*numgrids)
+	 */
+
+	int i;
+	const int calculationdof=3;
+	const int numgrids=6;
+	int DOFPERGRID=1;
+
+	/*Same thing in the actual coordinate system: */
+	double dh1dh6[calculationdof][numgrids];
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(Bprime_advec+DOFPERGRID*numgrids*0+DOFPERGRID*i)=dh1dh6[0][i]; 
+		*(Bprime_advec+DOFPERGRID*numgrids*1+DOFPERGRID*i)=dh1dh6[1][i]; 
+		*(Bprime_advec+DOFPERGRID*numgrids*2+DOFPERGRID*i)=dh1dh6[2][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION GetBPrime_vert {{{1*/
+void Penta::GetBPrime_vert(double* B, double* xyz_list, double* gauss_coord){
+
+	// Compute Bprime  matrix. Bprime=[L1 L2 L3 L4 L5 L6] where Li is the nodal function for grid i
+
+	int i;
+
+	GetNodalFunctions(B, gauss_coord);
+
+}
+/*}}}*/
+/*FUNCTION GetBprimeStokes {{{1*/
+void Penta::GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss_coord){
+
+	/*	Compute B'  matrix. B'=[B1' B2' B3' B4' B5' B6' Bb'] where Bi' is of size 3*NDOF2. 
+	 *	For grid i, Bi' can be expressed in the actual coordinate system
+	 *	by: 
+	 *				Bi'=[ dh/dx   0          0       0]
+	 *					 [   0      dh/dy      0       0]
+	 *					 [   0      0         dh/dz    0]
+	 *					 [  dh/dy   dh/dx      0       0]
+	 *					 [  dh/dz   0        dh/dx     0]
+	 *					 [   0      dh/dz    dh/dy     0]
+	 *					 [  dh/dx   dh/dy    dh/dz     0]
+	 *					 [   0      0          0       h]
+	 *	where h is the interpolation function for grid i.
+	 *
+	 * 	Same thing for the bubble fonction except that there is no fourth column
+	 */
+
+	int i;
+	const int calculationdof=3;
+	const int numgrids=6;
+	int DOFPERGRID=4;
+
+	double dh1dh7[calculationdof][numgrids+1];
+	double l1l6[numgrids];
+
+	/*Get dh1dh7 in actual coordinate system: */
+	GetNodalFunctionsDerivativesStokes(&dh1dh7[0][0],xyz_list, gauss_coord);
+
+	GetNodalFunctions(l1l6, gauss_coord);
+
+	/*B_primeuild B_prime: */
+	for (i=0;i<numgrids+1;i++){
+		*(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B_prime[0][DOFPERGRID*i]=dh1dh6[0][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=dh1dh7[1][i]; 
+		*(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=dh1dh7[0][i]; 
+		*(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=dh1dh7[2][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=dh1dh7[0][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=dh1dh7[2][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=dh1dh7[1][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=dh1dh7[0][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=dh1dh7[1][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=dh1dh7[2][i];
+		*(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=0;
+	}
+
+	for (i=0;i<numgrids;i++){ //last column not for the bubble function
+		*(B_prime+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=0;
+		*(B_prime+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=l1l6[i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetBStokes {{{1*/
+void Penta::GetBStokes(double* B, double* xyz_list, double* gauss_coord){
+
+	/*Compute B  matrix. B=[B1 B2 B3 B4 B5 B6] where Bi is of size 3*DOFPERGRID. 
+	 * For grid i, Bi can be expressed in the actual coordinate system
+	 * by: 				Bi=[ dh/dx          0             0       0  ]
+	 *					[   0           dh/dy           0       0  ]
+	 *					[   0             0           dh/dy     0  ]
+	 *					[ 1/2*dh/dy    1/2*dh/dx        0       0  ]
+	 *					[ 1/2*dh/dz       0         1/2*dh/dx   0  ]
+	 *					[   0          1/2*dh/dz    1/2*dh/dy   0  ]
+	 *					[   0             0             0       h  ]
+	 *					[ dh/dx         dh/dy         dh/dz     0  ]
+	 *	where h is the interpolation function for grid i.
+	 *	Same thing for Bb except the last column that does not exist.
+	 */
+
+	int i;
+	const int calculationdof=3;
+	const int numgrids=6;
+	int DOFPERGRID=4;
+
+	double dh1dh7[calculationdof][numgrids+1];
+	double l1l6[numgrids];
+
+
+	/*Get dh1dh7 in actual coordinate system: */
+	GetNodalFunctionsDerivativesStokes(&dh1dh7[0][0],xyz_list, gauss_coord);
+
+	GetNodalFunctions(l1l6, gauss_coord);
+
+	/*Build B: */
+	for (i=0;i<numgrids+1;i++){
+		*(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i)=dh1dh7[0][i]; //B[0][DOFPERGRID*i]=dh1dh6[0][i];
+		*(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+1)=0;
+		*(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+2)=0;
+		*(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i)=0;
+		*(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+1)=dh1dh7[1][i];
+		*(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+2)=0;
+		*(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i)=0;
+		*(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+1)=0;
+		*(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+2)=dh1dh7[2][i];
+		*(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i)=(float).5*dh1dh7[1][i]; 
+		*(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+1)=(float).5*dh1dh7[0][i]; 
+		*(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+2)=0;
+		*(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i)=(float).5*dh1dh7[2][i];
+		*(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+1)=0;
+		*(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+2)=(float).5*dh1dh7[0][i];
+		*(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i)=0;
+		*(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+1)=(float).5*dh1dh7[2][i];
+		*(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+2)=(float).5*dh1dh7[1][i];
+		*(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i)=0;
+		*(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+1)=0;
+		*(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+2)=0;
+		*(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i)=dh1dh7[0][i];
+		*(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+1)=dh1dh7[1][i];
+		*(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+2)=dh1dh7[2][i];
+	}
+
+	for (i=0;i<numgrids;i++){ //last column not for the bubble function
+		*(B+(DOFPERGRID*numgrids+3)*0+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*1+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*2+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*3+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*4+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*5+DOFPERGRID*i+3)=0;
+		*(B+(DOFPERGRID*numgrids+3)*6+DOFPERGRID*i+3)=l1l6[i];
+		*(B+(DOFPERGRID*numgrids+3)*7+DOFPERGRID*i+3)=0;
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetDofList {{{1*/
+void  Penta::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	for(i=0;i<6;i++){
+		nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+		for(j=0;j<numberofdofspernode;j++){
+			doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION GetDofList1 {{{1*/
+void  Penta::GetDofList1(int* doflist){
+	
+	int i;
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	for(i=0;i<6;i++){
+		doflist[i]=nodes[i]->GetDofList1();
+	}
+
+}
+/*}}}*/
+/*FUNCTION Id {{{1*/
+int    Penta::Id(void){
+	return id; 
+}
+/*}}}*/
+/*FUNCTION GetJacobian {{{1*/
+void Penta::GetJacobian(double* J, double* xyz_list,double* gauss_coord){
+
+	const int NDOF3=3;
+	int i,j;
+
+	/*The Jacobian is constant over the element, discard the gaussian points. 
+	 * J is assumed to have been allocated of size NDOF2xNDOF2.*/
+
+	double A1,A2,A3; //area coordinates
+	double xi,eta,zi; //parametric coordinates
+
+	double x1,x2,x3,x4,x5,x6;
+	double y1,y2,y3,y4,y5,y6;
+	double z1,z2,z3,z4,z5,z6;
+
+	/*Figure out xi,eta and zi (parametric coordinates), for this gaussian point: */
+	A1=gauss_coord[0];
+	A2=gauss_coord[1];
+	A3=gauss_coord[2];
+
+	xi=A2-A1;
+	eta=SQRT3*A3;
+	zi=gauss_coord[3];
+
+	x1=*(xyz_list+3*0+0);
+	x2=*(xyz_list+3*1+0);
+	x3=*(xyz_list+3*2+0);
+	x4=*(xyz_list+3*3+0);
+	x5=*(xyz_list+3*4+0);
+	x6=*(xyz_list+3*5+0);
+
+	y1=*(xyz_list+3*0+1);
+	y2=*(xyz_list+3*1+1);
+	y3=*(xyz_list+3*2+1);
+	y4=*(xyz_list+3*3+1);
+	y5=*(xyz_list+3*4+1);
+	y6=*(xyz_list+3*5+1);
+
+	z1=*(xyz_list+3*0+2);
+	z2=*(xyz_list+3*1+2);
+	z3=*(xyz_list+3*2+2);
+	z4=*(xyz_list+3*3+2);
+	z5=*(xyz_list+3*4+2);
+	z6=*(xyz_list+3*5+2);
+
+
+	*(J+NDOF3*0+0)=0.25*(x1-x2-x4+x5)*zi+0.25*(-x1+x2-x4+x5);
+	*(J+NDOF3*1+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*zi+SQRT3/12.0*(-x1-x2+2*x3-x4-x5+2*x6);
+	*(J+NDOF3*2+0)=SQRT3/12.0*(x1+x2-2*x3-x4-x5+2*x6)*eta+1/4*(x1-x2-x4+x5)*xi +0.25*(-x1+x5-x2+x4);
+
+	*(J+NDOF3*0+1)=0.25*(y1-y2-y4+y5)*zi+0.25*(-y1+y2-y4+y5);
+	*(J+NDOF3*1+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*zi+SQRT3/12.0*(-y1-y2+2*y3-y4-y5+2*y6);
+	*(J+NDOF3*2+1)=SQRT3/12.0*(y1+y2-2*y3-y4-y5+2*y6)*eta+0.25*(y1-y2-y4+y5)*xi+0.25*(y4-y1+y5-y2);
+
+	*(J+NDOF3*0+2)=0.25*(z1-z2-z4+z5)*zi+0.25*(-z1+z2-z4+z5);
+	*(J+NDOF3*1+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*zi+SQRT3/12.0*(-z1-z2+2*z3-z4-z5+2*z6);
+	*(J+NDOF3*2+2)=SQRT3/12.0*(z1+z2-2*z3-z4-z5+2*z6)*eta+0.25*(z1-z2-z4+z5)*xi+0.25*(-z1+z5-z2+z4);
+
+}
+/*}}}*/
+/*FUNCTION GetJacobianDeterminant {{{1*/
+void Penta::GetJacobianDeterminant(double*  Jdet, double* xyz_list,double* gauss_coord){
+
+	/*On a penta, Jacobian varies according to coordinates. We need to get the Jacobian, and take 
+	 * the determinant of it: */
+	const int NDOF3=3;
+
+	double J[NDOF3][NDOF3];
+
+	GetJacobian(&J[0][0],xyz_list,gauss_coord);
+
+	*Jdet= J[0][0]*J[1][1]*J[2][2]-J[0][0]*J[1][2]*J[2][1]-J[1][0]*J[0][1]*J[2][2]+J[1][0]*J[0][2]*J[2][1]+J[2][0]*J[0][1]*J[1][2]-J[2][0]*J[0][2]*J[1][1];
+
+	if(*Jdet<0){
+		ISSMERROR("%s%i","negative jacobian determinant on element ",id); 
+	}
+}
+/*}}}*/
+/*FUNCTION GetJacobianInvert {{{1*/
+void Penta::GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_coord){
+
+	double Jdet;
+	const int NDOF3=3;
+
+	/*Call Jacobian routine to get the jacobian:*/
+	GetJacobian(Jinv, xyz_list, gauss_coord);
+
+	/*Invert Jacobian matrix: */
+	MatrixInverse(Jinv,NDOF3,NDOF3,NULL,0,&Jdet);
+}
+/*}}}*/
+/*FUNCTION GetLStokes {{{1*/
+void Penta::GetLStokes(double* LStokes, double* gauss_coord_tria){
+
+	/*
+	 * Compute L  matrix. L=[L1 L2 L3] where Li is square and of size numdof. 
+	 * For grid i, Li can be expressed in the actual coordinate system
+	 * by: 
+	 *       Li=[ h    0    0   0]
+	 *	 	 [ 0    h    0   0]
+	 *		 [ 0    0    h   0]
+	 *		 [ 0    0    h   0]
+	 *	 	 [ h    0    0   0]
+	 *	 	 [ 0    h    0   0]
+	 *	 	 [ h    0    0   0]
+	 *	 	 [ 0    h    0   0]
+	 *		 [ 0    0    h   0]
+	 *		 [ 0    0    h   0]
+	 *		 [ 0    0    h   0]
+	 *	 	 [ h    0    0   0]
+	 *	 	 [ 0    h    0   0]
+	 *		 [ 0    0    h   0]
+	 * where h is the interpolation function for grid i.
+	 */
+
+	int i;
+	const int numgrids2d=3;
+	int num_dof=4;
+
+	double l1l2l3[numgrids2d];
+
+
+	/*Get l1l2l3 in actual coordinate system: */
+	l1l2l3[0]=gauss_coord_tria[0];
+	l1l2l3[1]=gauss_coord_tria[1];
+	l1l2l3[2]=gauss_coord_tria[2];
+
+	/*Build LStokes: */
+	for (i=0;i<3;i++){
+		*(LStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LStokes[0][NDOF2*i]=dh1dh3[0][i];
+		*(LStokes+num_dof*numgrids2d*0+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*0+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*0+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*1+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*1+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*1+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*2+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*2+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*2+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*2+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*3+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*3+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*3+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*3+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*4+num_dof*i)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*4+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*4+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*4+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*5+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*5+num_dof*i+1)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*5+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*5+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*6+num_dof*i)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*6+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*6+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*6+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*7+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*7+num_dof*i+1)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*7+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*7+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*8+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*8+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*8+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*8+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*9+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*9+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*9+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*9+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*10+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*10+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*10+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*10+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*11+num_dof*i)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*11+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*11+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*11+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*12+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*12+num_dof*i+1)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*12+num_dof*i+2)=0;
+		*(LStokes+num_dof*numgrids2d*12+num_dof*i+3)=0;
+		*(LStokes+num_dof*numgrids2d*13+num_dof*i)=0;
+		*(LStokes+num_dof*numgrids2d*13+num_dof*i+1)=0;
+		*(LStokes+num_dof*numgrids2d*13+num_dof*i+2)=l1l2l3[i];
+		*(LStokes+num_dof*numgrids2d*13+num_dof*i+3)=0;
+
+	}
+}
+/*}}}*/
+/*FUNCTION GetLprimeStokes {{{1*/
+void Penta::GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_coord_tria, double* gauss_coord){
+
+	/*
+	 * Compute Lprime  matrix. Lprime=[Lp1 Lp2 Lp3] where Lpi is square and of size numdof. 
+	 * For grid i, Lpi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Lpi=[ h    0    0   0]
+	 *		 [ 0    h    0   0]
+	 *		 [ h    0    0   0]
+	 *		 [ 0    h    0   0]
+	 *		 [ 0    0    h   0]
+	 *		 [ 0    0    h   0]
+	 *		 [ 0    0  dh/dz 0]
+	 *		 [ 0    0  dh/dz 0]
+	 *		 [ 0    0  dh/dz 0]
+	 *		 [dh/dz 0  dh/dx 0]
+	 *		 [ 0 dh/dz dh/dy 0]
+	 * 		 [ 0    0    0   h]
+	 * 		 [ 0    0    0   h]
+	 * 		 [ 0    0    0   h]
+	 * where h is the interpolation function for grid i.
+	 */
+
+	int i;
+	const int numgrids2d=3;
+	int num_dof=4;
+
+	double l1l2l3[numgrids2d];
+	double dh1dh6[3][6];
+
+
+	/*Get l1l2l3 in actual coordinate system: */
+	l1l2l3[0]=gauss_coord_tria[0];
+	l1l2l3[1]=gauss_coord_tria[1];
+	l1l2l3[2]=gauss_coord_tria[2];
+
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list,gauss_coord);
+
+	/*Build LprimeStokes: */
+	for (i=0;i<3;i++){
+		*(LprimeStokes+num_dof*numgrids2d*0+num_dof*i)=l1l2l3[i]; //LprimeStokes[0][NDOF2*i]=dh1dh3[0][i];
+		*(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*0+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*1+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+1)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*1+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*2+num_dof*i)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*2+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*3+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+1)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*3+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*4+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+2)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*4+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*5+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+2)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*5+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*6+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+2)=dh1dh6[2][i];
+		*(LprimeStokes+num_dof*numgrids2d*6+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*7+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+2)=dh1dh6[2][i];
+		*(LprimeStokes+num_dof*numgrids2d*7+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*8+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+2)=dh1dh6[2][i];
+		*(LprimeStokes+num_dof*numgrids2d*8+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*9+num_dof*i)=dh1dh6[2][i];
+		*(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+2)=dh1dh6[0][i];
+		*(LprimeStokes+num_dof*numgrids2d*9+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*10+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+1)=dh1dh6[2][i];
+		*(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+2)=dh1dh6[1][i];
+		*(LprimeStokes+num_dof*numgrids2d*10+num_dof*i+3)=0;
+		*(LprimeStokes+num_dof*numgrids2d*11+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*11+num_dof*i+3)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*12+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*12+num_dof*i+3)=l1l2l3[i];
+		*(LprimeStokes+num_dof*numgrids2d*13+num_dof*i)=0;
+		*(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+1)=0;
+		*(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+2)=0;
+		*(LprimeStokes+num_dof*numgrids2d*13+num_dof*i+3)=l1l2l3[i];
+
+	}
+}
+/*}}}*/
+/*FUNCTION GetMatPar {{{1*/
+void* Penta::GetMatPar(){
+
+	/*dynamic objects pointed to by hooks: */
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	matpar=(Matpar*)hmatpar.delivers();
+
+	return matpar;
+}
+/*}}}*/
+/*FUNCTION GetMatrixInvert {{{1*/
+void Penta::GetMatrixInvert(double*  Ke_invert, double* Ke){
+	/*Inverse a 3 by 3 matrix only */
+
+	double a,b,c,d,e,f,g,h,i;
+	double det;
+	int calculationdof=3;
+
+	/*Take the matrix components: */
+	a=*(Ke+calculationdof*0+0);
+	b=*(Ke+calculationdof*0+1);
+	c=*(Ke+calculationdof*0+2);
+	d=*(Ke+calculationdof*1+0);
+	e=*(Ke+calculationdof*1+1);
+	f=*(Ke+calculationdof*1+2);
+	g=*(Ke+calculationdof*2+0);
+	h=*(Ke+calculationdof*2+1);
+	i=*(Ke+calculationdof*2+2);
+
+	det=a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g);
+
+	*(Ke_invert+calculationdof*0+0)=(e*i-f*h)/det;
+	*(Ke_invert+calculationdof*0+1)=(c*h-b*i)/det;
+	*(Ke_invert+calculationdof*0+2)=(b*f-c*e)/det;
+	*(Ke_invert+calculationdof*1+0)=(f*g-d*i)/det;
+	*(Ke_invert+calculationdof*1+1)=(a*i-c*g)/det;
+	*(Ke_invert+calculationdof*1+2)=(c*d-a*f)/det;
+	*(Ke_invert+calculationdof*2+0)=(d*h-e*g)/det;
+	*(Ke_invert+calculationdof*2+1)=(b*g-a*h)/det;
+	*(Ke_invert+calculationdof*2+2)=(a*e-b*d)/det;
+
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctions {{{1*/
+void Penta::GetNodalFunctions(double* l1l6, double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions  at the gaussian point.*/
+
+	l1l6[0]=gauss_coord[0]*(1-gauss_coord[3])/2.0;
+
+	l1l6[1]=gauss_coord[1]*(1-gauss_coord[3])/2.0;
+
+	l1l6[2]=gauss_coord[2]*(1-gauss_coord[3])/2.0;
+
+	l1l6[3]=gauss_coord[0]*(1+gauss_coord[3])/2.0;
+
+	l1l6[4]=gauss_coord[1]*(1+gauss_coord[3])/2.0;
+
+	l1l6[5]=gauss_coord[2]*(1+gauss_coord[3])/2.0;
+
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivatives {{{1*/
+void Penta::GetNodalFunctionsDerivatives(double* dh1dh6,double* xyz_list, double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the actual coordinate system: */
+
+
+	int i;
+	const int NDOF3=3;
+	const int numgrids=6;
+
+	double dh1dh6_ref[NDOF3][numgrids];
+	double Jinv[NDOF3][NDOF3];
+
+	/*Get derivative values with respect to parametric coordinate system: */
+	GetNodalFunctionsDerivativesReference(&dh1dh6_ref[0][0], gauss_coord); 
+
+	/*Get Jacobian invert: */
+	GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);
+
+	/*Build dh1dh3: 
+	 *
+	 * [dhi/dx]= Jinv*[dhi/dr]
+	 * [dhi/dy]       [dhi/ds]
+	 * [dhi/dz]       [dhi/dn]
+	 */
+
+	for (i=0;i<numgrids;i++){
+		*(dh1dh6+numgrids*0+i)=Jinv[0][0]*dh1dh6_ref[0][i]+Jinv[0][1]*dh1dh6_ref[1][i]+Jinv[0][2]*dh1dh6_ref[2][i];
+		*(dh1dh6+numgrids*1+i)=Jinv[1][0]*dh1dh6_ref[0][i]+Jinv[1][1]*dh1dh6_ref[1][i]+Jinv[1][2]*dh1dh6_ref[2][i];
+		*(dh1dh6+numgrids*2+i)=Jinv[2][0]*dh1dh6_ref[0][i]+Jinv[2][1]*dh1dh6_ref[1][i]+Jinv[2][2]*dh1dh6_ref[2][i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivativesStokes {{{1*/
+void Penta::GetNodalFunctionsDerivativesStokes(double* dh1dh7,double* xyz_list, double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the 
+	 * actual coordinate system: */
+
+	int i;
+
+	const  int numgrids=7;
+	double dh1dh7_ref[3][numgrids];
+	double Jinv[3][3];
+
+
+	/*Get derivative values with respect to parametric coordinate system: */
+	GetNodalFunctionsDerivativesReferenceStokes(&dh1dh7_ref[0][0], gauss_coord); 
+
+	/*Get Jacobian invert: */
+	GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_coord);
+
+	/*Build dh1dh6: 
+	 *
+	 * [dhi/dx]= Jinv'*[dhi/dr]
+	 * [dhi/dy]        [dhi/ds]
+	 * [dhi/dz]        [dhi/dzeta]
+	 */
+
+	for (i=0;i<numgrids;i++){
+		*(dh1dh7+numgrids*0+i)=Jinv[0][0]*dh1dh7_ref[0][i]+Jinv[0][1]*dh1dh7_ref[1][i]+Jinv[0][2]*dh1dh7_ref[2][i];
+		*(dh1dh7+numgrids*1+i)=Jinv[1][0]*dh1dh7_ref[0][i]+Jinv[1][1]*dh1dh7_ref[1][i]+Jinv[1][2]*dh1dh7_ref[2][i];
+		*(dh1dh7+numgrids*2+i)=Jinv[2][0]*dh1dh7_ref[0][i]+Jinv[2][1]*dh1dh7_ref[1][i]+Jinv[2][2]*dh1dh7_ref[2][i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivativesReference {{{1*/
+void Penta::GetNodalFunctionsDerivativesReference(double* dl1dl6,double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the 
+	 * natural coordinate system) at the gaussian point. Those values vary along xi,eta,z */
+
+	const int numgrids=6;
+	double A1,A2,A3,z;
+
+	A1=gauss_coord[0]; //first area coordinate value. In term of xi and eta: A1=(1-xi)/2-eta/(2*SQRT3);
+	A2=gauss_coord[1]; //second area coordinate value In term of xi and eta: A2=(1+xi)/2-eta/(2*SQRT3);
+	A3=gauss_coord[2]; //third area coordinate value  In term of xi and eta: A3=y/SQRT3;
+	z=gauss_coord[3]; //fourth vertical coordinate value. Corresponding nodal function: (1-z)/2 and (1+z)/2
+
+
+	/*First nodal function derivatives. The corresponding nodal function is N=A1*(1-z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+0)=-0.5*(1.0-z)/2.0;
+	*(dl1dl6+numgrids*1+0)=-0.5/SQRT3*(1.0-z)/2.0;
+	*(dl1dl6+numgrids*2+0)=-0.5*A1;
+
+	/*Second nodal function: The corresponding nodal function is N=A2*(1-z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+1)=0.5*(1.0-z)/2.0;
+	*(dl1dl6+numgrids*1+1)=-0.5/SQRT3*(1.0-z)/2.0;
+	*(dl1dl6+numgrids*2+1)=-0.5*A2;
+
+	/*Third nodal function: The corresponding nodal function is N=A3*(1-z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+2)=0.0;
+	*(dl1dl6+numgrids*1+2)=1.0/SQRT3*(1.0-z)/2.0;
+	*(dl1dl6+numgrids*2+2)=-0.5*A3;
+
+	/*Fourth nodal function: The corresponding nodal function is N=A1*(1+z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+3)=-0.5*(1.0+z)/2.0;
+	*(dl1dl6+numgrids*1+3)=-0.5/SQRT3*(1.0+z)/2.0;
+	*(dl1dl6+numgrids*2+3)=0.5*A1;
+
+	/*Fifth nodal function: The corresponding nodal function is N=A2*(1+z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+4)=0.5*(1.0+z)/2.0;
+	*(dl1dl6+numgrids*1+4)=-0.5/SQRT3*(1.0+z)/2.0;
+	*(dl1dl6+numgrids*2+4)=0.5*A2;
+
+	/*Sixth nodal function: The corresponding nodal function is N=A3*(1+z)/2. Its derivatives follow*/
+	*(dl1dl6+numgrids*0+5)=0.0;
+	*(dl1dl6+numgrids*1+5)=1.0/SQRT3*(1.0+z)/2.0;
+	*(dl1dl6+numgrids*2+5)=0.5*A3;
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivativesReferenceStokes {{{1*/
+void Penta::GetNodalFunctionsDerivativesReferenceStokes(double* dl1dl7,double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the 
+	 * natural coordinate system) at the gaussian point. */
+
+	int    numgrids=7; //six plus bubble grids
+
+	double r=gauss_coord[1]-gauss_coord[0];
+	double s=-3.0/SQRT3*(gauss_coord[0]+gauss_coord[1]-2.0/3.0);
+	double zeta=gauss_coord[3];
+
+	/*First nodal function: */
+	*(dl1dl7+numgrids*0+0)=-0.5*(1.0-zeta)/2.0;
+	*(dl1dl7+numgrids*1+0)=-SQRT3/6.0*(1.0-zeta)/2.0;
+	*(dl1dl7+numgrids*2+0)=-0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);
+
+	/*Second nodal function: */
+	*(dl1dl7+numgrids*0+1)=0.5*(1.0-zeta)/2.0;
+	*(dl1dl7+numgrids*1+1)=-SQRT3/6.0*(1.0-zeta)/2.0;
+	*(dl1dl7+numgrids*2+1)=-0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);
+
+	/*Third nodal function: */
+	*(dl1dl7+numgrids*0+2)=0;
+	*(dl1dl7+numgrids*1+2)=SQRT3/3.0*(1.0-zeta)/2.0;
+	*(dl1dl7+numgrids*2+2)=-0.5*(SQRT3/3.0*s+ONETHIRD);
+
+	/*Fourth nodal function: */
+	*(dl1dl7+numgrids*0+3)=-0.5*(1.0+zeta)/2.0;
+	*(dl1dl7+numgrids*1+3)=-SQRT3/6.0*(1.0+zeta)/2.0;
+	*(dl1dl7+numgrids*2+3)=0.5*(-0.5*r-SQRT3/6.0*s+ONETHIRD);
+
+	/*Fith nodal function: */
+	*(dl1dl7+numgrids*0+4)=0.5*(1.0+zeta)/2.0;
+	*(dl1dl7+numgrids*1+4)=-SQRT3/6.0*(1.0+zeta)/2.0;
+	*(dl1dl7+numgrids*2+4)=0.5*(0.5*r-SQRT3/6.0*s+ONETHIRD);
+
+	/*Sixth nodal function: */
+	*(dl1dl7+numgrids*0+5)=0;
+	*(dl1dl7+numgrids*1+5)=SQRT3/3.0*(1.0+zeta)/2.0;
+	*(dl1dl7+numgrids*2+5)=0.5*(SQRT3/3.0*s+ONETHIRD);
+
+	/*Seventh nodal function: */
+	*(dl1dl7+numgrids*0+6)=9.0/2.0*r*(1.0+zeta)*(zeta-1.0)*(SQRT3*s+1.0);
+	*(dl1dl7+numgrids*1+6)=9.0/4.0*(1+zeta)*(1-zeta)*(SQRT3*pow(s,2.0)-2.0*s-SQRT3*pow(r,2.0));
+	*(dl1dl7+numgrids*2+6)=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(-2.0*zeta);
+
+}
+/*}}}*/
+/*FUNCTION GetNodalFunctionsStokes {{{1*/
+void Penta::GetNodalFunctionsStokes(double* l1l7, double* gauss_coord){
+
+	/*This routine returns the values of the nodal functions  at the gaussian point.*/
+
+	/*First nodal function: */
+	l1l7[0]=gauss_coord[0]*(1.0-gauss_coord[3])/2.0;
+
+	/*Second nodal function: */
+	l1l7[1]=gauss_coord[1]*(1.0-gauss_coord[3])/2.0;
+
+	/*Third nodal function: */
+	l1l7[2]=gauss_coord[2]*(1.0-gauss_coord[3])/2.0;
+
+	/*Fourth nodal function: */
+	l1l7[3]=gauss_coord[0]*(1.0+gauss_coord[3])/2.0;
+
+	/*Fifth nodal function: */
+	l1l7[4]=gauss_coord[1]*(1.0+gauss_coord[3])/2.0;
+
+	/*Sixth nodal function: */
+	l1l7[5]=gauss_coord[2]*(1.0+gauss_coord[3])/2.0;
+
+	/*Seventh nodal function: */
+	l1l7[6]=27*gauss_coord[0]*gauss_coord[1]*gauss_coord[2]*(1.0+gauss_coord[3])*(1.0-gauss_coord[3]);
+
+}
+/*}}}*/
+/*FUNCTION GetNodes {{{1*/
+void  Penta::GetNodes(void** vpnodes){
+
+	int i;
+	Node** pnodes=NULL;
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	/*virtual object: */
+	pnodes=(Node**)vpnodes;
+
+	for(i=0;i<6;i++){
+		pnodes[i]=nodes[i];
+	}
+}
+/*}}}*/
+/*FUNCTION GetOnBed {{{1*/
+bool Penta::GetOnBed(){
+	
+	bool onbed;
+
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	return onbed;
+}
+/*}}}*/
+/*FUNCTION GetParameterDerivativeValue {{{1*/
+void Penta::GetParameterDerivativeValue(double* p, double* p_list,double* xyz_list, double* gauss_coord){
+
+	/*From grid values of parameter p (p_list[0], p_list[1], p_list[2], p_list[3], p_list[4] and p_list[4]), return parameter derivative value at gaussian point specified by gauss_coord:
+	 *   dp/dx=p_list[0]*dh1/dx+p_list[1]*dh2/dx+p_list[2]*dh3/dx+p_list[3]*dh4/dx+p_list[4]*dh5/dx+p_list[5]*dh6/dx;
+	 *   dp/dy=p_list[0]*dh1/dy+p_list[1]*dh2/dy+p_list[2]*dh3/dy+p_list[3]*dh4/dy+p_list[4]*dh5/dy+p_list[5]*dh6/dy;
+	 *   dp/dz=p_list[0]*dh1/dz+p_list[1]*dh2/dz+p_list[2]*dh3/dz+p_list[3]*dh4/dz+p_list[4]*dh5/dz+p_list[5]*dh6/dz;
+	 *
+	 *   p is a vector of size 3x1 already allocated.
+	 */
+
+	const int NDOF3=3;
+	const int numgrids=6;
+	double dh1dh6[NDOF3][numgrids];
+
+	/*Get dh1dh6 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh6[0][0],xyz_list, gauss_coord);
+
+	*(p+0)=p_list[0]*dh1dh6[0][0]+p_list[1]*dh1dh6[0][1]+p_list[2]*dh1dh6[0][2]+p_list[3]*dh1dh6[0][3]+p_list[4]*dh1dh6[0][4]+p_list[5]*dh1dh6[0][5];
+	;
+	*(p+1)=p_list[0]*dh1dh6[1][0]+p_list[1]*dh1dh6[1][1]+p_list[2]*dh1dh6[1][2]+p_list[3]*dh1dh6[1][3]+p_list[4]*dh1dh6[1][4]+p_list[5]*dh1dh6[1][5];
+
+	*(p+2)=p_list[0]*dh1dh6[2][0]+p_list[1]*dh1dh6[2][1]+p_list[2]*dh1dh6[2][2]+p_list[3]*dh1dh6[2][3]+p_list[4]*dh1dh6[2][4]+p_list[5]*dh1dh6[2][5];
+
+}
+/*}}}*/
+/*FUNCTION GetParameterValue {{{1*/
+void Penta::GetParameterValue(double* pvalue, double* v_list,double* gauss_coord){
+
+	const int numgrids=6;
+	double l1l6[numgrids];
+
+	GetNodalFunctions(&l1l6[0], gauss_coord);
+
+	*pvalue=l1l6[0]*v_list[0]+l1l6[1]*v_list[1]+l1l6[2]*v_list[2]+l1l6[3]*v_list[3]+l1l6[4]*v_list[4]+l1l6[5]*v_list[5];
+}
+/*}}}*/
+/*FUNCTION 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=2*pow(epsilon_eff,2.0)*viscosity;
+}
+/*}}}*/
+/*FUNCTION GetShelf {{{1*/
+bool   Penta::GetShelf(){
+	bool onshelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onshelf,ElementOnIceShelfEnum);
+
+	return onshelf;
+}
+/*}}}*/
+/*FUNCTION GetStrainRate {{{1*/
+void Penta::GetStrainRate(double* epsilon, double* velocity, double* xyz_list, double* gauss_coord){
+
+	int i;
+	const int numgrids=6;
+	const int NDOF2=2;
+
+	double B[5][NDOF2*numgrids];
+
+	/*Get B matrix: */
+	GetB(&B[0][0], xyz_list, gauss_coord);
+
+	/*Multiply B by velocity, to get strain rate: */
+	MatrixMultiply( &B[0][0],5,NDOF2*numgrids,0,
+				velocity,NDOF2*numgrids,1,0,
+				epsilon,0);
+
+}
+/*}}}*/
+/*FUNCTION GetStrainRateStokes {{{1*/
+void Penta::GetStrainRateStokes(double* epsilon, double* velocity, double* xyz_list, double* gauss_coord){
+
+	int i,j;
+
+	const int numgrids=6;
+	const int DOFVELOCITY=3;
+	double B[8][27];
+	double B_reduced[numgrids][DOFVELOCITY*numgrids];
+
+	/*Get B matrix: */
+	GetBStokes(&B[0][0], xyz_list, gauss_coord);
+
+	/*Create a reduced matrix of B to get rid of pressure */
+	for (i=0;i<6;i++){
+		for (j=0;j<3;j++){
+			B_reduced[i][j]=B[i][j];
+		}
+		for (j=4;j<7;j++){
+			B_reduced[i][j-1]=B[i][j];
+		}
+		for (j=8;j<11;j++){
+			B_reduced[i][j-2]=B[i][j];
+		}
+		for (j=12;j<15;j++){
+			B_reduced[i][j-3]=B[i][j];
+		}
+		for (j=16;j<19;j++){
+			B_reduced[i][j-4]=B[i][j];
+		}
+		for (j=20;j<23;j++){
+			B_reduced[i][j-5]=B[i][j];
+		}
+	}
+	/*Multiply B by velocity, to get strain rate: */
+	MatrixMultiply( &B_reduced[0][0],6,DOFVELOCITY*numgrids, 0, velocity,DOFVELOCITY*numgrids,1,0,epsilon, 0);
+}
+/*}}}*/
+/*FUNCTION GetThicknessList {{{1*/
+void Penta::GetThicknessList(double* thickness_list){
+
+	const int numgrids=6;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0,0},{0,1,0,0},{0,0,1,0},{1,0,0,1},{0,1,0,1},{0,0,1,1}};
+	inputs->GetParameterValues(thickness_list,&gaussgrids[0][0],6,ThicknessEnum);
+
+}
+/*}}}*/
+/*FUNCTION Gradj {{{1*/
+void  Penta::Gradj(Vec grad_g,int analysis_type,int sub_analysis_type,char* control_type){
+
+	/*inputs: */
+	bool onwater;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, skip grad (=0): */
+	if(onwater)return;
+
+	if (strcmp(control_type,"drag")==0){
+		GradjDrag( grad_g,analysis_type,sub_analysis_type);
+	}
+	else if (strcmp(control_type,"B")==0){
+		GradjB( grad_g, analysis_type,sub_analysis_type);
+	}
+	else ISSMERROR("%s%s","control type not supported yet: ",control_type);
+}
+/*}}}*/
+/*FUNCTION GradjDrag {{{1*/
+void  Penta::GradjDrag(Vec grad_g,int analysis_type,int sub_analysis_type){
+
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool onbed;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	/*If on shelf, skip: */
+	if(shelf)return;
+
+	/*Bail out if this element does not touch the bedrock: */
+	if (!onbed) return;
+
+	if (sub_analysis_type==HorizAnalysisEnum){
+
+		/*MacAyeal or Pattyn*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->GradjDrag( grad_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else if (sub_analysis_type==StokesAnalysisEnum){
+
+		/*Stokes*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria.
+		tria->GradjDragStokes( grad_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+}
+/*}}}*/
+/*FUNCTION GradjB {{{1*/
+void  Penta::GradjB(Vec grad_g,int analysis_type,int sub_analysis_type){
+
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	/*If on water, skip: */
+	if(onwater)return;
+
+	if (collapse){
+		/*Bail out element if collapsed (2d) and not on bed*/
+		if (!onbed) return;
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute gardj*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		tria->GradjB(grad_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+	else{
+		/*B is a 2d field, use MacAyeal(2d) gradient even if it is Stokes or Pattyn*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		tria->GradjB(grad_g,analysis_type,sub_analysis_type);
+		delete tria;
+		return;
+	}
+}
+/*}}}*/
+/*FUNCTION MassFlux {{{1*/
+double Penta::MassFlux( double* segment,double* ug){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Misfit {{{1*/
+double Penta::Misfit(int analysis_type,int sub_analysis_type){
+
+	double J;
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onsurface;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/*Bail out if this element if:
+	 * -> Non collapsed and not on the surface
+	 * -> collapsed (2d model) and not on bed) */
+	if ((!collapse && !onsurface) || (collapse && !onbed)){
+		return 0;
+	}
+	else if (collapse){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute Misfit*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		J=tria->Misfit(analysis_type,sub_analysis_type);
+		delete tria;
+		return J;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).
+		J=tria->Misfit(analysis_type,sub_analysis_type);
+		delete tria;
+		return J;
+	}
+}
+/*}}}*/
+/*FUNCTION MyRank {{{1*/
+int    Penta::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION ReduceMatrixStokes {{{1*/
+void Penta::ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp){
+
+	int i,j;
+
+	double Kii[24][24];
+	double Kib[24][3];
+	double Kbb[3][3];
+	double Kbi[3][24];
+	double Kbbinv[3][3];
+	double KibKbbinv[24][3];
+	double Kright[24][24];
+
+	/*Create the four matrices used for reduction */
+	for(i=0;i<24;i++){
+		for(j=0;j<24;j++){
+			Kii[i][j]=*(Ke_temp+27*i+j);
+		}
+		for(j=0;j<3;j++){
+			Kib[i][j]=*(Ke_temp+27*i+j+24);
+		}
+	}
+	for(i=0;i<3;i++){
+		for(j=0;j<24;j++){
+			Kbi[i][j]=*(Ke_temp+27*(i+24)+j);
+		}
+		for(j=0;j<3;j++){
+			Kbb[i][j]=*(Ke_temp+27*(i+24)+j+24);
+		}
+	}
+
+	/*Inverse the matrix corresponding to bubble part Kbb */
+	GetMatrixInvert(&Kbbinv[0][0], &Kbb[0][0]);
+
+	/*Multiply matrices to create the reduce matrix Ke_reduced */
+	MatrixMultiply(&Kib[0][0],24,3,0,&Kbbinv[0][0],3,3,0,&KibKbbinv[0][0],0);
+	MatrixMultiply(&KibKbbinv[0][0],24,3,0,&Kbi[0][0],3,24,0,&Kright[0][0],0);
+
+	/*Affect value to the reduced matrix */
+	for(i=0;i<24;i++){
+		for(j=0;j<24;j++){
+			*(Ke_reduced+24*i+j)=Kii[i][j]-Kright[i][j];
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION ReduceVectorStokes {{{1*/
+void Penta::ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp){
+
+	int i,j;
+
+	double Pi[24];
+	double Pb[3];
+	double Kbb[3][3];
+	double Kib[24][3];
+	double Kbbinv[3][3];
+	double KibKbbinv[24][3];
+	double Pright[24];
+
+	/*Create the four matrices used for reduction */
+	for(i=0;i<24;i++){
+		Pi[i]=*(Pe_temp+i);
+	}
+	for(i=0;i<3;i++){
+		Pb[i]=*(Pe_temp+i+24);
+	}
+	for(j=0;j<3;j++){
+		for(i=0;i<24;i++){
+			Kib[i][j]=*(Ke_temp+3*i+j);
+		}
+		for(i=0;i<3;i++){
+			Kbb[i][j]=*(Ke_temp+3*(i+24)+j);
+		}
+	}
+
+	/*Inverse the matrix corresponding to bubble part Kbb */
+	GetMatrixInvert(&Kbbinv[0][0], &Kbb[0][0]);
+
+	/*Multiply matrices to create the reduce matrix Ke_reduced */
+	MatrixMultiply(&Kib[0][0],24,3,0,&Kbbinv[0][0],3,3,0,&KibKbbinv[0][0],0);
+	MatrixMultiply(&KibKbbinv[0][0],24,3,0,&Pb[0],3,1,0,&Pright[0],0);
+
+	/*Affect value to the reduced matrix */
+	for(i=0;i<24;i++){
+		*(Pe_reduced+i)=Pi[i]-Pright[i];
+	}
+}
+/*}}}*/
+/*FUNCTION SetClone {{{1*/
+void  Penta::SetClone(int* minranks){
+
+	ISSMERROR("not implemented yet");
+}
+/*}}}1*/
+/*FUNCTION SurfaceArea {{{1*/
+double Penta::SurfaceArea(int analysis_type,int sub_analysis_type){
+
+	double S;
+	Tria* tria=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool collapse;
+	bool onsurface;
+	bool onbed;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&collapse,CollapseEnum);
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+	inputs->GetParameterValue(&onsurface,ElementOnSurfaceEnum);
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/*Bail out if this element if:
+	 * -> Non collapsed and not on the surface
+	 * -> collapsed (2d model) and not on bed) */
+	if ((!collapse && !onsurface) || (collapse && !onbed)){
+		return 0;
+	}
+	else if (collapse){
+
+		/*This element should be collapsed into a tria element at its base. Create this tria element, 
+		 * and compute SurfaceArea*/
+		tria=(Tria*)SpawnTria(0,1,2); //grids 0, 1 and 2 make the new tria (lower face).
+		S=tria->SurfaceArea(analysis_type,sub_analysis_type);
+		delete tria;
+		return S;
+	}
+	else{
+
+		tria=(Tria*)SpawnTria(3,4,5); //grids 3, 4 and 5 make the new tria (upper face).
+		S=tria->SurfaceArea(analysis_type,sub_analysis_type);
+		delete tria;
+		return S;
+	}
+}
+/*}}}*/
+/*FUNCTION SurfaceNormal {{{1*/
+void Penta::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
+
+	int i;
+	double v13[3];
+	double v23[3];
+	double normal[3];
+	double normal_norm;
+
+	for (i=0;i<3;i++){
+		v13[i]=xyz_list[0][i]-xyz_list[2][i];
+		v23[i]=xyz_list[1][i]-xyz_list[2][i];
+	}
+
+	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
+	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
+	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
+
+	normal_norm=sqrt( pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2) );
+
+	*(surface_normal)=normal[0]/normal_norm;
+	*(surface_normal+1)=normal[1]/normal_norm;
+	*(surface_normal+2)=normal[2]/normal_norm;
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Elements/Penta.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Penta.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Penta.h	(revision 3683)
@@ -0,0 +1,148 @@
+/*! \file Penta.h 
+ *  \brief: header file for penta object
+ */
+
+#ifndef _PENTA_H
+#define _PENTA_H
+
+/*Headers:*/
+/*{{{1*/
+
+#include "../Elements/Element.h"
+class  Object;
+class  Hook;
+class  Parameters;
+class  Inputs;
+
+class IoModel;
+
+#include "../../shared/Exceptions/exceptions.h"
+#include "../../include/macros.h"
+
+/*}}}*/
+
+class Penta: public Element{
+
+	public:
+
+		int id;
+		Hook hnodes;  //hook to 6 nodes
+		Hook hmatice; //hook to 1 matice
+		Hook hmatpar; //hook to 1 matpar
+
+		Parameters* parameters; //pointer to solution parameters
+		Inputs* inputs;
+
+		/*FUNCTION constructors, destructors {{{1*/
+		Penta();
+		Penta(int penta_id,int* penta_node_ids, int penta_matice_id, int penta_matpar_id);
+		Penta(int penta_id,Hook* penta_hnodes, Hook* penta_hmatice, Hook* penta_hmatpar, Parameters* penta_parameters, Inputs* inputs);
+		Penta(int penta_id,int i, IoModel* iomodel);
+		~Penta();
+		/*}}}*/
+		/*FUNCTION object management {{{1*/
+		void  Configure(DataSet* loads,DataSet* nodes,DataSet* materials,Parameters* parameters);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		void*  SpawnTria(int g0, int g1, int g2);
+		void  SetClone(int* minranks);
+
+		/*}}}*/
+		/*FUNCTION element numerical routines {{{1*/
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixDiagnosticHoriz( Mat Kgg,  int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixDiagnosticVert( Mat Kgg,  int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  GetDofList1(int* doflist);
+		void* GetMatPar();
+		bool   GetShelf();
+		void  GetNodes(void** nodes);
+		bool   GetOnBed();
+		void  Du(Vec du_g,int analysis_type,int sub_analysis_type);
+		void  Gradj(Vec grad_g,int analysis_type,int sub_analysis_type,char* control_type);
+		void  GradjDrag(Vec grad_g,int analysis_type,int sub_analysis_type);
+		void  GradjB(Vec grad_g,int analysis_type,int sub_analysis_type);
+		double Misfit(int analysis_type,int sub_analysis_type);
+		double SurfaceArea(int analysis_type,int sub_analysis_type);
+		double CostFunction(int analysis_type,int sub_analysis_type);
+		
+		void          GetThicknessList(double* thickness_list);
+		void          GetBedList(double* bed_list);
+
+		void  GetStrainRate(double* epsilon, double* velocity, double* xyz_list, double* gauss_coord);
+		void  GetB(double* pB, double* xyz_list, double* gauss_coord);
+		void  GetBPrime(double* B, double* xyz_list, double* gauss_coord);
+		void  GetB_vert(double* B, double* xyz_list, double* gauss_coord);
+		void  GetBPrime_vert(double* B, double* xyz_list, double* gauss_coord);
+		void  GetJacobianDeterminant(double*  Jdet, double* xyz_list,double* gauss_coord);
+		void  GetNodalFunctionsDerivatives(double* dh1dh6,double* xyz_list, double* gauss_coord);
+		void  GetJacobian(double* J, double* xyz_list,double* gauss_coord);
+		void  GetNodalFunctionsDerivativesReference(double* dl1dl6,double* gauss_coord);
+		void  GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_coord);
+		void  CreatePVectorDiagnosticHoriz( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticVert( Vec pg, int analysis_type,int sub_analysis_type);
+		void  GetParameterValue(double* pvalue, double* v_list,double* gauss_coord);
+		void  GetParameterDerivativeValue(double* p, double* p_list,double* xyz_list, double* gauss_coord);
+		void  GetNodalFunctions(double* l1l6, double* gauss_coord);
+		void  FieldExtrude(Vec field,double* field_serial,char* field_name, int iscollapsed);
+		void  ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type);
+		void  ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type);
+		void  ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixSlopeCompute(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorSlopeCompute( Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixPrognostic(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorPrognostic( Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBalancedthickness(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBalancedvelocities(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixDiagnosticStokes( Mat Kgg,  int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBalancedthickness( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBalancedvelocities( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticStokes( Vec pg, int analysis_type,int sub_analysis_type);
+		void  ReduceMatrixStokes(double* Ke_reduced, double* Ke_temp);
+		void  GetMatrixInvert(double*  Ke_invert, double* Ke);
+		void  SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+		void  GetStrainRateStokes(double* epsilon, double* velocity, double* xyz_list, double* gauss_coord);
+		void  GetBStokes(double* B, double* xyz_list, double* gauss_coord);
+		void  GetBprimeStokes(double* B_prime, double* xyz_list, double* gauss_coord);
+		void  GetLStokes(double* LStokes, double* gauss_coord_tria);
+		void  GetLprimeStokes(double* LprimeStokes, double* xyz_list, double* gauss_coord_tria, double* gauss_coord);
+		void  GetNodalFunctionsDerivativesStokes(double* dh1dh7,double* xyz_list, double* gauss_coord);
+		void  GetNodalFunctionsDerivativesReferenceStokes(double* dl1dl7,double* gauss_coord);
+		void  ReduceVectorStokes(double* Pe_reduced, double* Ke_temp, double* Pe_temp);
+		void  GetNodalFunctionsStokes(double* l1l7, double* gauss_coord);
+		void  CreateKMatrixThermal(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  GetB_conduct(double* B_conduct, double* xyz_list, double* gauss_coord);
+		void  GetB_advec(double* B_advec, double* xyz_list, double* gauss_coord);
+		void  GetBprime_advec(double* Bprime_advec, double* xyz_list, double* gauss_coord);
+		void  GetB_artdiff(double* B_artdiff, double* xyz_list, double* gauss_coord);
+		void  CreateKMatrixMelting(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorThermal( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorMelting( Vec pg, int analysis_type,int sub_analysis_type);
+		void  GetPhi(double* phi, double*  epsilon, double viscosity);
+		double MassFlux(double* segment,double* ug);
+
+		/*updates: */
+		void  UpdateFromDakota(void* inputs);
+		void  UpdateInputs(double* solution, int analysis_type, int sub_analysis_type);
+		void  UpdateInputsDiagnosticHoriz( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsSlopeCompute( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsPrognostic( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsPrognostic2(double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedthickness( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedthickness2( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedvelocities( double* solution,int analysis_type,int sub_analysis_type);
+		void AddInput(double value, int enum_type){ISSMERROR("not supporte yet!");}
+
+		/*}}}*/
+
+
+};
+#endif  /* _PENTA_H */
Index: /issm/trunk/src/c/objects/Elements/Sing.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Sing.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Sing.cpp	(revision 3683)
@@ -0,0 +1,538 @@
+/*!\file Sing.c
+ * \brief: implementation of the Sing object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION Sing::Sing(){{{1*/
+Sing::Sing(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+	return;
+}
+/*}}}*/
+/*FUNCTION Sing::Sing(int sing_id,int* sing_node_ids, int sing_matice_id, int sing_matpar_id, int sing_numpar_id) {{{1*/
+Sing::Sing(int sing_id,int* sing_node_ids, int sing_matice_id, int sing_matpar_id):
+	hnodes(sing_node_ids,1),
+	hmatice(&sing_matice_id,1),
+	hmatpar(&sing_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=sing_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Sing::Sing(int sing_id,Hook* sing_hnodes, Hook* sing_hmatice, Hook* sing_hmatpar, Hook* sing_hnumpar, Inputs* sing_inputs) {{{1*/
+Sing::Sing(int sing_id,Hook* sing_hnodes, Hook* sing_hmatice, Hook* sing_hmatpar, Parameters* sing_parameters,Inputs* sing_inputs):
+	hnodes(sing_hnodes),
+	hmatice(sing_hmatice),
+	hmatpar(sing_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=sing_id;
+	if(sing_inputs){
+		this->inputs=(Inputs*)sing_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=sing_parameters;
+}
+/*}}}*/
+/*FUNCTION Sing::Sing(int sing_id, int i, IoModel* iomodel) {{{1*/
+Sing::Sing(int sing_id, int i, IoModel* iomodel){
+
+	int sing_matice_id;
+	int sing_matpar_id;
+	
+	int sing_g;
+	double sing_h;
+	double sing_k;
+
+	/*id: */
+	this->id=sing_id;
+
+	/*hooks: */
+	sing_matice_id=i+1;                        //refers to the corresponding material property card
+	sing_matpar_id=iomodel->numberofvertices+1;//refers to the corresponding matpar property card
+	sing_g=i+1;
+
+	this->hnodes.Init(&sing_g,1);
+	this->hmatice.Init(&sing_matice_id,1);
+	this->hmatpar.Init(&sing_matpar_id,1);
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+
+	if (iomodel->thickness) this->inputs->AddInput(new SingVertexInput(ThicknessEnum,iomodel->thickness[i]));
+	if (iomodel->drag_coefficient) this->inputs->AddInput(new SingVertexInput(DragCoefficientEnum,iomodel->drag_coefficient[i]));
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+
+}
+/*}}}*/
+/*FUNCTION Sing::~Sing(){{{1*/
+Sing::~Sing(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION Sing::Configure {{{1*/
+void  Sing::Configure(DataSet* loadsin, DataSet* nodesin, DataSet* materialsin, Parameters* parametersin){
+
+	int i;
+	
+	/*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: */
+	hnodes.configure(nodesin);
+	hmatice.configure(materialsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION Sing::copy {{{1*/
+Object* Sing::copy() {
+	
+	return new Sing(this->id,&this->hnodes,&this->hmatice,&this->hmatpar,this->parameters,this->inputs);
+
+}
+/*}}}*/
+/*FUNCTION Sing::DeepEcho {{{1*/
+void Sing::DeepEcho(void){
+
+	printf("Sing:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	hmatice.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Sing::Demarshall {{{1*/
+void  Sing::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	hmatice.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Sing::Echo{{{1*/
+
+void Sing::Echo(void){
+
+	printf("Sing:\n");
+	printf("   id: %i\n",id);
+	hnodes.Echo();
+	hmatice.Echo();
+	hmatpar.Echo();
+	printf("   parameters\n");
+	parameters->Echo();
+	printf("   inputs\n");
+	inputs->Echo();
+}
+/*}}}*/
+/*FUNCTION Sing::Marshall {{{1*/
+void  Sing::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Sing: */
+	enum_type=SingEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Sing data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+	
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	hmatice.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Sing::MashallSize {{{1*/
+int   Sing::MarshallSize(){
+
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+hmatice.MarshallSize()
+		+hmatpar.MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Sing::UpdateInputs {{{1*/
+void  Sing::UpdateInputs(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+		
+/*Object functions*/
+/*FUNCTION Sing::ComputeBasalStress {{{1*/
+void  Sing::ComputeBasalStress(Vec p_g,int analysis_type,int sub_analysis_type){
+
+	ISSMERROR("Not implemented yet");
+
+}
+/*}}}*/
+/*FUNCTION Sing::ComputePressure {{{1*/
+void  Sing::ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type){
+
+	int    dof;
+	double pressure;
+	double thickness;
+	double rho_ice,g;
+
+	/*dynamic objects pointed to by hooks: */
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*Get dof list on which we will plug the pressure values: */
+	GetDofList1(&dof);
+
+	/*recover objects from hooks: */
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*pressure is lithostatic: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+	inputs->GetParameterValue(&thickness,ThicknessEnum);
+	pressure=rho_ice*g*thickness;
+	
+	/*plug local pressure values into global pressure vector: */
+	VecSetValue(p_g,dof,pressure,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Sing::ComputeStrainRate {{{1*/
+void  Sing::ComputeStrainRate(Vec p_g,int analysis_type,int sub_analysis_type){
+
+	ISSMERROR("Not implemented yet");
+
+}
+/*}}}*/
+/*FUNCTION Sing::CostFunction {{{1*/
+double Sing::CostFunction( int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::CreateKMatrix {{{1*/
+
+void  Sing::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	if ((analysis_type==DiagnosticAnalysisEnum) && (sub_analysis_type==HutterAnalysisEnum)){
+
+		CreateKMatrixDiagnosticHutter( Kgg,analysis_type,sub_analysis_type);
+
+	}
+	else{
+		ISSMERROR("%s%i%s%i%s\n","analysis: ",analysis_type," and sub_analysis_type: ",sub_analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Sing::CreateKMatrixDiagnosticHutter {{{1*/
+
+void  Sing::CreateKMatrixDiagnosticHutter(Mat Kgg,int analysis_type,int sub_analysis_type){
+	
+	const int numgrids=1;
+	const int NDOF2=2;
+	const int numdofs=numgrids*NDOF2;
+	double Ke_gg[numdofs][numdofs]={{1,0},{0,1}};
+	int    doflist[numdofs];
+	int    numberofdofspernode;
+
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	MatSetValues(Kgg,numdofs,doflist,numdofs,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Sing::CreatePVector {{{1*/
+void  Sing::CreatePVector(Vec pg,int analysis_type,int sub_analysis_type){
+	
+	/*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
+	if ((analysis_type==DiagnosticAnalysisEnum) && (sub_analysis_type==HutterAnalysisEnum)){
+	
+			CreatePVectorDiagnosticHutter( pg,analysis_type,sub_analysis_type);
+
+	}
+	else{
+		ISSMERROR("%s%i%s"," analysis ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Sing::CreatePVectorDiagnosticHutter {{{1*/
+
+void Sing::CreatePVectorDiagnosticHutter( Vec pg,  int analysis_type,int sub_analysis_type){
+	
+	
+	const int numgrids=1;
+	const int NDOF2=2;
+	const int numdofs=NDOF2*numgrids;
+	int       doflist[numdofs];
+	int       dofs[1]={0};
+	int       found=0;
+	double    slope[2];
+	double    slope2;
+	double    pe_g[numdofs]={0,0};
+	double    ub,vb;
+	double    constant_part;
+	int       numberofdofspernode;
+	double    rho_ice,gravity,n,B;
+	double    thickness;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  node=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	node=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	inputs->GetParameterValue(&slope[0],SurfaceSlopexEnum);
+	inputs->GetParameterValue(&slope[1],SurfaceSlopeyEnum);
+
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//compute slope2 
+	slope2=pow(slope[0],2)+pow(slope[1],2);
+
+	//compute ub
+	rho_ice=matpar->GetRhoIce();
+	gravity=matpar->GetG();
+	n=matice->GetN();
+	B=matice->GetB();
+	inputs->GetParameterValue(&thickness,ThicknessEnum);
+
+	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];
+
+	//compute constant_part
+	constant_part=-2*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2));
+
+	pe_g[0]=ub-2.0*pow(rho_ice*gravity,n)*pow(slope2,((n-1)/2.0))*pow(thickness,n)/(pow(B,n)*(n+1))*slope[0];
+	pe_g[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];
+
+	VecSetValues(pg,numdofs,doflist,(const double*)pe_g,ADD_VALUES);
+
+
+}
+/*}}}*/
+/*FUNCTION Sing::Du {{{1*/
+void  Sing::Du(Vec,int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::Enum {{{1*/
+int Sing::Enum(void){
+
+	return SingEnum;
+
+}
+/*}}}*/
+/*FUNCTION Sing::GetBedList {{{1*/
+void  Sing::GetBedList(double*){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::GetDofList {{{1*/
+void  Sing::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+	
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	nodes[0]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+	for(i=0;i<numberofdofspernode;i++){
+		doflist[i]=doflist_per_node[i];
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION Sing::GetDofList1 {{{1*/
+void  Sing::GetDofList1(int* doflist){
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	int i;
+	doflist[0]=nodes[0]->GetDofList1();
+
+}
+/*}}}*/
+/*FUNCTION Sing::Id {{{1*/
+int    Sing::Id(void){ return id; }
+/*}}}*/
+/*FUNCTION Sing::GetMatPar {{{1*/
+void* Sing::GetMatPar(){
+
+	/*dynamic objects pointed to by hooks: */
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	matpar=(Matpar*)hmatpar.delivers();
+
+	return matpar;
+}
+/*}}}*/
+/*FUNCTION Sing::GetNodes {{{1*/
+void  Sing::GetNodes(void** vpnodes){
+	
+	Node** pnodes=NULL;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	
+	/*recover nodes: */
+	pnodes=(Node**)vpnodes;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	pnodes[0]=nodes[0];
+}
+/*}}}*/
+/*FUNCTION Sing::GetOnBed {{{1*/
+bool   Sing::GetOnBed(){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::GetShelf {{{1*/
+bool   Sing::GetShelf(){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::GetThicknessList {{{1*/
+void  Sing::GetThicknessList(double* thickness_list){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::Gradj {{{1*/
+void  Sing::Gradj(Vec,  int, int ,char*){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::GradB {{{1*/
+void  Sing::GradjB(Vec,  int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::GradjDrag {{{1*/
+void  Sing::GradjDrag(Vec,  int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::MassFlux {{{1*/
+double Sing::MassFlux( double* segment,double* ug){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::Misfit {{{1*/
+double Sing::Misfit( int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::MyRank {{{1*/
+int    Sing::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Sing::SurfaceArea {{{1*/
+double Sing::SurfaceArea( int,int){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Sing::SetClone {{{1*/
+void  Sing::SetClone(int* minranks){
+
+	ISSMERROR("not implemented yet");
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Elements/Sing.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Sing.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Sing.h	(revision 3683)
@@ -0,0 +1,91 @@
+/*!\file: Sing.h
+ * \brief prototypes for Sing element
+ */ 
+
+#ifndef _SING_H_
+#define  _SING_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Element.h"
+class Hook;
+class Parameters;
+class Inputs;
+class IoModel;
+
+#include "../../include/macros.h"
+#include "../../shared/Exceptions/exceptions.h"
+
+/*}}}*/
+
+class Sing: public Element{
+
+	public:
+
+		/*ids:*/
+		int id;
+
+		Hook hnodes;  //hook to 2 nodes
+		Hook hmatice; //hook to 1 matice
+		Hook hmatpar; //hook to 1 matpar
+		
+		Parameters* parameters; //pointer to solution parameters
+		Inputs* inputs;
+
+
+		/*constructors, destructors: {{{1*/
+		Sing();
+		Sing(int sing_id,int* sing_node_ids, int sing_matice_id, int sing_matpar_id);
+		Sing(int sing_id,Hook* sing_hnodes, Hook* sing_hmatice, Hook* sing_hmatpar, Parameters* sing_parameters,Inputs* sing_inputs);
+		Sing(int sing_id, int i, IoModel* iomodel);
+		~Sing();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  Configure(DataSet* loads,DataSet* nodes,DataSet* materials,Parameters* parameters);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  SetClone(int* minranks);
+		int   MyRank();
+		/*}}}*/
+		/*numerics: {{{1*/
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+		void  UpdateInputs(double* solution, int analysis_type, int sub_analysis_type);
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  GetDofList1(int* doflist);
+		void  CreateKMatrixDiagnosticHutter(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3);
+		void  CreatePVectorDiagnosticHutter(Vec pg,int analysis_type,int sub_analysis_type);
+		void* GetMatPar();
+		void  ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type);
+		void  ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type);
+		void  ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type);
+		void  GetNodes(void** vpnodes);
+		/*}}}*/
+		/*not implemented: {{{1*/
+		bool   GetShelf();
+		bool   GetOnBed();
+		void  GetBedList(double*);
+		void  GetThicknessList(double* thickness_list);
+		void  Du(Vec,int,int);
+		void  Gradj(Vec, int, int,char*);
+		void  GradjDrag(Vec , int,int);
+		void  GradjB(Vec,  int,int);
+		double Misfit(int,int);
+		double SurfaceArea(int,int);
+		double CostFunction(int,int);
+		double MassFlux(double* segment,double* ug);
+		void AddInput(double value, int enum_type){ISSMERROR("not supporte yet!");}
+		/*}}}*/
+
+
+
+};
+#endif //ifndef _SING_H_
+
Index: /issm/trunk/src/c/objects/Elements/Tria.cpp
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Tria.cpp	(revision 3683)
@@ -0,0 +1,5109 @@
+/*!\file Tria.c
+ * \brief: implementation of the Tria object
+ */
+
+/*Headers:*/
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION Tria::Tria(){{{1*/
+Tria::Tria(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Tria::Tria(int id, int* node_ids, int matice_id, int matpar_id){{{1*/
+Tria::Tria(int tria_id,int* tria_node_ids, int tria_matice_id, int tria_matpar_id): 
+	hnodes(tria_node_ids,3),
+	hmatice(&tria_matice_id,1),
+	hmatpar(&tria_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=tria_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+}
+/*}}}*/
+/*FUNCTION Tria::Tria(int id, Hook* hnodes, Hook* hmatice, Hook* hmatpar, Parameters* parameters, Inputs* tria_inputs) {{{1*/
+Tria::Tria(int tria_id,Hook* tria_hnodes, Hook* tria_hmatice, Hook* tria_hmatpar, Parameters* tria_parameters, Inputs* tria_inputs):
+	hnodes(tria_hnodes),
+	hmatice(tria_hmatice),
+	hmatpar(tria_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=tria_id;
+	if(tria_inputs){
+		this->inputs=(Inputs*)tria_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=tria_parameters;
+}
+/*}}}*/
+/*FUNCTION Tria::Tria(int id, int index, IoModel* iomodel){{{1*/
+Tria::Tria(int tria_id, int index, IoModel* iomodel){ //i is the element index
+
+	int    i;
+	int    j;
+	int    tria_node_ids[3];
+	int    tria_matice_id;
+	int    tria_matpar_id;
+	double nodeinputs[3];
+
+	/*id: */
+	this->id=tria_id;
+	
+	/*hooks: */
+	//go recover node ids, needed to initialize the node hook.
+	if (iomodel->analysis_type==Prognostic2AnalysisEnum || iomodel->analysis_type==Balancedthickness2AnalysisEnum){
+		/*Discontinuous Galerkin*/
+		tria_node_ids[0]=3*index+1;
+		tria_node_ids[1]=3*index+2;
+		tria_node_ids[2]=3*index+3;
+	}
+	else{
+		/*Continuous Galerkin*/
+		for(i=0;i<3;i++){ 
+			tria_node_ids[i]=(int)*(iomodel->elements+3*index+i); //ids for vertices are in the elements array from Matlab
+		}
+	}
+	tria_matice_id=index+1; //refers to the corresponding ice material object
+	tria_matpar_id=iomodel->numberofelements+1; //refers to the constant material parameters object
+
+	this->hnodes.Init(tria_node_ids,3);
+	this->hmatice.Init(&tria_matice_id,1);
+	this->hmatpar.Init(&tria_matpar_id,1);
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+	
+	if (iomodel->thickness) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->thickness[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(ThicknessEnum,nodeinputs));
+	}
+	if (iomodel->surface) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->surface[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(SurfaceEnum,nodeinputs));
+	}
+	if (iomodel->bed) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->bed[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(BedEnum,nodeinputs));
+	}
+	if (iomodel->drag_coefficient) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->drag_coefficient[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(DragCoefficientEnum,nodeinputs));
+
+		if (iomodel->drag_p) this->inputs->AddInput(new DoubleInput(DragPEnum,iomodel->drag_p[index]));
+		if (iomodel->drag_q) this->inputs->AddInput(new DoubleInput(DragQEnum,iomodel->drag_q[index]));
+		this->inputs->AddInput(new IntInput(DragTypeEnum,iomodel->drag_type));
+
+	}
+	if (iomodel->melting_rate) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->melting_rate[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(MeltingRateEnum,nodeinputs));
+	}
+	if (iomodel->accumulation_rate) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->accumulation_rate[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(AccumulationRateEnum,nodeinputs));
+	}
+	if (iomodel->geothermalflux) {
+		for(i=0;i<3;i++)nodeinputs[i]=iomodel->geothermalflux[tria_node_ids[i]-1];
+		this->inputs->AddInput(new TriaVertexInput(GeothermalFluxEnum,nodeinputs));
+	}	
+
+	if (iomodel->elementoniceshelf) this->inputs->AddInput(new BoolInput(ElementOnIceShelfEnum,(IssmBool)iomodel->elementoniceshelf[index]));
+	if (iomodel->elementonbed) this->inputs->AddInput(new BoolInput(ElementOnBedEnum,(IssmBool)iomodel->elementonbed[index]));
+	if (iomodel->elementonwater) this->inputs->AddInput(new BoolInput(ElementOnWaterEnum,(IssmBool)iomodel->elementonwater[index]));
+	if (iomodel->elementonsurface) this->inputs->AddInput(new BoolInput(ElementOnSurfaceEnum,(IssmBool)iomodel->elementonsurface[index]));
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+
+
+}
+/*}}}*/
+/*FUNCTION Tria::~Tria(){{{1*/
+Tria::~Tria(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object management: */
+/*FUNCTION Tria::Configure {{{1*/
+void  Tria::Configure(DataSet* loadsin, DataSet* nodesin, DataSet* materialsin, Parameters* parametersin){
+
+	/*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: */
+	hnodes.configure(nodesin);
+	hmatice.configure(materialsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION Tria::copy {{{1*/
+Object* Tria::copy() {
+
+	return new Tria(this->id,&this->hnodes,&this->hmatice,&this->hmatpar,this->parameters,this->inputs);
+
+}
+
+/*}}}*/
+/*FUNCTION Tria::Demarshall {{{1*/
+void  Tria::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	hmatice.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+	
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Tria::DeepEcho{{{1*/
+
+void Tria::DeepEcho(void){
+
+	printf("Tria:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	hmatice.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+	
+	return;
+}
+/*}}}*/
+/*FUNCTION Tria::Echo{{{1*/
+
+void Tria::Echo(void){
+
+	printf("Tria:\n");
+	printf("   id: %i\n",id);
+	hnodes.Echo();
+	hmatice.Echo();
+	hmatpar.Echo();
+	printf("   parameters\n");
+	parameters->Echo();
+	printf("   inputs\n");
+	inputs->Echo();
+}
+/*}}}*/
+/*FUNCTION Tria::Marshall {{{1*/
+void  Tria::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Tria: */
+	enum_type=TriaEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Tria data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	hmatice.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Tria::MarshallSize {{{1*/
+int   Tria::MarshallSize(){
+	
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+hmatice.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+
+/*Updates: */
+/*FUNCTION Tria::UpdateFromDakota {{{1*/
+void  Tria::UpdateFromDakota(void* vinputs){
+
+	int     i;
+	int     dofs[1]={0};
+	double  temperature_list[3];
+	double  temperature_average;
+	double  B_list[3];
+	double  B_average;
+	double  new_h[3];
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*Update internal data if inputs holds new values: */
+	/*inputs->Recover("thickness",&this->properties.h[0],1,dofs,3,(void**)nodes);
+	if(inputs->Recover("thickness",&new_h[0],1,dofs,3,(void**)nodes)){
+	//density, needed later:
+	double di=(this->matpar->GetRhoIce()/this->matpar->GetRhoWater());
+	//Go through grids:
+	for (i=0;i<3;i++){
+	if(nodes[i]->IsOnShelf()){
+	this->b[i]=this->b[i]-di*(new_h[i]-h[i]); //hydrostatic equilibrium;
+	}
+	this->s[i]=this->b[i]+new_h[i];
+	this->h[i]=new_h[i];
+	}
+	}*/
+
+	ISSMERROR("not supported yet!");
+
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputs {{{1*/
+void  Tria::UpdateInputs(double* solution, int analysis_type, int sub_analysis_type){
+
+	/*Just branch to the correct UpdateInputs generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+		
+		UpdateInputsDiagnosticHoriz( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+	
+		if (sub_analysis_type==HorizAnalysisEnum){
+
+			UpdateInputsDiagnosticHoriz( solution,analysis_type,sub_analysis_type);
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+
+		UpdateInputsSlopeCompute( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		UpdateInputsPrognostic( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Prognostic2AnalysisEnum){
+
+		UpdateInputsPrognostic2(solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		UpdateInputsBalancedthickness( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+
+		UpdateInputsBalancedthickness2( solution,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		UpdateInputsBalancedvelocities( solution,analysis_type,sub_analysis_type);
+	}
+	else{
+
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsDiagnosticHoriz {{{1*/
+void  Tria::UpdateInputsDiagnosticHoriz(double* solution, int analysis_type, int sub_analysis_type){
+	
+	
+	int i;
+
+	const int    numvertices=3;
+	const int    numdofpervertex=2;
+	const int    numdof=numdofpervertex*numvertices;
+	
+	int          doflist[numdof];
+	double       values[numdof];
+	double       vx[numvertices];
+	double       vy[numvertices];
+
+	int          dummy;
+	
+	/*Get dof list: */
+	GetDofList(&doflist[0],&dummy);
+
+	/*Use the dof list to index into the solution vector: */
+	for(i=0;i<numdof;i++){
+		values[i]=solution[doflist[i]];
+	}
+
+	/*Ok, we have vx and vy in values, fill in vx and vy arrays: */
+	for(i=0;i<numvertices;i++){
+		vx[i]=values[i*numdofpervertex+0];
+		vy[i]=values[i*numdofpervertex+1];
+	}
+
+	/*Add vx and vy as inputs to the tria element: */
+	this->inputs->AddInput(new TriaVertexInput(VxEnum,vx));
+	this->inputs->AddInput(new TriaVertexInput(VyEnum,vy));
+}
+
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsSlopeCompute {{{1*/
+void  Tria::UpdateInputsSlopeCompute(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsPrognostic {{{1*/
+void  Tria::UpdateInputsPrognostic(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsPrognostic2 {{{1*/
+void  Tria::UpdateInputsPrognostic2(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsBalancedthickness {{{1*/
+void  Tria::UpdateInputsBalancedthickness(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsBalancedthickness2 {{{1*/
+void  Tria::UpdateInputsBalancedthickness2(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Tria::UpdateInputsBalancedvelocities {{{1*/
+void  Tria::UpdateInputsBalancedvelocities(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR(" not supported yet!");
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION Tria::ComputeBasalStress {{{1*/
+void  Tria::ComputeBasalStress(Vec eps,int analysis_type,int sub_analysis_type){
+
+	int i;
+	const int numgrids=3;
+	int doflist[numgrids];
+	double value;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*plug local pressure values into global pressure vector: */
+	ISSMERROR("Not Implemented yet");
+	//VecSetValues(eps,1,2,(const double*)&value,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Tria::ComputePressure {{{1*/
+void  Tria::ComputePressure(Vec pg,int analysis_type,int sub_analysis_type){
+
+	int i;
+	const int numvertices=3;
+	int doflist[numvertices];
+	double pressure[numvertices];
+	double thickness[numvertices];
+	double rho_ice,g;
+	double gauss[numvertices][numvertices]={{1,0,0},{0,1,0},{0,0,1}};
+	
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*Get dof list on which we will plug the pressure values: */
+	GetDofList1(&doflist[0]);
+
+	/*pressure is lithostatic: */
+	rho_ice=matpar->GetRhoIce();
+	g=matpar->GetG();
+
+	/*recover value of thickness at gauss points (0,0,1), (0,1,0),(1,0,0): */
+	inputs->GetParameterValues(&thickness[0],&gauss[0][0],3,ThicknessEnum);
+
+	for(i=0;i<numvertices;i++){
+		pressure[i]=rho_ice*g*thickness[i];
+	}
+
+	/*plug local pressure values into global pressure vector: */
+	VecSetValues(pg,numvertices,doflist,(const double*)pressure,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Tria::ComputeStrainRate {{{1*/
+void  Tria::ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type){
+
+	int i;
+	const int numgrids=3;
+	int doflist[numgrids];
+	double value;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=   NULL;
+	Matpar* matpar    =NULL;
+	Matice* matice= NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*plug local pressure values into global pressure vector: */
+	ISSMERROR("Not Implemented yet");
+	//VecSetValues(eps,1,2,(const double*)&value,INSERT_VALUES);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CostFunction {{{1*/
+double Tria::CostFunction(int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* output: */
+	double Jelem;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	const int    NDOF2=2;
+	int          dofs1[1]={0};
+	int          dofs2[2]={0,1};
+	double       xyz_list[numgrids][3];
+
+	/* grid data: */
+	double B[numgrids];
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  k_gauss;
+	double  B_gauss;
+
+	/* parameters: */
+	double  dk[NDOF2]; 
+	double  dB[NDOF2]; 
+	char*   control_type=NULL;
+	double  cm_noisedmp;
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater;
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&control_type,ControlTypeEnum);
+	this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+
+	/*First, get Misfit*/
+	Jelem=Misfit(analysis_type,sub_analysis_type);
+
+	  /* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	  GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Add Tikhonov regularization term to misfit*/
+		if (strcmp(control_type,"drag")==0){
+			if (shelf){
+				inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
+				Jelem+=cm_noisedmp*1/2*(pow(dk[0],2)+pow(dk[1],2))*Jdet*gauss_weight;
+
+			}
+		}
+		else if (strcmp(control_type,"B")==0){
+			inputs->GetParameterDerivativeValue(&dB[0], &xyz_list[0][0], &gauss_l1l2l3[0],RheologyBEnum);
+			Jelem+=cm_noisedmp*1/2*(pow(dB[0],2)+pow(dB[1],2))*Jdet*gauss_weight;
+		}
+		else{
+			ISSMERROR("%s%s","unsupported control type: ",control_type);
+		}
+
+	}
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+	xfree((void**)&control_type);
+
+	/*Return: */
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrix {{{1*/
+
+void  Tria::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element stiffness matrix generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+		
+		CreateKMatrixDiagnosticHoriz( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+	
+		if (sub_analysis_type==HorizAnalysisEnum){
+
+			CreateKMatrixDiagnosticHoriz( Kgg,analysis_type,sub_analysis_type);
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+
+		CreateKMatrixSlopeCompute( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		CreateKMatrixPrognostic( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Prognostic2AnalysisEnum){
+
+		CreateKMatrixPrognostic2(Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		CreateKMatrixBalancedthickness( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+
+		CreateKMatrixBalancedthickness2( Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		CreateKMatrixBalancedvelocities( Kgg,analysis_type,sub_analysis_type);
+	}
+	else{
+
+		ISSMERROR("%s%i%s\n","analysis: ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixBalancedthickness {{{1*/
+void  Tria::CreateKMatrixBalancedthickness(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* matrices: */
+	double L[numgrids];
+	double B[2][numgrids];
+	double Bprime[2][numgrids];
+	double DL[2][2]={0.0};
+	double DLprime[2][2]={0.0};
+	double DL_scalar;
+	double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix 
+	double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+	double Ke_gg_thickness1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+	double Ke_gg_thickness2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx_list[numgrids];
+	double  vy_list[numgrids];
+	double  dvx[2];
+	double  dvy[2];
+	double  vx,vy;
+	double  dvxdx,dvydy;
+	double  v_gauss[2]={0.0};
+
+
+	double  K[2][2]={0.0};
+	double  KDL[2][2]={0.0};
+	int     dofs[2]={0,1};
+	int     found=0;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*parameters: */
+	double artdiff;
+
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*Recover velocity: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&artdiff,ArtDiffEnum);
+
+	//Create Artificial diffusivity once for all if requested
+	if(artdiff){
+		//Get the Jacobian determinant
+		gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		//Build K matrix (artificial diffusivity matrix)
+		v_gauss[0]=ONETHIRD*(vx_list[0]+vx_list[1]+vx_list[2]);
+		v_gauss[1]=ONETHIRD*(vy_list[0]+vy_list[1]+vy_list[2]);
+
+		K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
+		K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get B  and B prime matrix: */
+		GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		//Get vx, vy and their derivatives at gauss point
+		this->GetParameterValue(&vx, &vx_list[0],gauss_l1l2l3);
+		this->GetParameterValue(&vy, &vy_list[0],gauss_l1l2l3);
+
+		this->GetParameterDerivativeValue(&dvx[0], &vx_list[0],&xyz_list[0][0], gauss_l1l2l3);
+		this->GetParameterDerivativeValue(&dvy[0], &vy_list[0],&xyz_list[0][0], gauss_l1l2l3);
+
+		dvxdx=dvx[0];
+		dvydy=dvy[1];
+
+		DL_scalar=gauss_weight*Jdettria;
+
+		//Create DL and DLprime matrix
+		DL[0][0]=DL_scalar*dvxdx;
+		DL[1][1]=DL_scalar*dvydy;
+
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		//Do the triple product tL*D*L. 
+		//Ke_gg_thickness=B'*DLprime*Bprime;
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&B[0][0],2,numdof,0,
+					&Ke_gg_thickness1[0][0],0);
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke_gg_thickness2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
+
+		if(artdiff){
+
+			/* Compute artificial diffusivity */
+			KDL[0][0]=DL_scalar*K[0][0];
+			KDL[1][1]=DL_scalar*K[1][1];
+
+			TripleMultiply( &Bprime[0][0],2,numdof,1,
+						&KDL[0][0],2,2,0,
+						&Bprime[0][0],2,numdof,0,
+						&Ke_gg_gaussian[0][0],0);
+
+			/* Add artificial diffusivity matrix */
+			for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+		}
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixBalancedthickness2 {{{1*/
+void  Tria::CreateKMatrixBalancedthickness2(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrices: */
+	double B[2][numgrids];
+	double Bprime[2][numgrids];
+	double DL[2][2]={0.0};
+	double DLprime[2][2]={0.0};
+	double DL_scalar;
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg2[numdof][numdof]={0.0};
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx,vy;
+	int     dofs[1]={0};
+	int     found;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+
+	/*recover objects from hooks: */
+	nodes=(Node**)   hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get B  and B prime matrix: */
+		/*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
+		GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		//Get vx, vy and their derivatives at gauss point
+		inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
+		inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
+
+		DL_scalar=-gauss_weight*Jdettria;
+
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		//Do the triple product tL*D*L. 
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke_gg2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixBalancedvelocities {{{1*/
+void  Tria::CreateKMatrixBalancedvelocities(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* matrices: */
+	double L[numgrids];
+	double B[2][numgrids];
+	double Bprime[2][numgrids];
+	double DL[2][2]={0.0};
+	double DLprime[2][2]={0.0};
+	double DL_scalar;
+	double Ke_gg[numdof][numdof]={0.0};//local element stiffness matrix 
+	double Ke_gg_gaussian[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+	double Ke_gg_velocities1[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+	double Ke_gg_velocities2[numdof][numdof]={0.0}; //stiffness matrix evaluated at the gaussian point.
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  surface_normal[3];
+	double  surface_list[3];
+	double  nx,ny,norm;
+	double  vx_list[numgrids]={0.0};
+	double  vy_list[numgrids]={0.0};
+	double  dvx[2];
+	double  dvy[2];
+	double  vx,vy;
+	double  dvxdx,dvydy;
+	double  v_gauss[2]={0.0};
+	double  K[2][2]={0.0};
+	double  KDL[2][2]={0.0};
+	int     dofs[2]={0,1};
+	int     found=0;
+
+	/*parameters: */
+	double artdiff;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*Recover velocity: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&artdiff,ArtDiffEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*Modify z so that it reflects the surface*/
+	inputs->GetParameterValues(&surface_list[0],&gaussgrids[0][0],3,SurfaceEnum);
+	for(i=0;i<numgrids;i++) xyz_list[i][2]=surface_list[i];
+
+	/*Get normal vector to the surface*/
+	nx=(vx_list[0]+vx_list[1]+vx_list[2])/3;
+	ny=(vy_list[0]+vy_list[1]+vy_list[2])/3;
+	if(nx==0 && ny==0){
+		SurfaceNormal(&surface_normal[0],xyz_list);
+		nx=surface_normal[0];
+		ny=surface_normal[1];
+	}
+	if(nx==0 && ny==0){
+		nx=0;
+		ny=1;
+	}
+	norm=pow( pow(nx,2)+pow(ny,2) , (double).5);
+	nx=nx/norm;
+	ny=ny/norm;
+
+	//Create Artificial diffusivity once for all if requested
+	if(artdiff){
+		//Get the Jacobian determinant
+		gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		//Build K matrix (artificial diffusivity matrix)
+		v_gauss[0]=ONETHIRD*(vx_list[0]+vx_list[1]+vx_list[2]);
+		v_gauss[1]=ONETHIRD*(vy_list[0]+vy_list[1]+vy_list[2]);
+
+		K[0][0]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]); //pow should be zero!!
+		K[1][1]=pow(10,2)*pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get B  and B prime matrix: */
+		GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		//Get vx, vy and their derivatives at gauss point
+		GetParameterValue(&vx, &vx_list[0],gauss_l1l2l3);
+		GetParameterValue(&vy, &vy_list[0],gauss_l1l2l3);
+
+		GetParameterDerivativeValue(&dvx[0], &vx_list[0],&xyz_list[0][0], gauss_l1l2l3);
+		GetParameterDerivativeValue(&dvy[0], &vy_list[0],&xyz_list[0][0], gauss_l1l2l3);
+
+		dvxdx=dvx[0];
+		dvydy=dvy[1];
+
+		DL_scalar=gauss_weight*Jdettria;
+
+		DLprime[0][0]=DL_scalar*nx;
+		DLprime[1][1]=DL_scalar*ny;
+
+		//Do the triple product tL*D*L. 
+		//Ke_gg_velocities=B'*DLprime*Bprime;
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke_gg_velocities2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_velocities2[i][j];
+
+		if(artdiff){
+
+			/* Compute artificial diffusivity */
+			KDL[0][0]=DL_scalar*K[0][0];
+			KDL[1][1]=DL_scalar*K[1][1];
+
+			TripleMultiply( &Bprime[0][0],2,numdof,1,
+						&KDL[0][0],2,2,0,
+						&Bprime[0][0],2,numdof,0,
+						&Ke_gg_gaussian[0][0],0);
+
+			/* Add artificial diffusivity matrix */
+			for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+		}
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticHoriz {{{1*/
+void  Tria::CreateKMatrixDiagnosticHoriz(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* material data: */
+	double viscosity; //viscosity
+	double newviscosity; //viscosity
+	double oldviscosity; //viscosity
+
+	/* strain rate: */
+	double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
+	double oldepsilon[3]; /* oldepsilon=[exx,eyy,exy];*/
+
+	/* matrices: */
+	double B[3][numdof];
+	double Bprime[3][numdof];
+	double D[3][3]={0.0};  // material matrix, simple scalar matrix.
+	double D_scalar;
+
+	/*parameters: */
+	double viscosity_overshoot;
+
+	/* local element matrices: */
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
+
+	double Jdet;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  thickness;
+	int     dofs[2]={0,1};
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater,shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&viscosity_overshoot,ViscosityOvershootEnum);
+
+	/*First, if we are on water, return empty matrix: */
+	if(onwater) return;
+
+	/*recover objects from hooks: */
+	nodes =(Node**) hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+
+		/*Compute thickness at gaussian point: */
+		inputs->GetParameterValue(&thickness, gauss_l1l2l3,ThicknessEnum);
+
+		/*Get strain rate from velocity: */
+		inputs->GetStrainRate(&epsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxEnum,VyEnum);
+		inputs->GetStrainRate(&oldepsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxOldEnum,VyOldEnum);
+
+		/*Get viscosity: */
+		matice->GetViscosity2d(&viscosity, &epsilon[0]);
+		matice->GetViscosity2d(&oldviscosity, &oldepsilon[0]);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/* Build the D matrix: we plug the gaussian weight, the thickness, the viscosity, and the jacobian determinant 
+			onto this scalar matrix, so that we win some computational time: */
+		newviscosity=viscosity+viscosity_overshoot*(viscosity-oldviscosity);
+		D_scalar=newviscosity*thickness*gauss_weight*Jdet;
+
+		for (i=0;i<3;i++){
+			D[i][i]=D_scalar;
+		}
+
+		/*Get B and Bprime matrices: */
+		GetB(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		/*  Do the triple product tB*D*Bprime: */
+		TripleMultiply( &B[0][0],3,numdof,1,
+					&D[0][0],3,3,0,
+					&Bprime[0][0],3,numdof,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+	/*Do not forget to include friction: */
+	if(!shelf){
+		CreateKMatrixDiagnosticHorizFriction(Kgg,analysis_type,sub_analysis_type);
+	}
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticHorizFriction {{{1*/
+void  Tria::CreateKMatrixDiagnosticHorizFriction(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+	
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* matrices: */
+	double L[2][numdof];
+	double DL[2][2]={{ 0,0 },{0,0}}; //for basal drag
+	double DL_scalar;
+
+	/* local element matrices: */
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
+	
+	double Jdet;
+	
+	/*slope: */
+	double  slope[2]={0.0,0.0};
+	double  slope_magnitude;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx_list[numgrids];
+	double  vy_list[numgrids];
+	double  thickness_list[numgrids];
+	double  bed_list[numgrids];
+	double  dragcoefficient_list[numgrids];
+	double  drag_p,drag_q;
+
+	/*friction: */
+	double alpha2_list[numgrids]={0.0,0.0,0.0};
+	double alpha2;
+
+	double MAXSLOPE=.06; // 6 %
+	double MOUNTAINKEXPONENT=10;
+
+	/*inputs: */
+	bool shelf;
+	int  drag_type;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+	inputs->GetParameterValue(&drag_type,DragTypeEnum);
+	
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	if (shelf){
+		/*no friction, do nothing*/
+		return;
+	}
+
+	if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
+
+	/*Recover inputs: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+	inputs->GetParameterValues(&dragcoefficient_list[0],&gaussgrids[0][0],3,DragCoefficientEnum);
+	inputs->GetParameterValues(&bed_list[0],&gaussgrids[0][0],3,BedEnum);
+	inputs->GetParameterValues(&thickness_list[0],&gaussgrids[0][0],3,ThicknessEnum);
+	inputs->GetParameterValue(&drag_p,DragPEnum);
+	inputs->GetParameterValue(&drag_q,DragQEnum);
+
+	/*Build alpha2_list used by drag stiffness matrix*/
+	Friction* friction=NewFriction();
+	
+	/*Initialize all fields: */
+	friction->element_type=(char*)xmalloc((strlen("2d")+1)*sizeof(char));
+	strcpy(friction->element_type,"2d");
+	
+	friction->gravity=matpar->GetG();
+	friction->rho_ice=matpar->GetRhoIce();
+	friction->rho_water=matpar->GetRhoWater();
+	friction->K=&dragcoefficient_list[0];
+	friction->bed=&bed_list[0];
+	friction->thickness=&thickness_list[0];
+	friction->vx=&vx_list[0];
+	friction->vy=&vy_list[0];
+	friction->p=drag_p;
+	friction->q=drag_q;
+
+	/*Compute alpha2_list: */
+	FrictionGetAlpha2(&alpha2_list[0],friction);
+
+	/*Erase friction object: */
+	DeleteFriction(&friction);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+
+		// If we have a slope > 6% for this element,  it means  we are on a mountain. In this particular case, 
+		//velocity should be = 0. To achieve this result, we set alpha2_list to a very high value: */
+		inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
+		slope_magnitude=sqrt(pow(slope[0],2)+pow(slope[1],2));
+
+		if (slope_magnitude>MAXSLOPE){
+			alpha2_list[0]=pow((double)10,MOUNTAINKEXPONENT);
+			alpha2_list[1]=pow((double)10,MOUNTAINKEXPONENT);
+			alpha2_list[2]=pow((double)10,MOUNTAINKEXPONENT);
+		}
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/*Now, take care of the basal friction if there is any: */
+		GetParameterValue(&alpha2, &alpha2_list[0],gauss_l1l2l3);
+
+		DL_scalar=alpha2*gauss_weight*Jdet;
+		for (i=0;i<2;i++){
+			DL[i][i]=DL_scalar;
+		}
+		
+		/*  Do the triple producte tL*D*L: */
+		TripleMultiply( &L[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&L[0][0],2,numdof,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}	
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixDiagnosticSurfaceVert {{{1*/
+void  Tria::CreateKMatrixDiagnosticSurfaceVert(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+
+	/* surface normal: */
+	double x4,y4,z4;
+	double x5,y5,z5;
+	double x6,y6,z6;
+	double v46[3];
+	double v56[3];
+	double normal[3];
+	double norm_normal;
+	double nz;
+
+	/*Matrices: */
+	double DL_scalar;
+	double L[3];
+	double Jdet;
+
+	/* local element matrices: */
+	double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix 
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/*Build normal vector to the surface:*/
+
+	x4=xyz_list[0][0];
+	y4=xyz_list[0][1];
+	z4=xyz_list[0][2];
+
+	x5=xyz_list[1][0];
+	y5=xyz_list[1][1];
+	z5=xyz_list[1][2];
+
+	x6=xyz_list[2][0];
+	y6=xyz_list[2][1];
+	z6=xyz_list[2][2];
+
+	v46[0]=x4-x6;
+	v46[1]=y4-y6;
+	v46[2]=z4-z6;
+
+	v56[0]=x5-x6;
+	v56[1]=y5-y6;
+	v56[2]=z5-z6;
+
+	normal[0]=(y4-y6)*(z5-z6)-(z4-z6)*(y5-y6);
+	normal[1]=(z4-z6)*(x5-x6)-(x4-x6)*(z5-z6);
+	normal[2]=(x4-x6)*(y5-y6)-(y4-y6)*(x5-x6);
+
+	norm_normal=sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
+	nz=1.0/norm_normal*normal[2];
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		//Get L matrix if viscous basal drag present:
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
+
+		/**********************Do not forget the sign**********************************/
+		DL_scalar=- gauss_weight*Jdet*nz; 
+		/******************************************************************************/
+
+		/*  Do the triple producte tL*D*L: */
+		TripleMultiply( L,1,3,1,
+					&DL_scalar,1,1,0,
+					L,1,3,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		/* Add the Ke_gg_gaussian, onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+
+	} //for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixMelting {{{1*/
+void  Tria::CreateKMatrixMelting(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*indexing: */
+	int i,j;
+
+	const int  numgrids=3;
+	const int  NDOF1=1;
+	const int  numdof=numgrids*NDOF1;
+	int        doflist[numdof];
+	int        numberofdofspernode;
+
+	/*Grid data: */
+	double     xyz_list[numgrids][3];
+
+	/*Material constants */
+	double     heatcapacity,latentheat;
+
+	/* gaussian points: */
+	int     num_area_gauss,ig;
+	double* gauss_weights  =  NULL;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+
+	/*matrices: */
+	double     Jdet;
+	double     D_scalar;
+	double     K_terms[numdof][numdof]={0.0};
+	double     L[3];
+	double     tLD[3];
+	double     Ke_gaussian[numdof][numdof]={0.0};
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*Recover constants of ice */
+	latentheat=matpar->GetLatentHeat();
+	heatcapacity=matpar->GetHeatCapacity();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights: */
+	GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start looping on the number of gauss  (nodes on the bedrock) */
+	for (ig=0; ig<num_area_gauss; ig++){
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig); 
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+
+		//Get the Jacobian determinant
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
+
+		/*Get L matrix : */
+		GetL(&L[0], &xyz_list[0][0], gauss_coord,NDOF1);
+
+		/*Calculate DL on gauss point */
+		D_scalar=latentheat/heatcapacity*gauss_weight*Jdet;
+
+		/*  Do the triple product tL*D*L: */
+		MatrixMultiply(&L[0],numdof,1,0,&D_scalar,1,1,0,&tLD[0],0);
+		MatrixMultiply(&tLD[0],numdof,1,0,&L[0],1,numdof,0,&Ke_gaussian[0][0],0);
+
+		for(i=0;i<numgrids;i++){
+			for(j=0;j<numgrids;j++){
+				K_terms[i][j]+=Ke_gaussian[i][j];
+			}
+		}
+	}
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
+
+cleanup_and_return:
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixPrognostic {{{1*/
+void  Tria::CreateKMatrixPrognostic(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* matrices: */
+	double L[numgrids];
+	double B[2][numgrids];
+	double Bprime[2][numgrids];
+	double DL[2][2]={0.0};
+	double DLprime[2][2]={0.0};
+	double DL_scalar;
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg_gaussian[numdof][numdof]={0.0};
+	double Ke_gg_thickness1[numdof][numdof]={0.0};
+	double Ke_gg_thickness2[numdof][numdof]={0.0};
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx_list[numgrids]={0.0};
+	double  vy_list[numgrids]={0.0};
+	double  dvx[2];
+	double  dvy[2];
+	double  vx,vy;
+	double  dvxdx,dvydy;
+	double  v_gauss[2]={0.0};
+	double  K[2][2]={0.0};
+	double  KDL[2][2]={0.0};
+	int     dofs[2]={0,1};
+	int     found;
+
+	/*parameters: */
+	double dt;
+	double artdiff;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+	this->parameters->FindParam(&artdiff,ArtDiffEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*Recover velocity: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+
+	//Create Artificial diffusivity once for all if requested
+	if(artdiff==1){
+		//Get the Jacobian determinant
+		gauss_l1l2l3[0]=ONETHIRD; gauss_l1l2l3[1]=ONETHIRD; gauss_l1l2l3[2]=ONETHIRD;
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		//Build K matrix (artificial diffusivity matrix)
+		v_gauss[0]=ONETHIRD*(vx_list[0]+vx_list[1]+vx_list[2]);
+		v_gauss[1]=ONETHIRD*(vy_list[0]+vy_list[1]+vy_list[2]);
+
+		K[0][0]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[0]);
+		K[1][1]=pow(Jdettria,(double).5)/2.0*fabs(v_gauss[1]);
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		DL_scalar=gauss_weight*Jdettria;
+
+		/*  Do the triple product tL*D*L: */
+		TripleMultiply( &L[0],1,numdof,1,
+					&DL_scalar,1,1,0,
+					&L[0],1,numdof,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		/*Get B  and B prime matrix: */
+		GetB_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		//Get vx, vy and their derivatives at gauss point
+		GetParameterValue(&vx, &vx_list[0],gauss_l1l2l3);
+		GetParameterValue(&vy, &vy_list[0],gauss_l1l2l3);
+
+		GetParameterDerivativeValue(&dvx[0], &vx_list[0],&xyz_list[0][0], gauss_l1l2l3);
+		GetParameterDerivativeValue(&dvy[0], &vy_list[0],&xyz_list[0][0], gauss_l1l2l3);
+
+		dvxdx=dvx[0];
+		dvydy=dvy[1];
+
+		DL_scalar=dt*gauss_weight*Jdettria;
+
+		//Create DL and DLprime matrix
+		DL[0][0]=DL_scalar*dvxdx;
+		DL[1][1]=DL_scalar*dvydy;
+
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		//Do the triple product tL*D*L. 
+		//Ke_gg_thickness=B'*DL*B+B'*DLprime*Bprime;
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DL[0][0],2,2,0,
+					&B[0][0],2,numdof,0,
+					&Ke_gg_thickness1[0][0],0);
+
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke_gg_thickness2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness1[i][j];
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_thickness2[i][j];
+
+		if(artdiff==1){
+
+			/* Compute artificial diffusivity */
+			KDL[0][0]=DL_scalar*K[0][0];
+			KDL[1][1]=DL_scalar*K[1][1];
+
+			TripleMultiply( &Bprime[0][0],2,numdof,1,
+						&KDL[0][0],2,2,0,
+						&Bprime[0][0],2,numdof,0,
+						&Ke_gg_gaussian[0][0],0);
+
+			/* Add artificial diffusivity matrix */
+			for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+		}
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixPrognostic2 {{{1*/
+void  Tria::CreateKMatrixPrognostic2(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrices: */
+	double L[numgrids];
+	double B[2][numgrids];
+	double Bprime[2][numgrids];
+	double DL[2][2]={0.0};
+	double DLprime[2][2]={0.0};
+	double DL_scalar;
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg1[numdof][numdof]={0.0};
+	double Ke_gg2[numdof][numdof]={0.0};
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx,vy;
+	int     dofs[1]={0};
+	int     found;
+
+	/*parameters: */
+	double dt;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)   hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		DL_scalar=gauss_weight*Jdettria;
+
+		/*  Do the triple product tL*D*L: */
+		TripleMultiply( &L[0],1,numdof,1,
+					&DL_scalar,1,1,0,
+					&L[0],1,numdof,0,
+					&Ke_gg1[0][0],0);
+
+		/*Get B  and B prime matrix: */
+		/*WARNING: B and Bprime are inverted compared to usual prognostic!!!!*/
+		GetB_prog(&Bprime[0][0], &xyz_list[0][0], gauss_l1l2l3);
+		GetBPrime_prog(&B[0][0], &xyz_list[0][0], gauss_l1l2l3);
+
+		//Get vx, vy and their derivatives at gauss point
+		inputs->GetParameterValue(&vx,&gauss_l1l2l3[0],VxAverageEnum);
+		inputs->GetParameterValue(&vy,&gauss_l1l2l3[0],VyAverageEnum);
+
+		DL_scalar=-dt*gauss_weight*Jdettria;
+
+		DLprime[0][0]=DL_scalar*vx;
+		DLprime[1][1]=DL_scalar*vy;
+
+		//Do the triple product tL*D*L. 
+		TripleMultiply( &B[0][0],2,numdof,1,
+					&DLprime[0][0],2,2,0,
+					&Bprime[0][0],2,numdof,0,
+					&Ke_gg2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg1[i][j];
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixSlopeCompute {{{1*/
+
+void  Tria::CreateKMatrixSlopeCompute(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+	
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrices: */
+	double L[1][3];
+	double DL_scalar;
+
+	/* local element matrices: */
+	double Ke_gg[numdof][numdof]={0.0}; //local element stiffness matrix 
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
+	
+	double Jdet;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		
+		/*Get L matrix: */
+		GetL(&L[0][0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+		
+		DL_scalar=gauss_weight*Jdet;
+
+		/*  Do the triple producte tL*D*L: */
+		TripleMultiply( &L[0][0],1,3,1,
+					&DL_scalar,1,1,0,
+					&L[0][0],1,3,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+	} //for (ig=0; ig<num_gauss; ig++
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+		
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
+/*FUNCTION Tria::CreateKMatrixThermal {{{1*/
+void  Tria::CreateKMatrixThermal(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+	int found=0;
+	
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	double mixed_layer_capacity;
+	double thermal_exchange_velocity;
+	double rho_water;
+	double rho_ice;
+	double heatcapacity;
+
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+
+	/*matrices: */
+	double  Jdet;
+	double  K_terms[numdof][numdof]={0.0};
+	double  Ke_gaussian[numdof][numdof]={0.0};
+	double  l1l2l3[numgrids];
+	double     tl1l2l3D[3];
+	double  D_scalar;
+
+	/*parameters: */
+	double dt;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//recover material parameters
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+
+
+	GaussTria (&num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start looping on the number of gauss (nodes on the bedrock) */
+	for (ig=0; ig<num_gauss; ig++){
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig); 
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+		
+		//Get the Jacobian determinant
+		GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
+		
+		/*Get nodal functions values: */
+		GetNodalFunctions(&l1l2l3[0], gauss_coord);
+				
+		/*Calculate DL on gauss point */
+		D_scalar=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity/(heatcapacity*rho_ice);
+		if(dt){
+			D_scalar=dt*D_scalar;
+		}
+
+		/*  Do the triple product tL*D*L: */
+		MatrixMultiply(&l1l2l3[0],numdof,1,0,&D_scalar,1,1,0,&tl1l2l3D[0],0);
+		MatrixMultiply(&tl1l2l3D[0],numdof,1,0,&l1l2l3[0],1,numdof,0,&Ke_gaussian[0][0],0);
+
+		for(i=0;i<3;i++){
+			for(j=0;j<3;j++){
+				K_terms[i][j]+=Ke_gaussian[i][j];
+			}
+		}
+	}
+	
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)K_terms,ADD_VALUES);
+
+	cleanup_and_return:
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVector {{{1*/
+void  Tria::CreatePVector(Vec pg,int analysis_type,int sub_analysis_type){
+	
+	/*Just branch to the correct load generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+		
+		CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+	
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+		if (sub_analysis_type==HorizAnalysisEnum){
+		
+			CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+		}
+		else ISSMERROR("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet");
+	}
+	else if (analysis_type==SlopecomputeAnalysisEnum){
+		
+		CreatePVectorSlopeCompute( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum){
+
+		CreatePVectorPrognostic( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Prognostic2AnalysisEnum){
+
+		CreatePVectorPrognostic2( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedthicknessAnalysisEnum){
+
+		CreatePVectorBalancedthickness( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+
+		CreatePVectorBalancedthickness2( pg,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==BalancedvelocitiesAnalysisEnum){
+
+		CreatePVectorBalancedvelocities( pg,analysis_type,sub_analysis_type);
+	}
+	else{
+		ISSMERROR("%s%i%s"," analysis ",analysis_type," not supported yet");
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancedthickness {{{1*/
+void  Tria::CreatePVectorBalancedthickness(Vec pg ,int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrix */
+	double pe_g[numgrids]={0.0};
+	double L[numgrids];
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  accumulation_g;
+	double  melting_g;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/* Get accumulation, melting at gauss point */
+		inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
+		inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancedthickness2 {{{1*/
+void  Tria::CreatePVectorBalancedthickness2(Vec pg ,int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrix */
+	double pe_g[numgrids]={0.0};
+	double L[numgrids];
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  accumulation_g;
+	double  melting_g;
+	double  dhdt_g;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)   hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/* Get accumulation, melting and thickness at gauss point */
+		inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
+		inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
+		inputs->GetParameterValue(&dhdt_g, &gauss_l1l2l3[0],DhDtEnum);
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g+dhdt_g)*L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorBalancedvelocities {{{1*/
+void  Tria::CreatePVectorBalancedvelocities(Vec pg ,int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrix */
+	double pe_g[numgrids]={0.0};
+	double L[numgrids];
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  accumulation_g;
+	double  melting_g;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/* Get accumulation, melting at gauss point */
+		inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
+		inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(accumulation_g-melting_g)*L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorDiagnosticBaseVert {{{1*/
+void  Tria::CreatePVectorDiagnosticBaseVert(Vec pg,int analysis_type,int sub_analysis_type){
+
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof]={0.0};
+	double  pe_g_gaussian[numdof];
+
+	/* matrices: */
+	double L[numgrids];
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  vx,vy;
+	double  meltingvalue;
+	double  slope[2];
+	double  dbdx,dbdy;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/*For icesheets: */
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/*Get melting at gaussian point: */
+		inputs->GetParameterValue(&meltingvalue, &gauss_l1l2l3[0],MeltingRateEnum);
+
+		/*Get velocity at gaussian point: */
+		inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
+		inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
+
+		/*Get bed slope: */
+		inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
+		dbdx=slope[0];
+		dbdy=slope[1];
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		//Get L matrix if viscous basal drag present:
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,NDOF1);
+
+
+		/*Build gaussian vector: */
+		for(i=0;i<numgrids;i++){
+			pe_g_gaussian[i]=-Jdet*gauss_weight*(vx*dbdx+vy*dbdy-meltingvalue)*L[i];
+		}
+
+		/*Add pe_g_gaussian vector to pe_g: */
+		for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
+
+	}
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorDiagnosticHoriz {{{1*/
+void Tria::CreatePVectorDiagnosticHoriz( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	const int    NDOF2=2;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+	
+	/* parameters: */
+	double  plastic_stress; 
+	double  slope[NDOF2];
+	double  driving_stress_baseline;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof]={0.0};
+	double  pe_g_gaussian[numdof];
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  thickness;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater;
+	int  drag_type;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+	inputs->GetParameterValue(&drag_type,DragTypeEnum);
+
+	/*First, if we are on water, return empty vector: */
+	if(onwater)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+
+	/* Get gaussian points and weights: */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/*Compute thickness at gaussian point: */
+		inputs->GetParameterValue(&thickness, &gauss_l1l2l3[0],ThicknessEnum);
+		inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
+		
+		/*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the 
+		 * element itself: */
+		if(drag_type==1){
+			inputs->GetParameterValue(&plastic_stress, &gauss_l1l2l3[0],DragCoefficientEnum);
+		}
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+		
+		 /*Get nodal functions: */
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Compute driving stress: */
+		driving_stress_baseline=matpar->GetRhoIce()*matpar->GetG()*thickness;
+
+		/*Build pe_g_gaussian vector: */
+		if(drag_type==1){
+			for (i=0;i<numgrids;i++){
+				for (j=0;j<NDOF2;j++){
+					pe_g_gaussian[i*NDOF2+j]=(-driving_stress_baseline*slope[j]-plastic_stress)*Jdet*gauss_weight*l1l2l3[i]; 
+				}
+			}
+		}
+		else {
+			for (i=0;i<numgrids;i++){
+				for (j=0;j<NDOF2;j++){
+					pe_g_gaussian[i*NDOF2+j]=-driving_stress_baseline*slope[j]*Jdet*gauss_weight*l1l2l3[i];
+				}
+			}
+		}
+
+		/*Add pe_g_gaussian vector to pe_g: */
+		for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
+
+	} //for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorPrognostic {{{1*/
+void  Tria::CreatePVectorPrognostic(Vec pg ,int analysis_type,int sub_analysis_type){
+
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrix */
+	double pe_g[numgrids]={0.0};
+	double L[numgrids];
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  accumulation_g;
+	double  melting_g;
+	double  thickness_g;
+
+	/*parameters: */
+	double  dt;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/* Get accumulation, melting and thickness at gauss point */
+		inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
+		inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
+		inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorPrognostic2 {{{1*/
+void  Tria::CreatePVectorPrognostic2(Vec pg ,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* matrix */
+	double pe_g[numgrids]={0.0};
+	double L[numgrids];
+	double Jdettria;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  accumulation_g;
+	double  melting_g;
+	double  thickness_g;
+	double  dt;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdettria, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get L matrix: */
+		GetL(&L[0], &xyz_list[0][0], gauss_l1l2l3,numberofdofspernode);
+
+		/* Get accumulation, melting and thickness at gauss point */
+		inputs->GetParameterValue(&accumulation_g, &gauss_l1l2l3[0],AccumulationRateEnum);
+		inputs->GetParameterValue(&melting_g, &gauss_l1l2l3[0],MeltingRateEnum);
+		inputs->GetParameterValue(&thickness_g, &gauss_l1l2l3[0],ThicknessEnum);
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i]+=Jdettria*gauss_weight*(thickness_g+dt*(accumulation_g-melting_g))*L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorSlopeCompute {{{1*/
+
+void Tria::CreatePVectorSlopeCompute( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int             i,j;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+	
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof]={0.0};
+	double  pe_g_gaussian[numdof];
+	double  slope[2];
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+
+	/* Get gaussian points and weights: */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2); /*We need higher order because our load is order 2*/
+
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		if ( (sub_analysis_type==SurfaceXAnalysisEnum) || (sub_analysis_type==SurfaceYAnalysisEnum)){
+			inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],SurfaceEnum);
+		}
+		if ( (sub_analysis_type==BedXAnalysisEnum) || (sub_analysis_type==BedYAnalysisEnum)){
+			inputs->GetParameterDerivativeValue(&slope[0],&xyz_list[0][0],&gauss_l1l2l3[0],BedEnum);
+		}
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+		
+		 /*Get nodal functions: */
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Build pe_g_gaussian vector: */
+		if ( (sub_analysis_type==SurfaceXAnalysisEnum) || (sub_analysis_type==BedXAnalysisEnum)){
+			for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[0]*l1l2l3[i];
+		}
+		if ( (sub_analysis_type==SurfaceYAnalysisEnum) || (sub_analysis_type==BedYAnalysisEnum)){
+			for(i=0;i<numdof;i++) pe_g_gaussian[i]=Jdet*gauss_weight*slope[1]*l1l2l3[i];
+		}
+
+		/*Add pe_g_gaussian vector to pe_g: */
+		for( i=0; i<numdof; i++)pe_g[i]+=pe_g_gaussian[i];
+
+	} //for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorThermalShelf {{{1*/
+void Tria::CreatePVectorThermalShelf( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int i,found;
+	
+	const int  numgrids=3;
+	const int  NDOF1=1;
+	const int  numdof=numgrids*NDOF1;
+	int        doflist[numdof];
+	int        numberofdofspernode;
+	double       xyz_list[numgrids][3];
+
+	double mixed_layer_capacity;
+	double thermal_exchange_velocity;
+	double rho_water;
+	double rho_ice;
+	double heatcapacity;
+	double beta;
+	double meltingpoint;
+
+	/*inputs: */
+	double dt;
+	double pressure;
+
+	/* gaussian points: */
+	int     num_area_gauss,ig;
+	double* gauss_weights  =  NULL;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+	int     dofs1[1]={0};
+
+	/*matrices: */
+	double  Jdet;
+	double  P_terms[numdof]={0.0};
+	double  l1l2l3[numgrids];
+
+	double  t_pmp;
+	double  scalar_ocean;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+	
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//recover material parameters
+	mixed_layer_capacity=matpar->GetMixedLayerCapacity();
+	thermal_exchange_velocity=matpar->GetThermalExchangeVelocity();
+	rho_water=matpar->GetRhoWater();
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+	beta=matpar->GetBeta();
+	meltingpoint=matpar->GetMeltingPoint();
+	
+	/*retrieve some solution parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+	/* Ice/ocean heat exchange flux on ice shelf base */
+
+	GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	for (ig=0; ig<num_area_gauss; ig++){
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig); 
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+
+		//Get the Jacobian determinant
+		GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0], gauss_coord);
+
+		/*Get nodal functions values: */
+		GetNodalFunctions(&l1l2l3[0], gauss_coord);
+
+		/*Get geothermal flux and basal friction */
+		inputs->GetParameterValue(&pressure, &gauss_coord[0],PressureEnum);
+		t_pmp=meltingpoint-beta*pressure;
+
+		/*Calculate scalar parameter*/
+		scalar_ocean=gauss_weight*Jdet*rho_water*mixed_layer_capacity*thermal_exchange_velocity*(t_pmp)/(heatcapacity*rho_ice);
+		if(dt){
+			scalar_ocean=dt*scalar_ocean;
+		}
+
+		for(i=0;i<3;i++){
+			P_terms[i]+=scalar_ocean*l1l2l3[i];
+		}
+	}
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::CreatePVectorThermalSheet {{{1*/
+void Tria::CreatePVectorThermalSheet( Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int i,found;
+	
+	const int  numgrids=3;
+	const int  NDOF1=1;
+	const int  numdof=numgrids*NDOF1;
+	int        doflist[numdof];
+	int        numberofdofspernode;
+	double       xyz_list[numgrids][3];
+
+	double rho_ice;
+	double heatcapacity;
+
+	/*inputs: */
+	double dt;
+	double pressure_list[3];
+	double pressure;
+	double alpha2_list[3];
+	double basalfriction_list[3];
+	double basalfriction;
+	double geothermalflux_value;
+
+	double  vx_list[numgrids];
+	double  vy_list[numgrids];
+	double  thickness_list[numgrids];
+	double  bed_list[numgrids];
+	double  dragcoefficient_list[numgrids];
+	double  drag_p,drag_q;
+	int     drag_type;
+
+	/* gaussian points: */
+	int     num_area_gauss,ig;
+	double* gauss_weights  =  NULL;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/*matrices: */
+	double  Jdet;
+	double  P_terms[numdof]={0.0};
+	double  l1l2l3[numgrids];
+	double  scalar;
+
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&drag_type,DragTypeEnum);
+	
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//recover material parameters
+	rho_ice=matpar->GetRhoIce();
+	heatcapacity=matpar->GetHeatCapacity();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&dt,DtEnum);
+
+
+	/*Recover inputs: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+	inputs->GetParameterValues(&dragcoefficient_list[0],&gaussgrids[0][0],3,DragCoefficientEnum);
+	inputs->GetParameterValues(&bed_list[0],&gaussgrids[0][0],3,BedEnum);
+	inputs->GetParameterValues(&thickness_list[0],&gaussgrids[0][0],3,ThicknessEnum);
+	inputs->GetParameterValue(&drag_p,DragPEnum);
+	inputs->GetParameterValue(&drag_q,DragQEnum);
+
+	/*Build alpha2_list used by drag stiffness matrix*/
+	Friction* friction=NewFriction();
+	
+	/*Initialize all fields: */
+	if (drag_type!=2)ISSMERROR(" non-viscous friction not supported yet!");
+	
+	friction->element_type=(char*)xmalloc((strlen("3d")+1)*sizeof(char));
+	strcpy(friction->element_type,"3d");
+
+	friction->gravity=matpar->GetG();
+	friction->rho_ice=matpar->GetRhoIce();
+	friction->rho_water=matpar->GetRhoWater();
+	friction->K=&dragcoefficient_list[0];
+	friction->bed=&bed_list[0];
+	friction->thickness=&thickness_list[0];
+	friction->vx=&vx_list[0];
+	friction->vy=&vy_list[0];
+	friction->p=drag_p;
+	friction->q=drag_q;
+
+	/*Compute alpha2_list: */
+	FrictionGetAlpha2(&alpha2_list[0],friction);
+
+	/*Erase friction object: */
+	DeleteFriction(&friction);
+
+	/* Compute basal friction */
+	for(i=0;i<numgrids;i++){
+		basalfriction_list[i]= alpha2_list[i]*(pow(vx_list[i],(double)2.0)+pow(vy_list[i],(double)2.0));
+	}
+	
+	/* Ice/ocean heat exchange flux on ice shelf base */
+	GaussTria (&num_area_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start looping on the number of gauss 2d (nodes on the bedrock) */
+	for (ig=0; ig<num_area_gauss; ig++){
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig); 
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+
+		//Get the Jacobian determinant
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0], gauss_coord);
+
+		/*Get nodal functions values: */
+		GetNodalFunctions(&l1l2l3[0], gauss_coord);
+
+		/*Get geothermal flux and basal friction */
+		inputs->GetParameterValue(&geothermalflux_value, &gauss_coord[0],GeothermalFluxEnum);
+		GetParameterValue(&basalfriction,&basalfriction_list[0],gauss_coord);
+
+		/*Calculate scalar parameter*/
+		scalar=gauss_weight*Jdet*(basalfriction+geothermalflux_value)/(heatcapacity*rho_ice);
+		if(dt){
+			scalar=dt*scalar;
+		}
+
+		for(i=0;i<3;i++){
+			P_terms[i]+=scalar*l1l2l3[i];
+		}
+	}
+
+	/*Add pe_g to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::Du {{{1*/
+void Tria::Du(Vec du_g,int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	const int    NDOF2=2;
+	double       xyz_list[numgrids][3];
+	int          doflist[numdof];
+	int          numberofdofspernode;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* grid data: */
+	double vx_list[numgrids];
+	double vy_list[numgrids];
+	double obs_vx_list[numgrids];
+	double obs_vy_list[numgrids];
+	double dux_list[numgrids];
+	double duy_list[numgrids];
+	double weights_list[numgrids];
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/* parameters: */
+	double  obs_velocity_mag,velocity_mag;
+	double  dux,duy;
+	double  meanvel, epsvel;
+
+	/*element vector : */
+	double  due_g[numdof]={0.0};
+	double  due_g_gaussian[numdof];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*relative and algorithmic fitting: */
+	double scalex=0;
+	double scaley=0;
+	double scale=0;
+	double S=0;
+	double fit=-1;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&meanvel,MeanVelEnum);
+	this->parameters->FindParam(&epsvel,EpsVelEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Recover input data: */
+	inputs->GetParameterValues(&obs_vx_list[0],&gaussgrids[0][0],3,VxObsEnum);
+	inputs->GetParameterValues(&obs_vy_list[0],&gaussgrids[0][0],3,VyObsEnum);
+
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyEnum);
+	
+	inputs->GetParameterValues(&weights_list[0],&gaussgrids[0][0],3,WeightsEnum);
+	
+	inputs->GetParameterValue(&fit,FitEnum);
+	if(fit==3){
+		inputs->GetParameterValue(&S,SurfaceAreaEnum);
+	}
+
+	/*Get Du at the 3 nodes (integration of the linearized function)
+	 * Here we integrate linearized functions:
+	 *               
+	 * J(E) = int_E   sum_{i=1}^3  J_i Phi_i
+	 *
+	 *       d J                  dJ_i
+	 * DU= - --- = sum_{i=1}^3  - ---  Phi_i = sum_{i=1}^3 DU_i Phi_i
+	 *       d u                  du_i
+	 *
+	 * where J_i are the misfits at the 3 nodes of the triangle
+	 *       Phi_i is the nodal function (P1) with respect to 
+	 *       the vertex i
+	 */
+	if(fit==0){
+		/*We are using an absolute misfit:
+		 *
+		 *      1  [           2              2 ]
+		 * J = --- | (u - u   )  +  (v - v   )  |
+		 *      2  [       obs            obs   ]
+		 *
+		 *        dJ             2
+		 * DU = - -- = (u   - u )
+		 *        du     obs
+		 */
+		for (i=0;i<numgrids;i++){
+			dux_list[i]=obs_vx_list[i]-vx_list[i];
+			duy_list[i]=obs_vy_list[i]-vy_list[i];
+		}
+	}
+	else if(fit==1){
+		/*We are using a relative misfit: 
+		 *                        
+		 *      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                      
+		 *
+		 *        dJ     \bar{v}^2
+		 * DU = - -- = ------------- (u   - u )
+		 *        du   (u   + eps)^2    obs
+		 *               obs
+		 */
+		for (i=0;i<numgrids;i++){
+			scalex=pow(meanvel/(obs_vx_list[i]+epsvel),2);
+			scaley=pow(meanvel/(obs_vy_list[i]+epsvel),2);
+			if(obs_vx_list[i]==0)scalex=0;
+			if(obs_vy_list[i]==0)scaley=0;
+			dux_list[i]=scalex*(obs_vx_list[i]-vx_list[i]);
+			duy_list[i]=scaley*(obs_vy_list[i]-vy_list[i]);
+		}
+	}
+	else if(fit==2){
+		/*We are using a logarithmic misfit:
+		 *                        
+		 *                 [        vel + eps     ] 2
+		 * J = 4 \bar{v}^2 | log ( -----------  ) |  
+		 *                 [       vel   + eps    ]
+		 *                            obs
+		 *
+		 *        dJ                 2 * log(...)
+		 * DU = - -- = - 4 \bar{v}^2 -------------  u
+		 *        du                 vel^2 + eps
+		 *            
+		 */
+		for (i=0;i<numgrids;i++){
+			velocity_mag=sqrt(pow(vx_list[i],2)+pow(vy_list[i],2))+epsvel; //epsvel to avoid velocity being nil.
+			obs_velocity_mag=sqrt(pow(obs_vx_list[i],2)+pow(obs_vy_list[i],2))+epsvel; //epsvel to avoid observed velocity being nil.
+			scale=-8*pow(meanvel,2)/pow(velocity_mag,2)*log(velocity_mag/obs_velocity_mag);
+			dux_list[i]=scale*vx_list[i];
+			duy_list[i]=scale*vy_list[i];
+		}
+	}
+	else if(fit==3){
+		/*We are using an spacially average absolute misfit:
+		 *
+		 *      1                    2              2
+		 * J = ---  sqrt(  (u - u   )  +  (v - v   )  )
+		 *      S                obs            obs
+		 *
+		 *        dJ      1       1 
+		 * DU = - -- = - --- ----------- * 2 (u - u   )
+		 *        du      S  2 sqrt(...)           obs
+		 */
+		for (i=0;i<numgrids;i++){
+			scale=1.0/(S*sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))+epsvel);
+			dux_list[i]=scale*(obs_vx_list[i]-vx_list[i]);
+			duy_list[i]=scale*(obs_vy_list[i]-vy_list[i]);
+		}
+	}
+	else if(fit==4){
+		/*We are using an logarithmic 2 misfit:
+		 *
+		 *      1            [        |u| + eps     2          |v| + eps     2  ]
+		 * J = --- \bar{v}^2 | log ( -----------  )   +  log ( -----------  )   |  
+		 *      2            [       |u    |+ eps              |v    |+ eps     ]
+		 *                              obs                       obs
+		 *        dJ                              1      u                             1
+		 * DU = - -- = - \bar{v}^2 log(u...) --------- ----  ~ - \bar{v}^2 log(u...) ------
+		 *        du                         |u| + eps  |u|                           u + eps
+		 */
+		for (i=0;i<numgrids;i++){
+			dux_list[i] = - pow(meanvel,(double)2)*(
+						log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)) * 1/(vx_list[i]+epsvel));
+			duy_list[i] = - pow(meanvel,(double)2)*(
+						log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)) * 1/(vy_list[i]+epsvel));
+		}
+	}
+	else{
+		/*Not supported yet! : */
+		ISSMERROR("%s%g","unsupported type of fit: ",fit);
+	}
+
+	/*Apply weights to DU*/
+	for (i=0;i<numgrids;i++){
+		dux_list[i]=weights_list[i]*dux_list[i];
+		duy_list[i]=weights_list[i]*duy_list[i];
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/* Get nodal functions value at gaussian point:*/
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Build due_g_gaussian vector: we have three cases here, according to which type of misfit we are using. */
+
+		/*Compute absolute(x/y) at gaussian point: */
+		GetParameterValue(&dux, &dux_list[0],gauss_l1l2l3);
+		GetParameterValue(&duy, &duy_list[0],gauss_l1l2l3);
+
+		/*compute Du*/
+		for (i=0;i<numgrids;i++){
+			due_g_gaussian[i*NDOF2+0]=dux*Jdet*gauss_weight*l1l2l3[i]; 
+			due_g_gaussian[i*NDOF2+1]=duy*Jdet*gauss_weight*l1l2l3[i]; 
+		}
+
+		/*Add due_g_gaussian vector to due_g: */
+		for( i=0; i<numdof; i++){
+			due_g[i]+=due_g_gaussian[i];
+		}
+	}
+
+	/*Add due_g to global vector du_g: */
+	VecSetValues(du_g,numdof,doflist,(const double*)due_g,ADD_VALUES);
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::Enum {{{1*/
+int Tria::Enum(void){
+
+	return TriaEnum;
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetArea {{{1*/
+double Tria::GetArea(void){
+
+	double area=0;
+	const int    numgrids=3;
+	double xyz_list[numgrids][3];
+	double x1,y1,x2,y2,x3,y3;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*Get xyz list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	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;
+}
+/*}}}*/
+/*FUNCTION Tria::GetAreaCoordinate {{{1*/
+double Tria::GetAreaCoordinate(double x, double y, int which_one){
+
+	double area=0;
+	const int    numgrids=3;
+	double xyz_list[numgrids][3];
+	double x1,y1,x2,y2,x3,y3;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*Get area: */
+	area=this->GetArea();
+
+	/*Get xyz list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	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];
+
+	if(which_one==1){
+		/*Get first area coordinate = det(x-x3  x2-x3 ; y-y3   y2-y3)/area*/
+		return ((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area;
+	}
+	else if(which_one==2){
+		/*Get second area coordinate = det(x1-x3  x-x3 ; y1-y3   y-y3)/area*/
+		return ((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
+	}
+	else if(which_one==3){
+		/*Get third  area coordinate 1-area1-area2: */
+		return 1-((x-x3)*(y2-y3)-(x2-x3)*(y-y3))/area -((x1-x3)*(y-y3)-(x-x3)*(y1-y3))/area;
+	}
+	else ISSMERROR("%s%i%s\n"," error message: area coordinate ",which_one," done not exist!");
+}
+/*}}}*/
+/*FUNCTION Tria::GetB {{{1*/
+
+void Tria::GetB(double* B, double* xyz_list, double* gauss_l1l2l3){
+
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For grid i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ dh/dx    0    ]
+	 *                [   0    dh/dy  ]
+	 *                [ 1/2*dh/dy  1/2*dh/dx  ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B has been allocated already, of size: 3x(NDOF2*numgrids)
+	 */
+	
+	int i;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	double dh1dh3[NDOF2][numgrids];
+
+
+	/*Get dh1dh2dh3 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
+
+	/*Build B: */
+	for (i=0;i<numgrids;i++){
+		*(B+NDOF2*numgrids*0+NDOF2*i)=dh1dh3[0][i]; //B[0][NDOF2*i]=dh1dh3[0][i];
+		*(B+NDOF2*numgrids*0+NDOF2*i+1)=0;
+		*(B+NDOF2*numgrids*1+NDOF2*i)=0;
+		*(B+NDOF2*numgrids*1+NDOF2*i+1)=dh1dh3[1][i];
+		*(B+NDOF2*numgrids*2+NDOF2*i)=(float).5*dh1dh3[1][i]; 
+		*(B+NDOF2*numgrids*2+NDOF2*i+1)=(float).5*dh1dh3[0][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetB_prog {{{1*/
+
+void Tria::GetB_prog(double* B_prog, double* xyz_list, double* gauss_l1l2l3){
+
+	/*Compute B  matrix. B=[B1 B2 B3] where Bi is of size 3*NDOF2. 
+	 * For grid i, Bi can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi=[ h ]
+	 *                [ h ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B_prog has been allocated already, of size: 2x(NDOF1*numgrids)
+	 */
+
+	int i;
+	const int NDOF1=1;
+	const int numgrids=3;
+
+	double l1l2l3[numgrids];
+
+
+	/*Get dh1dh2dh3 in actual coordinate system: */
+	GetNodalFunctions(&l1l2l3[0],gauss_l1l2l3);
+
+	/*Build B_prog: */
+	for (i=0;i<numgrids;i++){
+		*(B_prog+NDOF1*numgrids*0+NDOF1*i)=l1l2l3[i];
+		*(B_prog+NDOF1*numgrids*1+NDOF1*i)=l1l2l3[i];
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetBedList {{{1*/
+void  Tria::GetBedList(double* bedlist){
+	
+	const int numgrids=3;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+	
+	inputs->GetParameterValues(bedlist,&gaussgrids[0][0],3,BedEnum);
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetBPrime {{{1*/
+
+void Tria::GetBPrime(double* Bprime, double* xyz_list, double* gauss_l1l2l3){
+
+	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_prime=[ 2*dh/dx dh/dy ]
+	 *                       [ dh/dx  2*dh/dy]
+	 *                       [dh/dy dh/dx]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
+	 */
+	
+	int i;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	/*Same thing in the actual coordinate system: */
+	double dh1dh3[NDOF2][numgrids];
+
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(Bprime+NDOF2*numgrids*0+NDOF2*i)=2*dh1dh3[0][i]; 
+		*(Bprime+NDOF2*numgrids*0+NDOF2*i+1)=dh1dh3[1][i]; 
+		*(Bprime+NDOF2*numgrids*1+NDOF2*i)=dh1dh3[0][i]; 
+		*(Bprime+NDOF2*numgrids*1+NDOF2*i+1)=2*dh1dh3[1][i]; 
+		*(Bprime+NDOF2*numgrids*2+NDOF2*i)=dh1dh3[1][i]; 
+		*(Bprime+NDOF2*numgrids*2+NDOF2*i+1)=dh1dh3[0][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetBPrime_prog {{{1*/
+
+void Tria::GetBPrime_prog(double* Bprime_prog, double* xyz_list, double* gauss_l1l2l3){
+
+	/*Compute B'  matrix. B'=[B1' B2' B3'] where Bi' is of size 3*NDOF2. 
+	 * For grid i, Bi' can be expressed in the actual coordinate system
+	 * by: 
+	 *       Bi_prime=[ dh/dx ]
+	 *                       [ dh/dy ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume B' has been allocated already, of size: 3x(NDOF2*numgrids)
+	 */
+
+	int i;
+	const int NDOF1=1;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	/*Same thing in the actual coordinate system: */
+	double dh1dh3[NDOF2][numgrids];
+
+	/*Get dh1dh2dh3 in actual coordinates system : */
+	GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list,gauss_l1l2l3);
+
+	/*Build B': */
+	for (i=0;i<numgrids;i++){
+		*(Bprime_prog+NDOF1*numgrids*0+NDOF1*i)=dh1dh3[0][i]; 
+		*(Bprime_prog+NDOF1*numgrids*1+NDOF1*i)=dh1dh3[1][i]; 
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetDofList {{{1*/
+void  Tria::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	for(i=0;i<3;i++){
+		nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+		for(j=0;j<numberofdofspernode;j++){
+			doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetDofList1 {{{1*/
+void  Tria::GetDofList1(int* doflist){
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	int i;
+	for(i=0;i<3;i++){
+		doflist[i]=nodes[i]->GetDofList1();
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::Id {{{1*/
+int    Tria::Id(){ return id; }
+/*}}}*/
+/*FUNCTION Tria::GetJacobian {{{1*/
+void Tria::GetJacobian(double* J, double* xyz_list,double* gauss_l1l2l3){
+
+	/*The Jacobian is constant over the element, discard the gaussian points. 
+	 * J is assumed to have been allocated of size NDOF2xNDOF2.*/
+
+	const int NDOF2=2;
+	const int numgrids=3;
+	double x1,y1,x2,y2,x3,y3;
+	
+	x1=*(xyz_list+numgrids*0+0);
+	y1=*(xyz_list+numgrids*0+1);
+	x2=*(xyz_list+numgrids*1+0);
+	y2=*(xyz_list+numgrids*1+1);
+	x3=*(xyz_list+numgrids*2+0);
+	y3=*(xyz_list+numgrids*2+1);
+
+
+	*(J+NDOF2*0+0)=0.5*(x2-x1);
+	*(J+NDOF2*1+0)=SQRT3/6.0*(2*x3-x1-x2);
+	*(J+NDOF2*0+1)=0.5*(y2-y1);
+	*(J+NDOF2*1+1)=SQRT3/6.0*(2*y3-y1-y2);
+}
+/*}}}*/
+/*FUNCTION Tria::GetJacobianDeterminant2d {{{1*/
+void Tria::GetJacobianDeterminant2d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
+
+	/*The Jacobian determinant is constant over the element, discard the gaussian points. 
+	 * J is assumed to have been allocated of size NDOF2xNDOF2.*/
+
+	double x1,x2,x3,y1,y2,y3;
+	
+	x1=*(xyz_list+3*0+0);
+	y1=*(xyz_list+3*0+1);
+	x2=*(xyz_list+3*1+0);
+	y2=*(xyz_list+3*1+1);
+	x3=*(xyz_list+3*2+0);
+	y3=*(xyz_list+3*2+1);
+
+
+	*Jdet=SQRT3/6.0*((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1));
+
+
+	if(Jdet<0){
+		ISSMERROR("negative jacobian determinant!");
+	}
+	
+}
+/*}}}*/
+/*FUNCTION Tria::GetJacobianDeterminant3d {{{1*/
+void Tria::GetJacobianDeterminant3d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3){
+
+	/*The Jacobian determinant is constant over the element, discard the gaussian points. 
+	 * J is assumed to have been allocated of size NDOF2xNDOF2.*/
+
+	double x1,x2,x3,y1,y2,y3,z1,z2,z3;
+	
+	x1=*(xyz_list+3*0+0);
+	y1=*(xyz_list+3*0+1);
+	z1=*(xyz_list+3*0+2);
+	x2=*(xyz_list+3*1+0);
+	y2=*(xyz_list+3*1+1);
+	z2=*(xyz_list+3*1+2);
+	x3=*(xyz_list+3*2+0);
+	y3=*(xyz_list+3*2+1);
+	z3=*(xyz_list+3*2+2);
+
+
+	*Jdet=SQRT3/6.0*pow(pow(((y2-y1)*(z3-z1)-(z2-z1)*(y3-y1)),2.0)+pow(((z2-z1)*(x3-x1)-(x2-x1)*(z3-z1)),2.0)+pow(((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)),2.0),0.5);
+
+	if(Jdet<0){
+		ISSMERROR("negative jacobian determinant!");
+	}
+	
+}
+/*}}}*/
+/*FUNCTION Tria::GetJacobianInvert {{{1*/
+void Tria::GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_l1l2l3){
+
+	double Jdet;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	/*Call Jacobian routine to get the jacobian:*/
+	GetJacobian(Jinv, xyz_list, gauss_l1l2l3);
+
+	/*Invert Jacobian matrix: */
+	MatrixInverse(Jinv,NDOF2,NDOF2,NULL,0,&Jdet);
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetL {{{1*/
+
+void Tria::GetL(double* L, double* xyz_list, double* gauss_l1l2l3,int numdof){
+
+	/*Compute L  matrix. L=[L1 L2 L3] where Li is square and of size numdof. 
+	 * For grid i, Li can be expressed in the actual coordinate system
+	 * by: 
+	 *       numdof=1: 
+	 *       Li=h;
+	 *       numdof=2:
+	 *       Li=[ h    0    ]
+	 *                [   0   h  ]
+	 * where h is the interpolation function for grid i.
+	 *
+	 * We assume L has been allocated already, of size: numgrids (numdof=1), or numdofx(numdof*numgrids) (numdof=2)
+	 */
+
+	int i;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	double l1l2l3[3];
+
+
+	/*Get l1l2l3 in actual coordinate system: */
+	GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+#ifdef _DELUG_ 
+	for (i=0;i<3;i++){
+		printf("Node %i  h=%lf \n",i,l1l2l3[i]);
+	}
+#endif
+
+	/*Build L: */
+	if(numdof==1){
+		for (i=0;i<numgrids;i++){
+			L[i]=l1l2l3[i]; 
+		}
+	}
+	else{
+		for (i=0;i<numgrids;i++){
+			*(L+numdof*numgrids*0+numdof*i)=l1l2l3[i]; //L[0][NDOF2*i]=dh1dh3[0][i];
+			*(L+numdof*numgrids*0+numdof*i+1)=0;
+			*(L+numdof*numgrids*1+numdof*i)=0;
+			*(L+numdof*numgrids*1+numdof*i+1)=l1l2l3[i];
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetMatPar {{{1*/
+void* Tria::GetMatPar(){
+
+	/*dynamic objects pointed to by hooks: */
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	matpar=(Matpar*)hmatpar.delivers();
+
+	return matpar;
+}
+/*}}}*/
+/*FUNCTION Tria::GetNodalFunctions {{{1*/
+void Tria::GetNodalFunctions(double* l1l2l3, double* gauss_l1l2l3){
+	
+	/*This routine returns the values of the nodal functions  at the gaussian point.*/
+
+	/*First nodal function: */
+	l1l2l3[0]=gauss_l1l2l3[0];
+
+	/*Second nodal function: */
+	l1l2l3[1]=gauss_l1l2l3[1];
+
+	/*Third nodal function: */
+	l1l2l3[2]=gauss_l1l2l3[2];
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetNodalFunctionsDerivatives {{{1*/
+void Tria::GetNodalFunctionsDerivatives(double* dh1dh3,double* xyz_list, double* gauss_l1l2l3){
+	
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the 
+	 * actual coordinate system: */
+
+	int i;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	double dh1dh3_ref[NDOF2][numgrids];
+	double Jinv[NDOF2][NDOF2];
+
+
+	/*Get derivative values with respect to parametric coordinate system: */
+	GetNodalFunctionsDerivativesReference(&dh1dh3_ref[0][0], gauss_l1l2l3); 
+
+	/*Get Jacobian invert: */
+	GetJacobianInvert(&Jinv[0][0], xyz_list, gauss_l1l2l3);
+
+	/*Build dh1dh3: 
+	 *
+	 * [dhi/dx]= Jinv*[dhi/dr]
+	 * [dhi/dy]       [dhi/ds]
+	 */
+
+	for (i=0;i<numgrids;i++){
+		*(dh1dh3+numgrids*0+i)=Jinv[0][0]*dh1dh3_ref[0][i]+Jinv[0][1]*dh1dh3_ref[1][i];
+		*(dh1dh3+numgrids*1+i)=Jinv[1][0]*dh1dh3_ref[0][i]+Jinv[1][1]*dh1dh3_ref[1][i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetNodalFunctionsDerivativesReference {{{1*/
+void Tria::GetNodalFunctionsDerivativesReference(double* dl1dl3,double* gauss_l1l2l3){
+	
+	/*This routine returns the values of the nodal functions derivatives  (with respect to the 
+	 * natural coordinate system) at the gaussian point. */
+
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	/*First nodal function: */
+	*(dl1dl3+numgrids*0+0)=-0.5; 
+	*(dl1dl3+numgrids*1+0)=-1.0/(2.0*SQRT3);
+
+	/*Second nodal function: */
+	*(dl1dl3+numgrids*0+1)=0.5;
+	*(dl1dl3+numgrids*1+1)=-1.0/(2.0*SQRT3);
+
+	/*Third nodal function: */
+	*(dl1dl3+numgrids*0+2)=0;
+	*(dl1dl3+numgrids*1+2)=1.0/SQRT3;
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetNodes {{{1*/
+void  Tria::GetNodes(void** vpnodes){
+	int i;
+	Node** pnodes=NULL;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	
+	/*recover nodes: */
+	pnodes=(Node**)vpnodes;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	for(i=0;i<3;i++){
+		pnodes[i]=nodes[i];
+	}
+}
+/*}}}*/
+/*FUNCTION Tria::GetOnBed {{{1*/
+bool Tria::GetOnBed(){
+	
+	bool onbed;
+	inputs->GetParameterValue(&onbed,ElementOnBedEnum);
+
+	return onbed;
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterDerivativeValue {{{1*/
+void Tria::GetParameterDerivativeValue(double* p, double* plist,double* xyz_list, double* gauss_l1l2l3){
+	 
+	const int NDOF2=2;
+	const int numgrids=3;
+	/*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter derivative value at gaussian 
+	 * point specified by gauss_l1l2l3:
+	 *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
+	 *   dp/dx=plist[0]*dh1/dx+plist[1]*dh2/dx+plist[2]*dh3/dx
+	 *
+	 * p is a vector of size 2x1 already allocated.
+	 */
+	
+	double dh1dh3[NDOF2][numgrids]; //nodal derivative functions in actual coordinate system.
+
+	/*Get dh1dh2dh3 in actual coordinate system: */
+	GetNodalFunctionsDerivatives(&dh1dh3[0][0],xyz_list, gauss_l1l2l3);
+
+	*(p+0)=plist[0]*dh1dh3[0][0]+plist[1]*dh1dh3[0][1]+plist[2]*dh1dh3[0][2];
+	*(p+1)=plist[0]*dh1dh3[1][0]+plist[1]*dh1dh3[1][1]+plist[2]*dh1dh3[1][2];
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetParameterValue {{{1*/
+void Tria::GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3){
+	
+	/*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter value at gaussian 
+	 * point specifie by gauss_l1l2l3: */
+	
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*output: */
+	double p;
+
+	GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+	p=l1l2l3[0]*plist[0]+l1l2l3[1]*plist[1]+l1l2l3[2]*plist[2];
+
+	/*Assign output pointers:*/
+	*pp=p;
+}
+/*}}}*/
+/*FUNCTION Tria::GetShelf {{{1*/
+bool   Tria::GetShelf(){
+	/*inputs: */
+	bool shelf;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	return shelf;
+}
+/*}}}*/
+/*FUNCTION Tria::GetStrainRate {{{1*/
+void Tria::GetStrainRate(double* epsilon, double* velocity, double* xyz_list, double* gauss_l1l2l3){
+
+	int i;
+	const int NDOF2=2;
+	const int numgrids=3;
+
+	double B[3][NDOF2*numgrids];
+
+	/*Get B matrix: */
+	GetB(&B[0][0], xyz_list, gauss_l1l2l3);
+
+	/*Multiply B by velocity, to get strain rate: */
+	MatrixMultiply( &B[0][0],3,NDOF2*numgrids,0,
+			              velocity,NDOF2*numgrids,1,0,
+						  epsilon,0);
+
+}
+/*}}}*/
+/*FUNCTION Tria::GetThicknessList {{{1*/
+void Tria::GetThicknessList(double* thickness_list){
+
+	const int numgrids=3;
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+	inputs->GetParameterValues(thickness_list,&gaussgrids[0][0],3,ThicknessEnum);
+
+}
+/*}}}*/
+/*FUNCTION Tria::Gradj {{{1*/
+void  Tria::Gradj(Vec grad_g,int analysis_type,int sub_analysis_type,char* control_type){
+
+	/*inputs: */
+	bool onwater;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, grad = 0: */
+	if(onwater)return;
+
+	if (strcmp(control_type,"drag")==0){
+		GradjDrag( grad_g,analysis_type,sub_analysis_type);
+	}
+	else if (strcmp(control_type,"B")==0){
+		GradjB( grad_g,analysis_type,sub_analysis_type);
+	}
+	else ISSMERROR("%s%s","control type not supported yet: ",control_type);
+}
+/*}}}*/
+/*FUNCTION Tria::GradjB{{{1*/
+void  Tria::GradjB(Vec grad_g,int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF1=1;
+	const int    NDOF2=2;
+	const int    numdof=NDOF2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist1[numgrids];
+	double       dh1dh3[NDOF2][numgrids];
+
+	/* grid data: */
+	double B[numgrids];
+
+	int    dofs1[1]={0};
+	int    dofs2[2]={0,1};
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+
+	/*element vector at the gaussian points: */
+	double  grade_g[numgrids]={0.0};
+	double  grade_g_gaussian[numgrids];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/* strain rate: */
+	double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
+
+	/* parameters: */
+	double  viscosity_complement;
+	double  dvx[NDOF2];
+	double  dvy[NDOF2]; 
+	double  dadjx[NDOF2];
+	double  dadjy[NDOF2];
+	double  vx,vy;
+	double  lambda,mu;
+	double  thickness;
+	int     dofs[1]={0};
+	double  dB[NDOF2]; 
+	double  B_gauss;
+	
+	/*parameters: */
+	double  cm_noisedmp;
+	double  cm_mindmp_slope;
+	double  cm_mindmp_value;
+	double  cm_maxdmp_value;
+	double  cm_maxdmp_slope;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
+	this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
+	this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
+	this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
+	this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList1(&doflist1[0]);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/*Get thickness: */
+		inputs->GetParameterValue(&thickness, gauss_l1l2l3,ThicknessEnum);
+
+		/*Get strain rate, if velocity has been supplied: */
+		inputs->GetStrainRate(&epsilon[0],&xyz_list[0][0],gauss_l1l2l3,VxEnum,VyEnum);
+
+		/*Get viscosity complement: */
+		matice->GetViscosityComplement(&viscosity_complement, &epsilon[0]);
+
+		/*Get dvx, dvy, dadjx and dadjx: */
+		inputs->GetParameterDerivativeValue(&dvx[0],&xyz_list[0][0],&gauss_l1l2l3[0],VxEnum);
+		inputs->GetParameterDerivativeValue(&dvy[0],&xyz_list[0][0],&gauss_l1l2l3[0],VyEnum);
+		inputs->GetParameterDerivativeValue(&dadjx[0],&xyz_list[0][0],&gauss_l1l2l3[0],AdjointxEnum);
+		inputs->GetParameterDerivativeValue(&dadjy[0],&xyz_list[0][0],&gauss_l1l2l3[0],AdjointyEnum);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/* Get nodal functions value at gaussian point:*/
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Get nodal functions derivatives*/
+		GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get B derivative: dB/dx */
+		inputs->GetParameterDerivativeValue(&dB[0],&xyz_list[0][0],&gauss_l1l2l3[0],RheologyBEnum);
+		inputs->GetParameterValue(&B_gauss, gauss_l1l2l3,RheologyBEnum);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/dB): */
+		for (i=0;i<numgrids;i++){
+			//standard gradient dJ/dki
+			grade_g_gaussian[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*l1l2l3[i]; 
+
+			//Add regularization term
+			grade_g_gaussian[i]-=cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dB[0]+dh1dh3[1][i]*dB[1]);
+
+			//min dampening
+			if(B_gauss<cm_mindmp_value){ 
+				grade_g_gaussian[i]+= cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+
+			//max dampening
+			if(B_gauss>cm_maxdmp_value){ 
+				grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+
+		}
+
+		/*Add grade_g_gaussian to grade_g: */
+		for( i=0; i<numgrids;i++) grade_g[i]+=grade_g_gaussian[i];
+	}
+
+	/*Add grade_g to global vector grad_g: */
+	VecSetValues(grad_g,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
+/*FUNCTION Tria::GradjDrag {{{1*/
+void  Tria::GradjDrag(Vec grad_g,int analysis_type,int sub_analysis_type){
+
+
+	int i;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF2=2;
+	const int    numdof=NDOF2*numgrids;
+	double       xyz_list[numgrids][3];
+	int          doflist1[numgrids];
+	double       dh1dh3[NDOF2][numgrids];
+
+	/* grid data: */
+	double vx_list[numgrids];
+	double vy_list[numgrids];
+	double adjx_list[numgrids];
+	double adjy_list[numgrids];
+	double thickness_list[numgrids];
+	double bed_list[numgrids];
+	double dragcoefficient_list[numgrids];
+	double drag_p;
+	double drag_q;
+	int    drag_type;
+
+	double drag;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* parameters: */
+	double  dk[NDOF2]; 
+	double  vx,vy;
+	double  lambda,mu;
+	double  bed,thickness,Neff;
+	
+	/*drag: */
+	double alpha_complement_list[numgrids];
+	double alpha_complement;
+
+	/*element vector at the gaussian points: */
+	double  grade_g[numgrids]={0.0};
+	double  grade_g_gaussian[numgrids];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/* strain rate: */
+	double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
+
+	/*inputs: */
+	bool shelf;
+
+	/*parameters: */
+	double  cm_noisedmp;
+	double  cm_mindmp_slope;
+	double  cm_mindmp_value;
+	double  cm_maxdmp_value;
+	double  cm_maxdmp_slope;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
+	this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
+	this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
+	this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
+	this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
+
+
+	/*Get out if shelf*/
+	if(shelf)return;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList1(&doflist1[0]);
+
+	/*Recover inputs: */
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+	inputs->GetParameterValues(&thickness_list[0],&gaussgrids[0][0],3,ThicknessEnum);
+	inputs->GetParameterValues(&bed_list[0],&gaussgrids[0][0],3,BedEnum);
+	inputs->GetParameterValues(&dragcoefficient_list[0],&gaussgrids[0][0],3,DragCoefficientEnum);
+	inputs->GetParameterValue(&drag_p,DragPEnum);
+	inputs->GetParameterValue(&drag_q,DragQEnum);
+	inputs->GetParameterValue(&drag_type,DragTypeEnum);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/*Build alpha_complement_list: */
+		if (drag_type==2){
+		
+			/*Allocate friction object: */
+			Friction* friction=NewFriction();
+			
+			/*Initialize all fields: */
+			friction->element_type=(char*)xmalloc((strlen("2d")+1)*sizeof(char));
+			strcpy(friction->element_type,"2d");
+			
+			
+			friction->gravity=matpar->GetG();
+			friction->rho_ice=matpar->GetRhoIce();
+			friction->rho_water=matpar->GetRhoWater();
+			friction->K=&dragcoefficient_list[0];
+			friction->bed=&bed_list[0];
+			friction->thickness=&thickness_list[0];
+			friction->vx=&vx_list[0];
+			friction->vy=&vy_list[0];
+			friction->p=drag_p;
+			friction->q=drag_q;
+
+			
+			if(friction->p!=1) ISSMERROR("non-linear friction not supported yet in control methods!");
+
+			/*Compute alpha complement: */
+			FrictionGetAlphaComplement(&alpha_complement_list[0],friction);
+
+			/*Erase friction object: */
+			DeleteFriction(&friction);
+		}
+		else{
+			alpha_complement_list[0]=0;
+			alpha_complement_list[1]=0;
+			alpha_complement_list[2]=0;
+		}
+	
+		/*Recover alpha_complement and k: */
+		GetParameterValue(&alpha_complement, &alpha_complement_list[0],gauss_l1l2l3);
+		inputs->GetParameterValue(&drag, gauss_l1l2l3,DragCoefficientEnum);
+
+		/*recover lambda and mu: */
+		inputs->GetParameterValue(&lambda, gauss_l1l2l3,AdjointxEnum);
+		inputs->GetParameterValue(&mu, gauss_l1l2l3,AdjointyEnum);
+			
+		/*recover vx and vy: */
+		inputs->GetParameterValue(&vx, gauss_l1l2l3,VxEnum);
+		inputs->GetParameterValue(&vy, gauss_l1l2l3,VyEnum);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+		
+		/* Get nodal functions value at gaussian point:*/
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Get nodal functions derivatives*/
+		GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get k derivative: dk/dx */
+		inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		for (i=0;i<numgrids;i++){
+
+			//standard term dJ/dki
+			grade_g_gaussian[i]=-2*drag*alpha_complement*((lambda*vx+mu*vy))*Jdet*gauss_weight*l1l2l3[i];
+
+			//noise dampening d/dki(1/2*(dk/dx)^2)
+			grade_g_gaussian[i]+=-cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
+			
+			//min dampening
+			if(drag<cm_mindmp_value){ 
+				grade_g_gaussian[i]+=cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+
+			//max dampening
+			if(drag>cm_maxdmp_value){ 
+				grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+		}
+		
+		/*Add gradje_g_gaussian vector to gradje_g: */
+		for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
+	}
+
+	/*Add grade_g to global vector grad_g: */
+	VecSetValues(grad_g,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
+	
+	cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::GradjDragStokes {{{1*/
+void  Tria::GradjDragStokes(Vec grad_g,int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    NDOF2=2;
+	double       xyz_list[numgrids][3];
+	int          doflist1[numgrids];
+	double       dh1dh3[NDOF2][numgrids];
+
+	/* grid data: */
+	double vx_list[numgrids];
+	double vy_list[numgrids];
+	double vz_list[numgrids];
+	double drag;
+	double  thickness_list[numgrids];
+	double  bed_list[numgrids];
+	double  dragcoefficient_list[numgrids];
+	double  drag_p,drag_q;
+	double alpha_complement_list[numgrids];
+	double alpha_complement;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* parameters: */
+	double  vx,vy,vz;
+	double  lambda,mu,xi;
+	double  bed,thickness,Neff;
+	double  surface_normal[3];
+	double  bed_normal[3];
+	double  dk[NDOF2]; 
+
+	/*element vector at the gaussian points: */
+	double  grade_g[numgrids]={0.0};
+	double  grade_g_gaussian[numgrids];
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/* strain rate: */
+	double epsilon[3]; /* epsilon=[exx,eyy,exy];*/
+
+	/*inputs: */
+	bool shelf;
+	int  drag_type;
+
+	/*parameters: */
+	double  cm_noisedmp;
+	double  cm_mindmp_slope;
+	double  cm_mindmp_value;
+	double  cm_maxdmp_value;
+	double  cm_maxdmp_slope;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&shelf,ElementOnIceShelfEnum);
+	inputs->GetParameterValue(&drag_type,DragTypeEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&cm_noisedmp,CmNoiseDmpEnum);
+	this->parameters->FindParam(&cm_mindmp_value,CmMinDmpValueEnum);
+	this->parameters->FindParam(&cm_mindmp_slope,CmMinDmpSlopeEnum);
+	this->parameters->FindParam(&cm_maxdmp_value,CmMaxDmpValueEnum);
+	this->parameters->FindParam(&cm_maxdmp_slope,CmMaxDmpSlopeEnum);
+
+	/*Get out if shelf*/
+	if(shelf)return;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList1(&doflist1[0]);
+
+	/*Build alpha_complement_list: */
+	if (drag_type==2){
+
+		/*Allocate friction object: */
+		Friction* friction=NewFriction();
+
+		inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxAverageEnum);
+		inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyAverageEnum);
+		inputs->GetParameterValues(&vz_list[0],&gaussgrids[0][0],3,VzAverageEnum);
+		inputs->GetParameterValues(&dragcoefficient_list[0],&gaussgrids[0][0],3,DragCoefficientEnum);
+		inputs->GetParameterValues(&bed_list[0],&gaussgrids[0][0],3,BedEnum);
+		inputs->GetParameterValues(&thickness_list[0],&gaussgrids[0][0],3,ThicknessEnum);
+		inputs->GetParameterValue(&drag_p,DragPEnum);
+		inputs->GetParameterValue(&drag_q,DragQEnum);
+
+
+		/*Initialize all fields: */
+		friction->element_type=(char*)xmalloc((strlen("2d")+1)*sizeof(char));
+		strcpy(friction->element_type,"2d");
+
+		friction->gravity=matpar->GetG();
+		friction->rho_ice=matpar->GetRhoIce();
+		friction->rho_water=matpar->GetRhoWater();
+		friction->K=&dragcoefficient_list[0];
+		friction->bed=&bed_list[0];
+		friction->thickness=&thickness_list[0];
+		friction->vx=&vx_list[0];
+		friction->vy=&vy_list[0];
+		friction->p=drag_p;
+		friction->q=drag_q;
+
+
+		if(friction->p!=1) ISSMERROR("non-linear friction not supported yet in control methods!");
+
+		/*Compute alpha complement: */
+		FrictionGetAlphaComplement(&alpha_complement_list[0],friction);
+
+		/*Erase friction object: */
+		DeleteFriction(&friction);
+	}
+	else{
+		alpha_complement_list[0]=0;
+		alpha_complement_list[1]=0;
+		alpha_complement_list[2]=0;
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 4);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/*Recover alpha_complement and k: */
+		GetParameterValue(&alpha_complement, &alpha_complement_list[0],gauss_l1l2l3);
+		inputs->GetParameterValue(&drag, &gauss_l1l2l3[0],DragCoefficientEnum);
+
+		/*recover lambda mu and xi: */
+		inputs->GetParameterValue(&lambda, &gauss_l1l2l3[0],AdjointxEnum);
+		inputs->GetParameterValue(&mu, &gauss_l1l2l3[0],AdjointyEnum);
+		inputs->GetParameterValue(&xi, &gauss_l1l2l3[0],AdjointzEnum);
+
+		/*recover vx vy and vz: */
+		inputs->GetParameterValue(&vx, &gauss_l1l2l3[0],VxEnum);
+		inputs->GetParameterValue(&vy, &gauss_l1l2l3[0],VyEnum);
+		inputs->GetParameterValue(&vz, &gauss_l1l2l3[0],VzEnum);
+
+		/*Get normal vector to the bed */
+		SurfaceNormal(&surface_normal[0],xyz_list);
+
+		bed_normal[0]=-surface_normal[0]; //Program is for surface, so the normal to the bed is the opposite of the result
+		bed_normal[1]=-surface_normal[1];
+		bed_normal[2]=-surface_normal[2];
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant3d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/* Get nodal functions value at gaussian point:*/
+		GetNodalFunctions(l1l2l3, gauss_l1l2l3);
+
+		/*Get nodal functions derivatives*/
+		GetNodalFunctionsDerivatives(&dh1dh3[0][0],&xyz_list[0][0],gauss_l1l2l3);
+
+		/*Get k derivative: dk/dx */
+		inputs->GetParameterDerivativeValue(&dk[0],&xyz_list[0][0],&gauss_l1l2l3[0],DragCoefficientEnum);
+
+		/*Build gradje_g_gaussian vector (actually -dJ/ddrag): */
+		for (i=0;i<numgrids;i++){
+			//standard gradient dJ/dki
+			grade_g_gaussian[i]=(
+						-lambda*(2*drag*alpha_complement*(vx - vz*bed_normal[0]*bed_normal[2]))
+						-mu    *(2*drag*alpha_complement*(vy - vz*bed_normal[1]*bed_normal[2]))
+						-xi    *(2*drag*alpha_complement*(-vx*bed_normal[0]*bed_normal[2]-vy*bed_normal[1]*bed_normal[2]))
+						)*Jdet*gauss_weight*l1l2l3[i]; 
+
+			//Add regularization term
+			grade_g_gaussian[i]+= - cm_noisedmp*Jdet*gauss_weight*(dh1dh3[0][i]*dk[0]+dh1dh3[1][i]*dk[1]);
+
+			//min dampening
+			if(drag<cm_mindmp_value){ 
+				grade_g_gaussian[i]+= cm_mindmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+
+			//max dampening
+			if(drag>cm_maxdmp_value){ 
+				grade_g_gaussian[i]+= - cm_maxdmp_slope*Jdet*gauss_weight*l1l2l3[i];
+			}
+		}
+
+		/*Add gradje_g_gaussian vector to gradje_g: */
+		for( i=0; i<numgrids; i++)grade_g[i]+=grade_g_gaussian[i];
+	}
+
+	/*Add grade_g to global vector grad_g: */
+	VecSetValues(grad_g,numgrids,doflist1,(const double*)grade_g,ADD_VALUES);
+
+cleanup_and_return: 
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Tria::MassFlux {{{1*/
+double Tria::MassFlux( double* segment,double* ug){
+
+	int i;
+
+	const int    numgrids=3;
+	const int    numdofs=2;
+	int          numberofdofspernode;
+	double mass_flux=0;
+	int    doflist[numgrids*numdofs];
+	double vx_list[3];
+	double vy_list[3];
+	double xyz_list[numgrids][3];
+	double gauss_1[3];
+	double gauss_2[3];
+	double normal[2];
+	double length;
+	double x1,y1,x2,y2;
+	double h1,h2;
+	double vx1,vx2,vy1,vy2;
+	double rho_ice;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/*Get material parameters :*/
+	rho_ice=matpar->GetRhoIce();
+
+	/*First off, check that this segment belongs to this element: */
+	if ((int)*(segment+4)!=this->id)ISSMERROR("%s%i%s%i","error message: segment with id ",(int)*(segment+4)," does not belong to element with id:",this->id);
+
+	/*Recover segment node locations: */
+	x1=*(segment+0); y1=*(segment+1); x2=*(segment+2); y2=*(segment+3);
+
+	/*Get xyz list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+
+	/*recover velocity at three element nodes: */
+	this->GetDofList(&doflist[0],&numberofdofspernode);
+	for(i=0;i<3;i++){
+		vx_list[i]=ug[doflist[numberofdofspernode*i+0]];
+		vy_list[i]=ug[doflist[numberofdofspernode*i+1]];
+	}
+
+	/*get area coordinates of 0 and 1 locations: */
+	for(i=0;i<3;i++){
+		gauss_1[i]=this->GetAreaCoordinate(x1,y1,i+1);
+		gauss_2[i]=this->GetAreaCoordinate(x2,y2,i+1);
+	}
+
+	/*get normal of segment: */
+	normal[0]=cos(atan2(x1-x2,y2-y1));
+	normal[1]=sin(atan2(x1-x2,y2-y1));
+
+	/*get length of segment: */
+	length=sqrt(pow(x2-x1,2.0)+pow(y2-y1,2));
+
+	/*get thickness and velocity at two segment extremities: */
+	inputs->GetParameterValue(&h1, &gauss_1[0],ThicknessEnum);
+	inputs->GetParameterValue(&h2, &gauss_2[0],ThicknessEnum);
+	inputs->GetParameterValue(&vx1, &gauss_1[0],VxEnum);
+	inputs->GetParameterValue(&vx2, &gauss_2[0],VxEnum);
+	inputs->GetParameterValue(&vy1, &gauss_1[0],VyEnum);
+	inputs->GetParameterValue(&vy2, &gauss_2[0],VyEnum);
+
+	mass_flux= rho_ice*length*(  
+				(ONETHIRD*(h1-h2)*(vx1-vx2)+0.5*h2*(vx1-vx2)+0.5*(h1-h2)*vx2+h2*vx2)*normal[0]+
+				(ONETHIRD*(h1-h2)*(vy1-vy2)+0.5*h2*(vy1-vy2)+0.5*(h1-h2)*vy2+h2*vy2)*normal[1]
+				);
+	return mass_flux;
+}
+/*}}}*/
+/*FUNCTION Tria::Misfit {{{1*/
+double Tria::Misfit(int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* output: */
+	double Jelem=0;
+
+	/* node data: */
+	const int    numgrids=3;
+	const int    numdof=2*numgrids;
+	const int    NDOF2=2;
+	int          dofs1[1]={0};
+	int          dofs2[2]={0,1};
+	double       xyz_list[numgrids][3];
+
+	/* grid data: */
+	double vx_list[numgrids];
+	double vy_list[numgrids];
+	double obs_vx_list[numgrids];
+	double obs_vy_list[numgrids];
+	double misfit_list[numgrids];
+	double weights_list[numgrids];
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_l1l2l3[3];
+	double  gaussgrids[numgrids][numgrids]={{1,0,0},{0,1,0},{0,0,1}};
+
+	/* parameters: */
+	double  velocity_mag,obs_velocity_mag;
+	double  misfit;
+
+	/* Jacobian: */
+	double Jdet;
+
+	/*relative and logarithmic control method :*/
+	double scalex=1;
+	double scaley=1;
+	double S=0;
+	double fit=-1;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Matpar* matpar=NULL;
+	Matice* matice=NULL;
+
+	/*inputs: */
+	bool onwater;
+	
+	double  meanvel, epsvel;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+	matice=(Matice*)hmatice.delivers();
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+
+	/* Recover input data: */
+	inputs->GetParameterValue(&fit,FitEnum);
+	if(fit==3){
+		inputs->GetParameterValue(&S,SurfaceAreaEnum);
+	}
+	inputs->GetParameterValues(&obs_vx_list[0],&gaussgrids[0][0],3,VxObsEnum);
+	inputs->GetParameterValues(&obs_vy_list[0],&gaussgrids[0][0],3,VyObsEnum);
+	inputs->GetParameterValues(&vx_list[0],&gaussgrids[0][0],3,VxEnum);
+	inputs->GetParameterValues(&vy_list[0],&gaussgrids[0][0],3,VyEnum);
+	inputs->GetParameterValues(&weights_list[0],&gaussgrids[0][0],3,WeightsEnum);
+
+	/*retrieve some parameters: */
+	this->parameters->FindParam(&meanvel,MeanVelEnum);
+	this->parameters->FindParam(&epsvel,EpsVelEnum);
+	
+	/* Compute Misfit at the 3 nodes
+	 * Here we integrate linearized functions:
+	 *               
+	 * J(E) = int_E   sum_{i=1}^3  J_i Phi_i
+	 *
+	 * where J_i are the misfits at the 3 nodes of the triangle
+	 *       Phi_i is the nodal function (P1) with respect to 
+	 *       the vertex i
+	 */
+	if(fit==0){
+		/*We are using an absolute misfit:
+		 *
+		 *      1  [           2              2 ]
+		 * J = --- | (u - u   )  +  (v - v   )  |
+		 *      2  [       obs            obs   ]
+		 *
+		 */
+		for (i=0;i<numgrids;i++){
+			misfit_list[i]=0.5*(pow((vx_list[i]-obs_vx_list[i]),(double)2)+pow((vy_list[i]-obs_vy_list[i]),(double)2));
+		}
+	}
+	else if(fit==1){
+		/*We are using a relative misfit: 
+		 *                        
+		 *      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                      
+		 */
+		for (i=0;i<numgrids;i++){
+			scalex=pow(meanvel/(obs_vx_list[i]+epsvel),(double)2);
+			scaley=pow(meanvel/(obs_vy_list[i]+epsvel),(double)2);
+			if(obs_vx_list[i]==0)scalex=0;
+			if(obs_vy_list[i]==0)scaley=0;
+			misfit_list[i]=0.5*(scalex*pow((vx_list[i]-obs_vx_list[i]),2)+scaley*pow((vy_list[i]-obs_vy_list[i]),2));
+		}
+	}
+	else if(fit==2){
+		/*We are using a logarithmic misfit:
+		*                        
+		*                 [        vel + eps     ] 2
+		* J = 4 \bar{v}^2 | log ( -----------  ) |  
+		*                 [       vel   + eps    ]
+		*                            obs
+		*/
+		for (i=0;i<numgrids;i++){
+			velocity_mag=sqrt(pow(vx_list[i],(double)2)+pow(vy_list[i],(double)2))+epsvel; //epsvel to avoid velocity being nil.
+			obs_velocity_mag=sqrt(pow(obs_vx_list[i],(double)2)+pow(obs_vy_list[i],(double)2))+epsvel; //epsvel to avoid observed velocity being nil.
+			misfit_list[i]=4*pow(meanvel,(double)2)*pow(log(velocity_mag/obs_velocity_mag),(double)2);
+		}
+	}
+	else if(fit==3){
+		/*We are using an spacially average absolute misfit:
+		 *
+		 *      1                    2              2
+		 * J = ---  sqrt(  (u - u   )  +  (v - v   )  )
+		 *      S                obs            obs
+		 */
+		for (i=0;i<numgrids;i++){
+			misfit_list[i]=sqrt(pow(vx_list[i]-obs_vx_list[i],2)+pow(vy_list[i]-obs_vx_list[i],2))/S;
+		}
+	}
+	else if(fit==4){
+		/*We are using an logarithmic 2 misfit:
+		 *
+		 *      1            [        |u| + eps     2          |v| + eps     2  ]
+		 * J = --- \bar{v}^2 | log ( -----------  )   +  log ( -----------  )   |  
+		 *      2            [       |u    |+ eps              |v    |+ eps     ]
+		 *                              obs                       obs
+		 */
+		for (i=0;i<numgrids;i++){
+			misfit_list[i]=0.5*pow(meanvel,(double)2)*(
+			  pow(log((fabs(vx_list[i])+epsvel)/(fabs(obs_vx_list[i])+epsvel)),(double)2) +
+			  pow(log((fabs(vy_list[i])+epsvel)/(fabs(obs_vy_list[i])+epsvel)),(double)2) );
+		}
+	}
+	else{
+		/*Not supported yet! : */
+		ISSMERROR("%s%g","unsupported type of fit: ",fit);
+	}
+
+	/*Apply weights to misfits*/
+	for (i=0;i<numgrids;i++){
+		misfit_list[i]=weights_list[i]*misfit_list[i];
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_l1l2l3[0]=*(first_gauss_area_coord+ig); 
+		gauss_l1l2l3[1]=*(second_gauss_area_coord+ig);
+		gauss_l1l2l3[2]=*(third_gauss_area_coord+ig);
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant2d(&Jdet, &xyz_list[0][0],gauss_l1l2l3);
+
+		/*Compute misfit at gaussian point: */
+		GetParameterValue(&misfit, &misfit_list[0],gauss_l1l2l3);
+
+		/*compute Misfit*/
+		Jelem+=misfit*Jdet*gauss_weight;
+	}
+
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+		
+	/*Return: */
+	return Jelem;
+}
+/*}}}*/
+/*FUNCTION Tria::MyRank {{{1*/
+int    Tria::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Tria::Tria::SetClone {{{1*/
+void  Tria::SetClone(int* minranks){
+
+	ISSMERROR("not implemented yet");
+}
+/*}}}1*/
+/*FUNCTION Tria::SurfaceNormal{{{1*/
+
+void Tria::SurfaceNormal(double* surface_normal, double xyz_list[3][3]){
+
+	int i;
+	double v13[3];
+	double v23[3];
+	double normal[3];
+	double normal_norm;
+
+	for (i=0;i<3;i++){
+		v13[i]=xyz_list[0][i]-xyz_list[2][i];
+		v23[i]=xyz_list[1][i]-xyz_list[2][i];
+	}
+
+	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
+	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
+	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
+
+	normal_norm=sqrt( pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2) );
+
+	*(surface_normal)=normal[0]/normal_norm;
+	*(surface_normal+1)=normal[1]/normal_norm;
+	*(surface_normal+2)=normal[2]/normal_norm;
+
+}
+/*}}}*/
+/*FUNCTION Tria::SurfaceArea {{{1*/
+double Tria::SurfaceArea(int analysis_type,int sub_analysis_type){
+
+	int i;
+
+	/* output: */
+	double S;
+
+	/* node data: */
+	int numgrids=3;
+	double xyz_list[numgrids][3];
+	double v13[3];
+	double v23[3];
+	double normal[3];
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+
+	/*inputs: */
+	bool onwater;
+	int  fit;
+
+	/*retrieve inputs :*/
+	inputs->GetParameterValue(&fit,FitEnum);
+	inputs->GetParameterValue(&onwater,ElementOnWaterEnum);
+
+	/*If fit!=3, do not compute surface: */
+	if(fit!=3)return 0;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+
+	/*If on water, return 0: */
+	if(onwater)return 0;
+
+	/* Get node coordinates and dof list: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+
+	for (i=0;i<3;i++){
+		v13[i]=xyz_list[0][i]-xyz_list[2][i];
+		v23[i]=xyz_list[1][i]-xyz_list[2][i];
+	}
+
+	normal[0]=v13[1]*v23[2]-v13[2]*v23[1];
+	normal[1]=v13[2]*v23[0]-v13[0]*v23[2];
+	normal[2]=v13[0]*v23[1]-v13[1]*v23[0];
+
+	S = 0.5 * sqrt(pow(normal[0],(double)2)+pow(normal[1],(double)2)+pow(normal[2],(double)2));
+
+	/*Return: */
+	return S;
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Elements/Tria.h
===================================================================
--- /issm/trunk/src/c/objects/Elements/Tria.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Elements/Tria.h	(revision 3683)
@@ -0,0 +1,132 @@
+/*! \file Tria.h 
+ *  \brief: header file for tria object
+ */
+
+#ifndef _TRIA_H_
+#define _TRIA_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Element.h"
+class Hook;
+class Parameters;
+class Inputs;
+class IoModel;
+
+#include "../../include/macros.h"
+#include "../../shared/Exceptions/exceptions.h"
+/*}}}*/
+
+class Tria: public Element{
+
+	public:
+
+		int  id;
+
+		Hook hnodes;  //hook to 3 nodes
+		Hook hmatice; //hook to 1 matice
+		Hook hmatpar; //hook to 1 matpar
+
+		Parameters* parameters; //pointer to solution parameters
+		Inputs*  inputs;
+
+		/*FUNCTION constructors, destructors {{{1*/
+		Tria();
+		Tria(int tria_id,int* tria_node_ids, int tria_matice_id, int tria_matpar_id);
+		Tria(int tria_id,Hook* tria_hnodes, Hook* tria_hmatice, Hook* tria_hmatpar, Parameters* parameters, Inputs* tria_inputs);
+		Tria(int tria_id,int i, IoModel* iomodel);
+		~Tria();
+		/*}}}*/
+		/*FUNCTION object management {{{1*/
+		void  Configure(DataSet* loads,DataSet* nodes,DataSet* materials,Parameters* parameters);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		void  SetClone(int* minranks);
+		/*}}}*/
+		/*FUNCTION element numerical routines {{{1*/
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+				void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  GetDofList1(int* doflist);
+		void  CreateKMatrixDiagnosticHoriz(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixDiagnosticHorizFriction(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixDiagnosticSurfaceVert(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixSlopeCompute(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  GetParameterValue(double* pp, double* plist, double* gauss_l1l2l3);
+		void  GetParameterDerivativeValue(double* p, double* plist,double* xyz_list, double* gauss_l1l2l3);
+		void  GetStrainRate(double* epsilon, double* velocity, double* xyz_list, double* gauss_l1l2l3);
+		void  GetJacobianDeterminant2d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3);
+		void  GetJacobianDeterminant3d(double*  Jdet, double* xyz_list,double* gauss_l1l2l3);
+		void  GetB(double* B, double* xyz_list, double* gauss_l1l2l3);
+		void  GetBPrime(double* Bprime, double* xyz_list, double* gauss_l1l2l3);
+		void  GetL(double* L, double* xyz_list, double* gauss_l1l2l3,int numdof);
+		void  GetB_prog(double* B_prog, double* xyz_list, double* gauss_l1l2l3);
+		void  GetBPrime_prog(double* Bprime_prog, double* xyz_list, double* gauss_l1l2l3);
+		void  GetNodalFunctions(double* l1l2l3, double* gauss_l1l2l3);
+		void  GetNodalFunctionsDerivatives(double* dh1dh3,double* xyz_list, double* gauss_l1l2l3);
+		void  GetNodalFunctionsDerivativesReference(double* dl1dl3,double* gauss_l1l2l3);
+		void  GetJacobianInvert(double*  Jinv, double* xyz_list,double* gauss_l1l2l3);
+		void  GetJacobian(double* J, double* xyz_list,double* gauss_l1l2l3);
+		void  Du(Vec du_g,int analysis_type,int sub_analysis_type);
+		void  Gradj(Vec grad_g,int analysis_type,int sub_analysis_type,char* control_type);
+		void  GradjDrag(Vec grad_g,int analysis_type,int sub_analysis_type);
+		void  GradjDragStokes(Vec grad_g,int analysis_type,int sub_analysis_type);
+		void  SurfaceNormal(double* surface_normal, double xyz_list[3][3]);
+		void  GradjB(Vec grad_g,int analysis_type,int sub_analysis_type);
+		double Misfit(int analysis_type,int sub_analysis_type);
+		double SurfaceArea(int analysis_type,int sub_analysis_type);
+		double CostFunction(int analysis_type,int sub_analysis_type);
+
+		void  CreatePVectorDiagnosticHoriz(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticBaseVert(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorSlopeCompute( Vec pg,  int analysis_type,int sub_analysis_type);
+		void* GetMatPar();
+		bool  GetShelf();
+		void  GetNodes(void** nodes);
+		bool  GetOnBed();
+		void  GetThicknessList(double* thickness_list);
+		void  GetBedList(double* bed_list);
+		void  ComputeBasalStress(Vec sigma_b,int analysis_type,int sub_analysis_type);
+		void  ComputePressure(Vec p_g,int analysis_type,int sub_analysis_type);
+		void  ComputeStrainRate(Vec eps,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixThermal(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixMelting(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorThermalShelf( Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreatePVectorThermalSheet( Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixPrognostic(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorPrognostic(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixPrognostic2(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorPrognostic2(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBalancedthickness(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBalancedthickness(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBalancedthickness2(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBalancedthickness2(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBalancedvelocities(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBalancedvelocities(Vec pg,int analysis_type,int sub_analysis_type);
+		double MassFlux(double* segment,double* ug);
+		double GetArea(void);
+		double GetAreaCoordinate(double x, double y, int which_one);
+
+		/*updates:*/
+		void  UpdateFromDakota(void* inputs);
+		void  UpdateInputs(double* solution, int analysis_type, int sub_analysis_type);
+		void  UpdateInputsDiagnosticHoriz( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsSlopeCompute( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsPrognostic( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsPrognostic2(double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedthickness( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedthickness2( double* solution,int analysis_type,int sub_analysis_type);
+		void  UpdateInputsBalancedvelocities( double* solution,int analysis_type,int sub_analysis_type);
+		void  AddInput(double value, int enum_type){ISSMERROR("not supporte yet!");}
+
+		/*}}}*/
+
+};
+#endif  /* _TRIA_H */
Index: /issm/trunk/src/c/objects/Inputs/BeamVertexInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/BeamVertexInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/BeamVertexInput.cpp	(revision 3683)
@@ -0,0 +1,167 @@
+/*!\file BeamVertexInput.c
+ * \brief: implementation of the BeamVertexInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION BeamVertexInput::BeamVertexInput(){{{1*/
+BeamVertexInput::BeamVertexInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::BeamVertexInput(double* values){{{1*/
+BeamVertexInput::BeamVertexInput(int in_enum_type,double* in_values){
+
+	enum_type=in_enum_type;
+	values[0]=in_values[0];
+	values[1]=in_values[1];
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::~BeamVertexInput(){{{1*/
+BeamVertexInput::~BeamVertexInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION BeamVertexInput::copy{{{1*/
+Object* BeamVertexInput::copy() {
+	
+	return new BeamVertexInput(this->enum_type,this->values);
+
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::DeepEcho{{{1*/
+void BeamVertexInput::DeepEcho(void){
+
+	printf("BeamVertexInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g|%g\n",this->values[0],this->values[1]);
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::Demarshall{{{1*/
+void  BeamVertexInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&values,marshalled_dataset,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::Echo {{{1*/
+void BeamVertexInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::Enum{{{1*/
+int BeamVertexInput::Enum(void){
+
+	return BeamVertexInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::EnumType{{{1*/
+int BeamVertexInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::Id{{{1*/
+int    BeamVertexInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION BeamVertexInput::Marshall{{{1*/
+void  BeamVertexInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of BeamVertexInput: */
+	enum_value=BeamVertexInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall BeamVertexInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&values,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::MarshallSize{{{1*/
+int   BeamVertexInput::MarshallSize(){
+	
+	return sizeof(values)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum_value
+}
+/*}}}*/
+/*FUNCTION BeamVertexInput::MyRank{{{1*/
+int    BeamVertexInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION BeamVertexInput::GetParameterValue(bool* pvalue) {{{1*/
+void BeamVertexInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(int* pvalue){{{1*/
+void BeamVertexInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(double* pvalue){{{1*/
+void BeamVertexInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void BeamVertexInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void BeamVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void BeamVertexInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void BeamVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void BeamVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void BeamVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void BeamVertexInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BeamVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void BeamVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/BeamVertexInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/BeamVertexInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/BeamVertexInput.h	(revision 3683)
@@ -0,0 +1,59 @@
+/*! \file BeamVertexInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _BEAMVERTEXINPUT_H_
+#define _BEAMVERTEXINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+/*}}}*/
+
+
+class BeamVertexInput: public Input{
+
+	private: 
+		/*just hold 2 values for 2 vertices: */
+		int    enum_type;
+		double values[2];
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		BeamVertexInput();
+		BeamVertexInput(int enum_type,double* values);
+		~BeamVertexInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _BEAMVERTEXINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/BoolInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/BoolInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/BoolInput.cpp	(revision 3683)
@@ -0,0 +1,167 @@
+/*!\file BoolInput.c
+ * \brief: implementation of the BoolInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION BoolInput::BoolInput(){{{1*/
+BoolInput::BoolInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION BoolInput::BoolInput(double* values){{{1*/
+BoolInput::BoolInput(int in_enum_type,IssmBool in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION BoolInput::~BoolInput(){{{1*/
+BoolInput::~BoolInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION BoolInput::copy{{{1*/
+Object* BoolInput::copy() {
+	
+	return new BoolInput(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION BoolInput::DeepEcho{{{1*/
+void BoolInput::DeepEcho(void){
+
+	printf("BoolInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %s\n",value?"true":"false");
+}
+/*}}}*/
+/*FUNCTION BoolInput::Demarshall{{{1*/
+void  BoolInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION BoolInput::Echo {{{1*/
+void BoolInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION BoolInput::Enum{{{1*/
+int BoolInput::Enum(void){
+
+	return BoolInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION BoolInput::EnumType{{{1*/
+int BoolInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION BoolInput::Id{{{1*/
+int    BoolInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION BoolInput::Marshall{{{1*/
+void  BoolInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of BoolInput: */
+	enum_value=BoolInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall BoolInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION BoolInput::MarshallSize{{{1*/
+int   BoolInput::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION BoolInput::MyRank{{{1*/
+int    BoolInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION BoolInput::GetParameterValue(bool* pvalue) {{{1*/
+void BoolInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(int* pvalue){{{1*/
+void BoolInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(double* pvalue){{{1*/
+void BoolInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void BoolInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void BoolInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void BoolInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void BoolInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void BoolInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void BoolInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void BoolInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION BoolInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void BoolInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/BoolInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/BoolInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/BoolInput.h	(revision 3683)
@@ -0,0 +1,59 @@
+/*! \file BoolInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _BOOLINPUT_H_
+#define _BOOLINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+#include "../../include/types.h"
+/*}}}*/
+
+class BoolInput: public Input{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int    enum_type;
+		IssmBool value;
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		BoolInput();
+		BoolInput(int enum_type,IssmBool value);
+		~BoolInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _BOOLINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/DoubleInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/DoubleInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/DoubleInput.cpp	(revision 3683)
@@ -0,0 +1,167 @@
+/*!\file DoubleInput.c
+ * \brief: implementation of the DoubleInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION DoubleInput::DoubleInput(){{{1*/
+DoubleInput::DoubleInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleInput::DoubleInput(double* values){{{1*/
+DoubleInput::DoubleInput(int in_enum_type,IssmDouble in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION DoubleInput::~DoubleInput(){{{1*/
+DoubleInput::~DoubleInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION DoubleInput::copy{{{1*/
+Object* DoubleInput::copy() {
+	
+	return new DoubleInput(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION DoubleInput::DeepEcho{{{1*/
+void DoubleInput::DeepEcho(void){
+
+	printf("DoubleInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g\n",this->value);
+}
+/*}}}*/
+/*FUNCTION DoubleInput::Demarshall{{{1*/
+void  DoubleInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleInput::Echo {{{1*/
+void DoubleInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION DoubleInput::Enum{{{1*/
+int DoubleInput::Enum(void){
+
+	return DoubleInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION DoubleInput::EnumType{{{1*/
+int DoubleInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION DoubleInput::Id{{{1*/
+int    DoubleInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION DoubleInput::Marshall{{{1*/
+void  DoubleInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of DoubleInput: */
+	enum_value=DoubleInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall DoubleInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION DoubleInput::MarshallSize{{{1*/
+int   DoubleInput::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION DoubleInput::MyRank{{{1*/
+int    DoubleInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION DoubleInput::GetParameterValue(bool* pvalue) {{{1*/
+void DoubleInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(int* pvalue){{{1*/
+void DoubleInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(double* pvalue){{{1*/
+void DoubleInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void DoubleInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void DoubleInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void DoubleInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void DoubleInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void DoubleInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void DoubleInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void DoubleInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION DoubleInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void DoubleInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/DoubleInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/DoubleInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/DoubleInput.h	(revision 3683)
@@ -0,0 +1,59 @@
+/*! \file DoubleInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _DOUBLEINPUT_H_
+#define _DOUBLEINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+#include "../../include/types.h"
+/*}}}*/
+
+class DoubleInput: public Input{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int    enum_type;
+		IssmDouble value;
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		DoubleInput();
+		DoubleInput(int enum_type,IssmDouble value);
+		~DoubleInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _DOUBLEINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/Input.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/Input.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/Input.h	(revision 3683)
@@ -0,0 +1,42 @@
+/*!\file:  Input.h
+ * \brief abstract class for Input object
+ */ 
+
+
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "../Object.h"
+class Node;
+#include "../Node.h"
+/*}}}*/
+
+class Input: public Object{
+
+	public: 
+		
+		virtual        ~Input(){};
+		virtual int    Enum()=0; //object Enum
+		virtual int    EnumType()=0; //type of input (vx,vy?)
+
+		/*methods:{{{1*/
+		virtual void GetParameterValue(bool* pvalue)=0;
+		virtual void GetParameterValue(int* pvalue)=0;
+		virtual void GetParameterValue(double* pvalue)=0;
+		virtual void GetParameterValue(double* pvalue,Node* node)=0;
+		virtual void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord)=0;
+		virtual void GetParameterValue(double* pvalue,double* gauss)=0;
+		virtual void GetParameterValue(double* pvalue,double* gauss,double defaultvalue)=0;
+		
+		virtual void GetParameterValues(double* values,double* gauss_pointers, int numgauss)=0;
+	
+		virtual void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss)=0;
+		virtual void GetStrainRate(double* epsilon, Input* yinput, double* xyz_list, double* gauss)=0;
+		virtual void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss)=0;
+
+		/*}}}*/
+
+};
+#endif
Index: /issm/trunk/src/c/objects/Inputs/IntInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/IntInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/IntInput.cpp	(revision 3683)
@@ -0,0 +1,167 @@
+/*!\file IntInput.c
+ * \brief: implementation of the IntInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION IntInput::IntInput(){{{1*/
+IntInput::IntInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION IntInput::IntInput(double* values){{{1*/
+IntInput::IntInput(int in_enum_type,IssmInt in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION IntInput::~IntInput(){{{1*/
+IntInput::~IntInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION IntInput::copy{{{1*/
+Object* IntInput::copy() {
+	
+	return new IntInput(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION IntInput::DeepEcho{{{1*/
+void IntInput::DeepEcho(void){
+
+	printf("IntInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %i\n",this->value);
+}
+/*}}}*/
+/*FUNCTION IntInput::Demarshall{{{1*/
+void  IntInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION IntInput::Echo {{{1*/
+void IntInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION IntInput::Enum{{{1*/
+int IntInput::Enum(void){
+
+	return IntInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION IntInput::EnumType{{{1*/
+int IntInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION IntInput::Id{{{1*/
+int    IntInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION IntInput::Marshall{{{1*/
+void  IntInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of IntInput: */
+	enum_value=IntInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall IntInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION IntInput::MarshallSize{{{1*/
+int   IntInput::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION IntInput::MyRank{{{1*/
+int    IntInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION IntInput::GetParameterValue(bool* pvalue) {{{1*/
+void IntInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(int* pvalue){{{1*/
+void IntInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(double* pvalue){{{1*/
+void IntInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void IntInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void IntInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void IntInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void IntInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void IntInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void IntInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void IntInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION IntInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void IntInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/IntInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/IntInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/IntInput.h	(revision 3683)
@@ -0,0 +1,60 @@
+/*! \file IntInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _INTINPUT_H_
+#define _INTINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+#include "../../include/types.h"
+/*}}}*/
+
+class IntInput: public Input{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int    enum_type;
+		IssmInt value;
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		IntInput();
+		IntInput(int enum_type,IssmInt value);
+		~IntInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+
+		/*}}}*/
+
+};
+#endif  /* _INTINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/PentaVertexInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/PentaVertexInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/PentaVertexInput.cpp	(revision 3683)
@@ -0,0 +1,171 @@
+/*!\file PentaVertexInput.c
+ * \brief: implementation of the PentaVertexInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION PentaVertexInput::PentaVertexInput(){{{1*/
+PentaVertexInput::PentaVertexInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::PentaVertexInput(double* values){{{1*/
+PentaVertexInput::PentaVertexInput(int in_enum_type,double* in_values){
+
+	enum_type=in_enum_type;
+	values[0]=in_values[0];
+	values[1]=in_values[1];
+	values[2]=in_values[2];
+	values[3]=in_values[3];
+	values[4]=in_values[4];
+	values[5]=in_values[5];
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::~PentaVertexInput(){{{1*/
+PentaVertexInput::~PentaVertexInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION PentaVertexInput::copy{{{1*/
+Object* PentaVertexInput::copy() {
+	
+	return new PentaVertexInput(this->enum_type,this->values);
+
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::DeepEcho{{{1*/
+void PentaVertexInput::DeepEcho(void){
+
+	printf("PentaVertexInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g|%g|%g|%g|%g|%g\n",this->values[0],this->values[1],this->values[2],this->values[3],this->values[4],this->values[5]);
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::Demarshall{{{1*/
+void  PentaVertexInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&values,marshalled_dataset,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::Echo {{{1*/
+void PentaVertexInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::Enum{{{1*/
+int PentaVertexInput::Enum(void){
+
+	return PentaVertexInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::EnumType{{{1*/
+int PentaVertexInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::Id{{{1*/
+int    PentaVertexInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION PentaVertexInput::Marshall{{{1*/
+void  PentaVertexInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of PentaVertexInput: */
+	enum_value=PentaVertexInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall PentaVertexInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&values,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::MarshallSize{{{1*/
+int   PentaVertexInput::MarshallSize(){
+	
+	return sizeof(values)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION PentaVertexInput::MyRank{{{1*/
+int    PentaVertexInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION PentaVertexInput::GetParameterValue(bool* pvalue) {{{1*/
+void PentaVertexInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(int* pvalue){{{1*/
+void PentaVertexInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(double* pvalue){{{1*/
+void PentaVertexInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void PentaVertexInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void PentaVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void PentaVertexInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void PentaVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void PentaVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void PentaVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void PentaVertexInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION PentaVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void PentaVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/PentaVertexInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/PentaVertexInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/PentaVertexInput.h	(revision 3683)
@@ -0,0 +1,58 @@
+/*! \file PentaVertexInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _PENTAVERTEXINPUT_H_
+#define _PENTAVERTEXINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+/*}}}*/
+
+class PentaVertexInput: public Input{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int    enum_type;
+		double values[6];
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		PentaVertexInput();
+		PentaVertexInput(int enum_type,double* values);
+		~PentaVertexInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _PENTAVERTEXINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/SingVertexInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/SingVertexInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/SingVertexInput.cpp	(revision 3683)
@@ -0,0 +1,166 @@
+/*!\file SingVertexInput.c
+ * \brief: implementation of the SingVertexInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION SingVertexInput::SingVertexInput(){{{1*/
+SingVertexInput::SingVertexInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::SingVertexInput(double* values){{{1*/
+SingVertexInput::SingVertexInput(int in_enum_type,double in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::~SingVertexInput(){{{1*/
+SingVertexInput::~SingVertexInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION SingVertexInput::copy{{{1*/
+Object* SingVertexInput::copy() {
+	
+	return new SingVertexInput(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::DeepEcho{{{1*/
+void SingVertexInput::DeepEcho(void){
+
+	printf("SingVertexInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g\n",this->value);
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::Demarshall{{{1*/
+void  SingVertexInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::Echo {{{1*/
+void SingVertexInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::Enum{{{1*/
+int SingVertexInput::Enum(void){
+
+	return SingVertexInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::EnumType{{{1*/
+int SingVertexInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::Id{{{1*/
+int    SingVertexInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION SingVertexInput::Marshall{{{1*/
+void  SingVertexInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of SingVertexInput: */
+	enum_value=SingVertexInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall SingVertexInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::MarshallSize{{{1*/
+int   SingVertexInput::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION SingVertexInput::MyRank{{{1*/
+int    SingVertexInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION SingVertexInput::GetParameterValue(bool* pvalue) {{{1*/
+void SingVertexInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(int* pvalue){{{1*/
+void SingVertexInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(double* pvalue){{{1*/
+void SingVertexInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void SingVertexInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void SingVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void SingVertexInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void SingVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void SingVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void SingVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void SingVertexInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION SingVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void SingVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/SingVertexInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/SingVertexInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/SingVertexInput.h	(revision 3683)
@@ -0,0 +1,58 @@
+/*! \file SingVertexInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _SINGVERTEXINPUT_H_
+#define _SINGVERTEXINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+/*}}}*/
+
+class SingVertexInput: public Input{
+
+	private: 
+		/*just hold 1 value for 1 vertex: */
+		int    enum_type;
+		double value;
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		SingVertexInput();
+		SingVertexInput(int enum_type,double value);
+		~SingVertexInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _SINGVERTEXINPUT_H */
Index: /issm/trunk/src/c/objects/Inputs/TriaVertexInput.cpp
===================================================================
--- /issm/trunk/src/c/objects/Inputs/TriaVertexInput.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/TriaVertexInput.cpp	(revision 3683)
@@ -0,0 +1,168 @@
+/*!\file TriaVertexInput.c
+ * \brief: implementation of the TriaVertexInput object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION TriaVertexInput::TriaVertexInput(){{{1*/
+TriaVertexInput::TriaVertexInput(){
+	return;
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::TriaVertexInput(double* values){{{1*/
+TriaVertexInput::TriaVertexInput(int in_enum_type,double* in_values){
+
+	enum_type=in_enum_type;
+	values[0]=in_values[0];
+	values[1]=in_values[1];
+	values[2]=in_values[2];
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::~TriaVertexInput(){{{1*/
+TriaVertexInput::~TriaVertexInput(){
+	return;
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION TriaVertexInput::copy{{{1*/
+Object* TriaVertexInput::copy() {
+	
+	return new TriaVertexInput(this->enum_type,this->values);
+
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::DeepEcho{{{1*/
+void TriaVertexInput::DeepEcho(void){
+
+	printf("TriaVertexInput:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g|%g|%g\n",this->values[0],this->values[1],this->values[2]);
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::Demarshall{{{1*/
+void  TriaVertexInput::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&values,marshalled_dataset,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::Echo {{{1*/
+void TriaVertexInput::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::Enum{{{1*/
+int TriaVertexInput::Enum(void){
+
+	return TriaVertexInputEnum;
+
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::EnumType{{{1*/
+int TriaVertexInput::EnumType(void){
+
+	return this->enum_type;
+
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::Id{{{1*/
+int    TriaVertexInput::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION TriaVertexInput::Marshall{{{1*/
+void  TriaVertexInput::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of TriaVertexInput: */
+	enum_value=TriaVertexInputEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall TriaVertexInput data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&values,sizeof(values));marshalled_dataset+=sizeof(values);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::MarshallSize{{{1*/
+int   TriaVertexInput::MarshallSize(){
+	
+	return sizeof(values)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION TriaVertexInput::MyRank{{{1*/
+int    TriaVertexInput::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION TriaVertexInput::GetParameterValue(bool* pvalue) {{{1*/
+void TriaVertexInput::GetParameterValue(bool* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(int* pvalue){{{1*/
+void TriaVertexInput::GetParameterValue(int* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(double* pvalue){{{1*/
+void TriaVertexInput::GetParameterValue(double* pvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(double* pvalue,Node* node){{{1*/
+void TriaVertexInput::GetParameterValue(double* pvalue,Node* node){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){{{1*/
+void TriaVertexInput::GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(double* pvalue,double* gauss){{{1*/
+void TriaVertexInput::GetParameterValue(double* pvalue,double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){{{1*/
+void TriaVertexInput::GetParameterValue(double* pvalue,double* gauss,double defaultvalue){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){{{1*/
+void TriaVertexInput::GetParameterValues(double* values,double* gauss_pointers, int numgauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){{{1*/
+void TriaVertexInput::GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss){{{1*/
+void TriaVertexInput::GetStrainRate(double* epsilon,Input* yinput,double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
+/*FUNCTION TriaVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss){{{1*/
+void TriaVertexInput::GetStrainRateStokes(double* epsilon,Input* yinput,Input* zinput, double* xyz_list, double* gauss){ISSMERROR(" not supported yet!");}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Inputs/TriaVertexInput.h
===================================================================
--- /issm/trunk/src/c/objects/Inputs/TriaVertexInput.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Inputs/TriaVertexInput.h	(revision 3683)
@@ -0,0 +1,58 @@
+/*! \file TriaVertexInput.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _TRIAVERTEXINPUT_H_
+#define _TRIAVERTEXINPUT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Input.h"
+/*}}}*/
+
+class TriaVertexInput: public Input{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int    enum_type;
+		double values[3];
+
+	public:
+
+		/*constructors, destructors: {{{1*/
+		TriaVertexInput();
+		TriaVertexInput(int enum_type,double* values);
+		~TriaVertexInput();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  DeepEcho();
+		void  Echo();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   MyRank();
+		Object* copy();
+		int   EnumType();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void GetParameterValue(bool* pvalue);
+		void GetParameterValue(int* pvalue);
+		void GetParameterValue(double* pvalue);
+		void GetParameterValue(double* pvalue,Node* node);
+		void GetParameterValue(double* pvalue,Node* node1,Node* node2,double gauss_coord);
+		void GetParameterValue(double* pvalue,double* gauss);
+		void GetParameterValue(double* pvalue,double* gauss,double defaultvalue);
+		
+		void GetParameterValues(double* values,double* gauss_pointers, int numgauss);
+	
+		void GetParameterDerivativeValue(double* derivativevalues, double* xyz_list, double* gauss);
+		void GetStrainRate(double* epsilon,Input* yinput, double* xyz_list, double* gauss);
+		void GetStrainRateStokes(double* epsilon,Input* yinput, Input* zinput, double* xyz_list, double* gauss);
+		/*}}}*/
+
+};
+#endif  /* _TRIAVERTEXINPUT_H */
Index: /issm/trunk/src/c/objects/Loads/Friction.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Friction.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Friction.cpp	(revision 3683)
@@ -0,0 +1,195 @@
+/*!\file: Friction.cpp
+ * \brief: wrapper for all friction parameters
+ */ 
+
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+
+/*--------------------------------------------------
+	NewFriction
+  --------------------------------------------------*/
+
+/*FUNCTION NewFriction{{{1*/
+Friction* NewFriction(void)
+{
+	/* create a new Friction object */
+
+	return (Friction*)xmalloc(sizeof(Friction));
+}
+/*}}}*/
+/*FUNCTION FrictionEcho{{{1*/
+void  FrictionEcho(Friction* friction){
+
+	int i;
+	
+	printf("Friction echo: \n");
+	printf("   element_type: %s\n",friction->element_type);
+	printf("   gravity: %g\n",friction->gravity);
+	printf("   rho_ice: %g\n",friction->rho_ice);
+	printf("   rho_water: %g\n",friction->rho_water);
+	printf("   p: %g\n",friction->p);
+	printf("   q: %g\n",friction->q);
+	printf("   analysis_type: %i\n",friction->analysis_type);
+
+	printf("K: ");
+	for(i=0;i<3;i++)printf("%g ",friction->K[i]);
+	printf("\n");
+
+	printf("bed: ");
+	for(i=0;i<3;i++)printf("%g ",friction->bed[i]);
+	printf("\n");
+
+	printf("thickness: ");
+	for(i=0;i<3;i++)printf("%g ",friction->thickness[i]);
+	printf("\n");
+
+	printf("vx: ");
+	for(i=0;i<3;i++)printf("%g ",friction->vx[i]);
+	printf("\n            ");
+	printf("vy: ");
+	for(i=0;i<3;i++)printf("%g ",friction->vy[i]);
+	printf("\n");
+	if(friction->vz){
+		printf("vz: ");
+		for(i=0;i<3;i++)printf("%g ",friction->vz[i]);
+		printf("\n");
+	}
+
+}
+/*}}}*/
+/*FUNCTION FrictionInit {{{1*/
+/*--------------------------------------------------
+	FrictionInit
+  --------------------------------------------------*/
+
+int FrictionInit(Friction* friction)
+{
+	friction->element_type=NULL;
+	friction->gravity=UNDEF;
+	friction->rho_ice=UNDEF;
+	friction->rho_water=UNDEF;
+	friction->K=NULL; 
+	friction->bed=NULL;
+	friction->thickness=NULL;
+	friction->vx=NULL;
+	friction->vy=NULL;
+	friction->vz=NULL;
+	friction->p=UNDEF;
+	friction->q=UNDEF;
+	friction->analysis_type=UNDEF;
+	
+	return 1;
+}
+/*}}}*/
+/*FUNCTION DeleteFriction {{{1*/
+/*--------------------------------------------------
+	DeleteFriction
+  --------------------------------------------------*/
+
+void DeleteFriction(Friction** pfriction)
+{
+	Friction* friction = *pfriction;
+
+	/*Just  erase element_type: */
+	xfree((void**)&friction->element_type);
+
+	/*Erase entire structure: */
+	xfree((void**)pfriction);
+}
+/*}}}*/
+/*FUNCTION FrictionGetAlpha2 {{{1*/
+/*--------------------------------------------------
+	FrictionGetAlpha2
+  --------------------------------------------------*/
+void  FrictionGetAlpha2(double* alpha2, Friction* friction){
+
+	/*This routine calculates the basal friction coefficient 
+	alpha2= drag^2 * Neff ^r * vel ^s, with Neff=rho_ice*g*thickness+rho_ice*g*bed, r=q/p and s=1/p*
+	alpha2 is assumed to be double[3]: */
+
+	/*diverse: */
+	int     i;
+	const int     numgrids=3;
+	double  Neff[numgrids];
+	double  r,s;
+	double  velocity_x[numgrids];
+	double  velocity_y[numgrids];
+	double  velocity_z[numgrids];
+	double  velocity_mag[numgrids];
+
+	//compute r and q coefficients: */
+	r=friction->q/friction->p;
+	s=1./friction->p;
+		
+	//From bed and thickness, compute effective pressure when drag is viscous:
+	for(i=0;i<numgrids;i++){
+
+		Neff[i]=friction->gravity*(friction->rho_ice*friction->thickness[i]+friction->rho_water*friction->bed[i]);
+
+		/*If effective pressure becomes negative, sliding becomes unstable (Paterson 4th edition p 148). This is because 
+		the water pressure is so high, the ice sheet elevates over its ice bumps and slides. But the limit behaviour 
+		for friction should be an ice shelf sliding (no basal drag). Therefore, for any effective pressure Neff < 0, we should 
+		replace it by Neff=0 (ie, equival it to an ice shelf)*/
+		if (Neff[i]<0)Neff[i]=0;
+
+		//We need the velocity magnitude to evaluate the basal stress:
+		if(strcmp(friction->element_type,"2d")){
+			velocity_x[i]=friction->vx[i];//velocities of size numgridsx2
+			velocity_y[i]=friction->vy[i];
+			velocity_mag[i]=sqrt(pow(velocity_x[i],2)+pow(velocity_y[i],2));
+		}
+		else{
+			velocity_x[i]=friction->vx[i]; //velocities of size numgridsx3
+			velocity_y[i]=friction->vy[i];
+			velocity_z[i]=friction->vz[i];
+			velocity_mag[i]=sqrt(pow(velocity_x[i],2)+pow(velocity_y[i],2)+pow(velocity_z[i],2));
+		}
+	
+		alpha2[i]=pow(friction->K[i],2)*pow(Neff[i],r)*pow(velocity_mag[i],(s-1));
+	}
+}
+/*}}}*/
+/*FUNCTION FrictionGetAlphaComplement {{{1*/
+/*--------------------------------------------------
+	FrictionGetAlphaComplement
+  --------------------------------------------------*/
+void  FrictionGetAlphaComplement(double* alpha_complement, Friction* friction){
+
+	/* FrictionGetAlpha2 computes alpha2= drag^2 * Neff ^r * vel ^s, with Neff=rho_ice*g*thickness+rho_ice*g*bed, r=q/p and s=1/p. 
+	 * FrictionGetAlphaComplement is used in control methods on drag, and it computes: 
+	 * alpha_complement= Neff ^r * vel ^s*/
+
+	/*diverse: */
+	int     i;
+	const int     numgrids=3;
+	double  Neff[numgrids];
+	double  r,s;
+	double  velocity_x[numgrids];
+	double  velocity_y[numgrids];
+	double  velocity_mag[numgrids];
+
+	//compute r and q coefficients: */
+	r=friction->q/friction->p;
+	s=1./friction->p;
+		
+	//From bed and thickness, compute effective pressure when drag is viscous:
+	for(i=0;i<numgrids;i++){
+
+		Neff[i]=friction->gravity*(friction->rho_ice*friction->thickness[i]+friction->rho_water*friction->bed[i]);
+
+		/*If effective pressure becomes negative, sliding becomes unstable (Paterson 4th edition p 148). This is because 
+		the water pressure is so high, the ice sheet elevates over its ice bumps and slides. But the limit behaviour 
+		for friction should be an ice shelf sliding (no basal drag). Therefore, for any effective pressure Neff < 0, we should 
+		replace it by Neff=0 (ie, equival it to an ice shelf)*/
+		if (Neff[i]<0)Neff[i]=0;
+
+		//We need the velocity magnitude to evaluate the basal stress:
+		velocity_x[i]=friction->vx[i]; //velocities of size numgridsx2
+		velocity_y[i]=friction->vy[i];
+		velocity_mag[i]=sqrt(pow(velocity_x[i],2)+pow(velocity_y[i],2));
+	
+		alpha_complement[i]=pow(Neff[i],r)*pow(velocity_mag[i],(s-1));
+	}
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Loads/Friction.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Friction.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Friction.h	(revision 3683)
@@ -0,0 +1,38 @@
+/*! \file Friction.h
+ *  \brief Friction object, interface, declaration
+ */
+
+#ifndef _FRICTION_H
+#define _FRICTION_H
+
+/*!Friction declaration: */
+struct Friction {
+
+	char*   element_type;
+	double  gravity;
+	double  rho_ice;
+	double  rho_water;
+	double* K;
+	double* bed;
+	double* thickness;
+	double* vx;
+	double* vy;
+	double* vz;
+	double  p;
+	double  q;
+	int     analysis_type;
+
+};
+
+
+/* creation, initialisation: */
+
+	Friction*	NewFriction(void);
+	int	FrictionInit(Friction* friction);
+	void  DeleteFriction(Friction** pfriction);
+	void  FrictionGetAlpha2(double* alpha2, Friction* friction);
+	void  FrictionGetAlphaComplement(double* alpha_complement, Friction* friction);
+	void  FrictionEcho(Friction* friction);
+
+#endif  /* _FRICTION_H */
+
Index: /issm/trunk/src/c/objects/Loads/Icefront.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Icefront.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Icefront.cpp	(revision 3683)
@@ -0,0 +1,1342 @@
+/*!\file Icefront.c
+ * \brief: implementation of the Icefront object
+ */
+
+/*Headers:*/
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/	
+
+/*Object constructors and destructor*/
+/*FUNCTION Icefront::Icefront() {{{1*/
+Icefront::Icefront(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Icefront::Icefront(int id, int* node_ids, int numnodes, int element_id, int matpar_id){{{1*/
+Icefront::Icefront(int icefront_id,int* icefront_node_ids, int icefront_numnodes, int icefront_element_id, int icefront_matpar_id): 
+	hnodes(icefront_node_ids,icefront_numnodes),
+	helement(&icefront_element_id,1),
+	hmatpar(&icefront_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id : */
+	this->id=icefront_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+}
+/*}}}*/
+/*FUNCTION Icefront::Icefront(int id, Hook* hnodes, Hook* helement, Hook* hmatpar, Parameters* parameters, Inputs* icefront_inputs) {{{1*/
+Icefront::Icefront(int icefront_id,Hook* icefront_hnodes, Hook* icefront_helement, Hook* icefront_hmatpar, Parameters* icefront_parameters, Inputs* icefront_inputs):
+	hnodes(icefront_hnodes),
+	helement(icefront_helement),
+	hmatpar(icefront_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=icefront_id;
+	if(icefront_inputs){
+		this->inputs=(Inputs*)icefront_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=icefront_parameters;
+}
+/*}}}*/
+/*FUNCTION Icefront::Icefront(int id, int i, IoModel* iomodel) {{{1*/
+Icefront::Icefront(int icefront_id,int i, IoModel* iomodel){
+
+	int segment_width;
+	int element;
+	int num_nodes;
+
+	/*icefront constructor data: */
+	int  icefront_eid;
+	int  icefront_mparid;
+	int  icefront_node_ids[MAX_ICEFRONT_GRIDS];
+	int  icefront_fill;
+	int  icefront_type;
+
+	/*First, retrieve element index and element type: */
+	if (strcmp(iomodel->meshtype,"2d")==0){
+		segment_width=4;
+	}
+	else{
+		segment_width=6;
+	}
+	element=(int)(*(iomodel->pressureload+segment_width*i+segment_width-2)-1); //element is in the penultimate column (grid1 grid2 ... elem fill)
+
+	/*Build ids for hook constructors: */
+	icefront_eid=(int) *(iomodel->pressureload+segment_width*i+segment_width-2); //matlab indexing
+	icefront_mparid=iomodel->numberofelements+1; //matlab indexing
+
+	icefront_node_ids[0]=(int)*(iomodel->pressureload+segment_width*i+0);
+	icefront_node_ids[1]=(int)*(iomodel->pressureload+segment_width*i+1);
+
+	if (iomodel->sub_analysis_type==HorizAnalysisEnum){
+		if ((int)*(iomodel->elements_type+2*element+0)==MacAyealFormulationEnum){ //this is a collapsed 3d element, icefront will be 2d
+			icefront_type=SegmentIcefrontEnum;
+		}
+		else if ((int)*(iomodel->elements_type+2*element+0)==PattynFormulationEnum){ //this is a real 3d element, icefront will be 3d.
+			icefront_type=QuadIceFrontEnum;
+			icefront_node_ids[2]=(int)*(iomodel->pressureload+segment_width*i+2);
+			icefront_node_ids[3]=(int)*(iomodel->pressureload+segment_width*i+3);
+		}
+		else ISSMERROR(" element type %i not supported yet",(int)*(iomodel->elements_type+2*element+0));
+	}
+	else if (iomodel->sub_analysis_type==StokesAnalysisEnum){
+		//We have a Stokes element, so we need a 3d Icefront
+		icefront_type=QuadIceFrontEnum;
+		icefront_node_ids[2]=(int)*(iomodel->pressureload+segment_width*i+2);
+		icefront_node_ids[3]=(int)*(iomodel->pressureload+segment_width*i+3);
+	}
+	else ISSMERROR("Not supported yet!");
+
+	if (icefront_type==QuadIceFrontEnum) num_nodes=4;
+	else num_nodes=2;
+	icefront_fill=(int)*(iomodel->pressureload+segment_width*i+segment_width-1); 
+	
+	/*Ok, we have everything to build the object: */
+	this->id=icefront_id;
+
+	/*Hooks: */
+	this->hnodes.Init(icefront_node_ids,num_nodes);
+	this->helement.Init(&icefront_eid,1);
+	this->hmatpar.Init(&icefront_mparid,1);
+
+	//intialize  and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+	this->inputs->AddInput(new IntInput(FillEnum,icefront_fill));
+	this->inputs->AddInput(new IntInput(TypeEnum,icefront_type));
+	
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+}
+
+
+/*}}}*/
+/*FUNCTION Icefront::~Icefront() {{{1*/
+Icefront::~Icefront(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object marshall*/
+/*FUNCTION Icefront Configure {{{1*/
+void  Icefront::Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin){
+
+	/*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: */
+	hnodes.configure(nodesin);
+	helement.configure(elementsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+}
+/*}}}*/
+/*FUNCTION Icefront copy {{{1*/
+Object* Icefront::copy() {
+	return new Icefront(this->id,&this->hnodes,&this->helement,&this->hmatpar,this->parameters,this->inputs);
+}
+/*}}}*/
+/*FUNCTION Icefront::DeepEcho{{{1*/
+void Icefront::DeepEcho(void){
+
+	printf("Icefront:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	helement.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Icefront::Demarshall {{{1*/
+void  Icefront::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	helement.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+	
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Icefront Echo {{{1*/
+void Icefront::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Icefront Enum {{{1*/
+int Icefront::Enum(void){
+
+	return IcefrontEnum;
+
+}
+/*}}}*/
+/*FUNCTION Icefront Id {{{1*/
+int    Icefront::Id(void){ return id; }
+/*}}}*/
+/*FUNCTION Icefront::Marshall {{{1*/
+void  Icefront::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Icefront: */
+	enum_type=IcefrontEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Icefront data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	helement.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION Icefront::MarshallSize {{{1*/
+int   Icefront::MarshallSize(){
+	
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+helement.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Icefront MyRank {{{1*/
+int    Icefront::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION Icefront CreateKMatrix {{{1*/
+
+void  Icefront::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*No stiffness loads applied, do nothing: */
+
+	return;
+
+}
+/*}}}*/
+/*FUNCTION Icefront CreatePVector {{{1*/
+void  Icefront::CreatePVector(Vec pg, int analysis_type,int sub_analysis_type){
+
+	/*Just branch to the correct element icefront vector generator, according to the type of analysis we are carrying out: */
+	if (analysis_type==ControlAnalysisEnum){
+		
+		CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+	
+		if (sub_analysis_type==HorizAnalysisEnum){
+		
+			CreatePVectorDiagnosticHoriz( pg,analysis_type,sub_analysis_type);
+
+		}
+		else if (sub_analysis_type==StokesAnalysisEnum){
+			
+			CreatePVectorDiagnosticStokes( pg,analysis_type,sub_analysis_type);
+
+		}
+		else ISSMERROR("%s%i%s"," sub_analysis_type: ",sub_analysis_type," not supported yet");
+
+	}
+	else{
+		ISSMERROR("%s%i%s"," analysis ",analysis_type," not supported yet");
+	}
+}
+/*}}}*/
+/*FUNCTION Icefront CreatePVectorDiagnosticHoriz {{{1*/
+void Icefront::CreatePVectorDiagnosticHoriz( Vec pg,  int analysis_type,int sub_analysis_type){
+	
+	int type;
+	inputs->GetParameterValue(&type,TypeEnum);
+
+	/*Branck on the type of icefront: */
+	if (type==SegmentIcefrontEnum){
+		CreatePVectorDiagnosticHorizSegment(pg,analysis_type,sub_analysis_type);
+	}
+	else{
+		CreatePVectorDiagnosticHorizQuad(pg,analysis_type,sub_analysis_type);
+	}
+}	
+/*}}}*/
+/*FUNCTION Icefront CreatePVectorDiagnosticHorizSegment{{{1*/
+void Icefront::CreatePVectorDiagnosticHorizSegment( Vec pg,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+	
+	const int numgrids=2;
+	const int NDOF2=2;
+	int   numberofdofspernode;
+	const int numdofs=numgrids*NDOF2;
+	int   doflist[numdofs];
+	double xyz_list[numgrids][3];
+
+	double x1,y1,x2,y2;
+
+	/* input parameters: */
+	double thickness_list_element[6];
+	double thickness_list[2];
+	double bed_list_element[6];
+	double bed_list[2];
+	
+	int    grid1,grid2;
+	double normal[2];
+	double length;
+	int    element_type;
+
+	/*Objects: */
+	double  pe_g[numdofs]={0.0};
+	Matpar*  matpar=NULL;
+	Node**   element_nodes=NULL;
+	Node**   nodes=NULL;
+	Element* element=NULL;
+
+	/*Recover hook objects: */
+	matpar=(Matpar*)hmatpar.delivers();
+	element=(Element*)helement.delivers();
+	nodes=(Node**)hnodes.deliverp();
+
+	element_type=element->Enum();
+
+	//check that the element is onbed (collapsed formulation) otherwise:pe=0
+	if(element_type==PentaEnum){
+		if  (!element->GetOnBed()){
+			return;
+		}
+	}
+		
+	/*Identify which grids are comprised in the segment. */
+	if(element_type==TriaEnum)element_nodes=(Node**)xmalloc(3*sizeof(Node*));
+	if(element_type==PentaEnum)element_nodes=(Node**)xmalloc(6*sizeof(Node*));
+	element->GetNodes((void**)element_nodes);
+
+	/*go through first 3 grids (all grids for tria, bed grids for penta) and identify 1st and 2nd grid: */
+	for(i=0;i<3;i++){
+		if (nodes[0]==element_nodes[i])grid1=i;
+		if (nodes[1]==element_nodes[i])grid2=i;
+	}
+	
+	/* Get dof list and node coordinates: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	
+	/*Now build thickness_list_element and bed_list_element: */
+	element->GetThicknessList(&thickness_list_element[0]);
+	element->GetBedList(&bed_list_element[0]);
+		
+	/*Build thickness_list and bed_list: */
+	thickness_list[0]=thickness_list_element[grid1];
+	thickness_list[1]=thickness_list_element[grid2];
+	bed_list[0]=bed_list_element[grid1];
+	bed_list[1]=bed_list_element[grid2];
+
+	//Recover grid coordinates
+	x1=xyz_list[0][0];
+	y1=xyz_list[0][1];
+	x2=xyz_list[1][0];
+	y2=xyz_list[1][1];
+
+	//Compute length and normal of segment
+	normal[0]=cos(atan2(x1-x2,y2-y1));
+	normal[1]=sin(atan2(x1-x2,y2-y1));
+	length=sqrt(pow(x2-x1,2)+pow(y2-y1,2));
+
+	//Compute load contribution for this segment:
+	SegmentPressureLoad(pe_g,matpar->GetRhoWater(),matpar->GetRhoIce(),matpar->GetG(),thickness_list,bed_list,normal,length);
+		
+	/*Plug pe_g into vector: */
+	VecSetValues(pg,numdofs,doflist,pe_g,ADD_VALUES);
+
+	/*Free ressources:*/
+	xfree((void**)&element_nodes);
+
+}
+/*}}}*/
+/*FUNCTION Icefront CreatePVectorDiagnosticHorizQuad {{{1*/
+void Icefront::CreatePVectorDiagnosticHorizQuad( Vec pg,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+
+	const int numgrids=4;
+	const int NDOF2=2;
+	const int numdofs=numgrids*NDOF2;
+	int   numberofdofspernode;
+	int   doflist[numdofs];
+
+	double xyz_list[numgrids][3];
+	double xyz_list_quad[numgrids+1][3]; //center node
+
+	double thickness_list[6]; //from penta element
+	double thickness_list_quad[6]; //selection of 4 thickness from penta elements
+
+	double bed_list[6]; //from penta element
+	double bed_list_quad[6]; //selection of 4 beds from penta elements
+
+	/*Objects: */
+	double  pe_g[numdofs]={0.0};
+	Matpar* matpar=NULL;
+	Node**  element_nodes=NULL;
+	Node**   nodes=NULL;
+	Element* element=NULL;
+	int    element_type;
+		
+	/*quad grids: */
+	int grid1,grid2,grid3,grid4;
+
+	/*normals: */
+	double normal1[3];
+	double normal2[3];
+	double normal3[3];
+	double normal4[3];
+	double normal_norm;
+	double v15[3];
+	double v25[3];
+	double v35[3];
+	double v45[3];
+
+	/*Recover hook objects: */
+	matpar=(Matpar*)hmatpar.delivers();
+	element=(Element*)helement.delivers();
+	nodes=(Node**)hnodes.deliverp();
+
+	element_type=element->Enum();
+
+	/*check icefront is associated to a pentaelem: */
+	if(element_type!=PentaEnum){
+		ISSMERROR(" quad icefront is associated to a TriaElem!");
+	}
+
+	/* Get dof list and node coordinates: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	
+	//Identify which grids are comprised in the quad: 
+	if(element_type==PentaEnum)element_nodes=(Node**)xmalloc(6*sizeof(Node*));
+	element->GetNodes((void**)element_nodes);
+
+	grid1=-1; grid2=-1; grid3=-1; grid4=-1;
+	for(i=0;i<6;i++){
+		if (nodes[0]==element_nodes[i])grid1=i;
+		if (nodes[1]==element_nodes[i])grid2=i;
+		if (nodes[2]==element_nodes[i])grid3=i;
+		if (nodes[3]==element_nodes[i])grid4=i;
+	}
+	
+	if((grid1==-1) || (grid2==-1)|| (grid3==-1)||(grid4==-1)){
+		ISSMERROR("could not find element grids corresponding to quad icefront!");
+	}
+
+	/*Build new xyz, bed and thickness lists for grids 1 to 4: */
+	for(i=0;i<4;i++){
+		for(j=0;j<3;j++){
+			xyz_list_quad[i][j]=xyz_list[i][j];
+		}
+	}
+
+	element->GetThicknessList(&thickness_list[0]);
+	element->GetBedList(&bed_list[0]);
+
+	thickness_list_quad[0]=thickness_list[grid1];
+	thickness_list_quad[1]=thickness_list[grid2];
+	thickness_list_quad[2]=thickness_list[grid3];
+	thickness_list_quad[3]=thickness_list[grid4];
+
+	bed_list_quad[0]=bed_list[grid1];
+	bed_list_quad[1]=bed_list[grid2];
+	bed_list_quad[2]=bed_list[grid3];
+	bed_list_quad[3]=bed_list[grid4];
+
+	//Create a new grid in the midle of the quad and add it at the end of the list
+	xyz_list_quad[4][0] = (xyz_list_quad[0][0]+xyz_list_quad[1][0]+xyz_list_quad[2][0]+xyz_list_quad[3][0])/4.0;
+	xyz_list_quad[4][1] = (xyz_list_quad[0][1]+xyz_list_quad[1][1]+xyz_list_quad[2][1]+xyz_list_quad[3][1])/4.0;
+	xyz_list_quad[4][2] = (xyz_list_quad[0][2]+xyz_list_quad[1][2]+xyz_list_quad[2][2]+xyz_list_quad[3][2])/4.0;
+
+	//Compute four normals (the quad is divided into four triangles)
+	v15[0]=xyz_list_quad[0][0]-xyz_list_quad[4][0];
+	v15[1]=xyz_list_quad[0][1]-xyz_list_quad[4][1];
+	v15[2]=xyz_list_quad[0][2]-xyz_list_quad[4][2];
+	
+	v25[0]=xyz_list_quad[1][0]-xyz_list_quad[4][0];
+	v25[1]=xyz_list_quad[1][1]-xyz_list_quad[4][1];
+	v25[2]=xyz_list_quad[1][2]-xyz_list_quad[4][2];
+	
+	v35[0]=xyz_list_quad[2][0]-xyz_list_quad[4][0];
+	v35[1]=xyz_list_quad[2][1]-xyz_list_quad[4][1];
+	v35[2]=xyz_list_quad[2][2]-xyz_list_quad[4][2];
+	
+	v45[0]=xyz_list_quad[3][0]-xyz_list_quad[4][0];
+	v45[1]=xyz_list_quad[3][1]-xyz_list_quad[4][1];
+	v45[2]=xyz_list_quad[3][2]-xyz_list_quad[4][2];
+
+	cross(normal1,v15,v25); 
+	cross(normal2,v25,v35);
+	cross(normal3,v35,v45);
+	cross(normal4,v45,v15);
+
+	normal_norm=norm(normal1);normal1[0]=normal1[0]/normal_norm;normal1[1]=normal1[1]/normal_norm;normal1[2]=normal1[2]/normal_norm;
+	normal_norm=norm(normal2);normal2[0]=normal2[0]/normal_norm;normal2[1]=normal2[1]/normal_norm;normal2[2]=normal2[2]/normal_norm;
+	normal_norm=norm(normal3);normal3[0]=normal3[0]/normal_norm;normal3[1]=normal3[1]/normal_norm;normal3[2]=normal3[2]/normal_norm;
+	normal_norm=norm(normal4);normal4[0]=normal4[0]/normal_norm;normal4[1]=normal4[1]/normal_norm;normal4[2]=normal4[2]/normal_norm;
+
+
+	//Compute load contribution for this quad:
+	QuadPressureLoad(pe_g,matpar->GetRhoWater(),matpar->GetRhoIce(),matpar->GetG(),thickness_list_quad,bed_list_quad,normal1,normal2,normal3,normal4,&xyz_list_quad[0][0]);
+
+	/*Plug pe_g into vector: */
+	VecSetValues(pg,numdofs,doflist,pe_g,ADD_VALUES);
+
+	/*Free ressources:*/
+	xfree((void**)&element_nodes);
+
+}
+/*}}}*/
+/*FUNCTION Icefront CreatePVectorDiagnosticStokes {{{1*/
+void Icefront::CreatePVectorDiagnosticStokes( Vec pg,int analysis_type,int sub_analysis_type){
+
+	int i,j;
+
+	const int numgrids=4;
+	const int NDOF4=4;
+	const int numdofs=numgrids*NDOF4;
+	int   numberofdofspernode;
+	int   doflist[numdofs];
+
+	double xyz_list[numgrids][3];
+	double xyz_list_quad[numgrids+1][3]; //center node
+
+	double thickness_list[6]; //from penta element
+	double thickness_list_quad[6]; //selection of 4 thickness from penta elements
+
+	double bed_list[6]; //from penta element
+	double bed_list_quad[6]; //selection of 4 beds from penta elements
+
+	/*Objects: */
+	double  pe_g[numdofs]={0.0};
+	Matpar* matpar=NULL;
+	Node**  element_nodes=NULL;
+	Node**   nodes=NULL;
+	Element* element=NULL;
+	int     element_type;
+		
+
+	/*quad grids: */
+	int grid1,grid2,grid3,grid4;
+
+	/*normals: */
+	double normal1[3];
+	double normal2[3];
+	double normal3[3];
+	double normal4[3];
+	double normal_norm;
+	double v15[3];
+	double v25[3];
+	double v35[3];
+	double v45[3];
+
+	/*Recover hook objects: */
+	matpar=(Matpar*)hmatpar.delivers();
+	element=(Element*)helement.delivers();
+	nodes=(Node**)hnodes.deliverp();
+	
+	/*check icefront is associated to a pentaelem: */
+	if(element_type!=PentaEnum){
+		ISSMERROR(" quad icefront is associated to a TriaElem!");
+	}
+
+	/* Get dof list and node coordinates: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	
+	//Identify which grids are comprised in the quad: 
+	if(element_type==PentaEnum)element_nodes=(Node**)xmalloc(6*sizeof(Node*));
+	element->GetNodes((void**)element_nodes);
+
+	grid1=-1; grid2=-1; grid3=-1; grid4=-1;
+	for(i=0;i<6;i++){
+		if (nodes[0]==element_nodes[i])grid1=i;
+		if (nodes[1]==element_nodes[i])grid2=i;
+		if (nodes[2]==element_nodes[i])grid3=i;
+		if (nodes[3]==element_nodes[i])grid4=i;
+	}
+	
+	if((grid1==-1) || (grid2==-1)|| (grid3==-1)||(grid4==-1)){
+		ISSMERROR("could not find element grids corresponding to quad icefront!");
+	}
+
+	/*Build new xyz, bed and thickness lists for grids 1 to 4: */
+	for(i=0;i<4;i++){
+		for(j=0;j<3;j++){
+			xyz_list_quad[i][j]=xyz_list[i][j];
+		}
+	}
+
+	element->GetThicknessList(&thickness_list[0]);
+	element->GetBedList(&bed_list[0]);
+
+	thickness_list_quad[0]=thickness_list[grid1];
+	thickness_list_quad[1]=thickness_list[grid2];
+	thickness_list_quad[2]=thickness_list[grid3];
+	thickness_list_quad[3]=thickness_list[grid4];
+
+	bed_list_quad[0]=bed_list[grid1];
+	bed_list_quad[1]=bed_list[grid2];
+	bed_list_quad[2]=bed_list[grid3];
+	bed_list_quad[3]=bed_list[grid4];
+
+	//Create a new grid in the midle of the quad and add it at the end of the list
+	xyz_list_quad[4][0] = (xyz_list_quad[0][0]+xyz_list_quad[1][0]+xyz_list_quad[2][0]+xyz_list_quad[3][0])/4.0;
+	xyz_list_quad[4][1] = (xyz_list_quad[0][1]+xyz_list_quad[1][1]+xyz_list_quad[2][1]+xyz_list_quad[3][1])/4.0;
+	xyz_list_quad[4][2] = (xyz_list_quad[0][2]+xyz_list_quad[1][2]+xyz_list_quad[2][2]+xyz_list_quad[3][2])/4.0;
+
+	//Compute four normals (the quad is divided into four triangles)
+	v15[0]=xyz_list_quad[0][0]-xyz_list_quad[4][0];
+	v15[1]=xyz_list_quad[0][1]-xyz_list_quad[4][1];
+	v15[2]=xyz_list_quad[0][2]-xyz_list_quad[4][2];
+	
+	v25[0]=xyz_list_quad[1][0]-xyz_list_quad[4][0];
+	v25[1]=xyz_list_quad[1][1]-xyz_list_quad[4][1];
+	v25[2]=xyz_list_quad[1][2]-xyz_list_quad[4][2];
+	
+	v35[0]=xyz_list_quad[2][0]-xyz_list_quad[4][0];
+	v35[1]=xyz_list_quad[2][1]-xyz_list_quad[4][1];
+	v35[2]=xyz_list_quad[2][2]-xyz_list_quad[4][2];
+	
+	v45[0]=xyz_list_quad[3][0]-xyz_list_quad[4][0];
+	v45[1]=xyz_list_quad[3][1]-xyz_list_quad[4][1];
+	v45[2]=xyz_list_quad[3][2]-xyz_list_quad[4][2];
+
+	cross(normal1,v15,v25); 
+	cross(normal2,v25,v35);
+	cross(normal3,v35,v45);
+	cross(normal4,v45,v15);
+
+	normal_norm=norm(normal1);normal1[0]=normal1[0]/normal_norm;normal1[1]=normal1[1]/normal_norm;normal1[2]=normal1[2]/normal_norm;
+	normal_norm=norm(normal2);normal2[0]=normal2[0]/normal_norm;normal2[1]=normal2[1]/normal_norm;normal2[2]=normal2[2]/normal_norm;
+	normal_norm=norm(normal3);normal3[0]=normal3[0]/normal_norm;normal3[1]=normal3[1]/normal_norm;normal3[2]=normal3[2]/normal_norm;
+	normal_norm=norm(normal4);normal4[0]=normal4[0]/normal_norm;normal4[1]=normal4[1]/normal_norm;normal4[2]=normal4[2]/normal_norm;
+
+
+	//Compute load contribution for this quad:
+	QuadPressureLoadStokes(pe_g,matpar->GetRhoWater(),matpar->GetRhoIce(),matpar->GetG(),thickness_list_quad,bed_list_quad,normal1,normal2,normal3,normal4,&xyz_list_quad[0][0]);
+
+	/*Plug pe_g into vector: */
+	VecSetValues(pg,numdofs,doflist,pe_g,ADD_VALUES);
+
+	/*Free ressources:*/
+	xfree((void**)&element_nodes);
+
+}
+/*}}}*/
+/*FUNCTION Icefront DistributeNumDofs {{{1*/
+void  Icefront::DistributeNumDofs(int* numdofspernode,int analysis_type,int sub_analysis_type){return;}
+		
+/*}}}*/
+/*FUNCTION Icefront GetDofList{{{1*/
+
+void  Icefront::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+	int type;
+
+	Node**   nodes=NULL;
+	nodes=(Node**)hnodes.deliverp();
+	inputs->GetParameterValue(&type,TypeEnum);
+	
+	if(type==SegmentIcefrontEnum){
+		for(i=0;i<2;i++){
+			nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+			for(j=0;j<numberofdofspernode;j++){
+				doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+			}
+		}
+	}
+	else{
+		for(i=0;i<4;i++){
+			nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+			for(j=0;j<numberofdofspernode;j++){
+				doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+			}
+		}
+	}
+
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION Icefront PenaltyCreateKMatrix {{{1*/
+void  Icefront::PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+	/*do nothing: */
+}
+/*}}}*/
+/*FUNCTION Icefront PenaltyCreatePVector{{{1*/
+void  Icefront::PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type){
+	/*do nothing: */
+}
+/*}}}*/
+/*FUNCTION Icefront QuadPressureLoad {{{1*/
+void Icefront::QuadPressureLoad(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, 
+		                              double* normal1,double* normal2,double* normal3,double* normal4,double* xyz_list){
+	
+	
+	//The quad is divided into four triangles tria1 tria2 tria3 and tria4 as follows
+	//
+	//   grid 4 +-----------------+ grid 3
+	//          |\2            1 /|
+	//          |1\    tria3    /2|
+	//          |  \           /  |
+	//          |   \         /   |
+	//          |    \       /    |
+	//          |     \     /     |
+	//          |      \ 3 /      |
+	//          |tria4  \ / 3     |
+	//          |      3 \grid5   |
+	//          |       / \       | 
+	//          |      / 3 \ tria2|
+	//          |     /     \     |
+	//          |    /       \    |
+	//          |   /         \   |
+	//          |  /   tria1   \  |
+	//          |2/1           2\1|
+	//   grid1  +-----------------+ grid 2
+	//
+	//
+
+	int      i,j;
+
+	double nx[4];
+	double ny[4];
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+
+	double  surface_list[5];
+	double  x[5];
+	double  y[5];
+	double  z[5];
+	double l12,l14,l15,l23,l25,l34,l35,l45;
+	double cos_theta_triangle1,cos_theta_triangle2,cos_theta_triangle3,cos_theta_triangle4;
+
+	double xyz_tria[12][2];
+	double l1l2l3_tria[3];
+	double r_tria,s_tria;
+	double r_quad[4];
+	double s_quad[4];
+	double l1l4_tria[4][4];
+
+	double J[4];
+	double z_g[4];
+	double ice_pressure_tria[4];
+	double air_pressure_tria;
+	double water_level_above_g_tria;
+	double water_pressure_tria;
+	double pressure_tria[4];
+	int    fill;
+
+
+	/*To use tria functionalities: */
+	Tria* tria=NULL;
+	
+	/*Recover inputs: */
+	inputs->GetParameterValue(&fill,FillEnum);
+
+	/*Initialize fake tria: */
+	tria=new Tria();
+
+	//Build the four normal vectors 
+	nx[0]=normal1[0]; nx[1]=normal2[0]; nx[2]=normal3[0]; nx[3]=normal4[0];
+	ny[0]=normal1[1]; ny[1]=normal2[1]; ny[2]=normal3[1]; ny[3]=normal4[1];
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+	
+	//Recover the surface of the four nodes
+	for(i=0;i<4;i++){
+		surface_list[i]=thickness_list[i]+bed_list[i];
+	}
+	//Add surface sor the fifth point (average of the surfaces)
+	surface_list[4]=(surface_list[0]+surface_list[1]+surface_list[2]+surface_list[3])/4.0;
+
+	//Recover grid coordinates
+	for(i=0;i<5;i++){
+		x[i]=*(xyz_list+3*i+0);
+		y[i]=*(xyz_list+3*i+1);
+		z[i]=*(xyz_list+3*i+2);
+	}
+	
+	//Build triangles in a 2D plan before using reference elements
+	l12=pow((x[1]-x[0]),2)+pow((y[1]-y[0]),2)+pow((z[1]-z[0]),2);
+	l14=pow((x[3]-x[0]),2)+pow((y[3]-y[0]),2)+pow((z[3]-z[0]),2);
+	l15=pow((x[4]-x[0]),2)+pow((y[4]-y[0]),2)+pow((z[4]-z[0]),2);
+	l23=pow((x[2]-x[1]),2)+pow((y[2]-y[1]),2)+pow((z[2]-z[1]),2);
+	l25=pow((x[4]-x[1]),2)+pow((y[4]-y[1]),2)+pow((z[4]-z[1]),2);
+	l34=pow((x[3]-x[2]),2)+pow((y[3]-y[2]),2)+pow((z[3]-z[2]),2);
+	l35=pow((x[4]-x[2]),2)+pow((y[4]-y[2]),2)+pow((z[4]-z[2]),2);
+	l45=pow((x[4]-x[3]),2)+pow((y[4]-y[3]),2)+pow((z[4]-z[3]),2);
+
+	cos_theta_triangle1=(l15+l12-l25)/(2*sqrt(l12*l15));
+	cos_theta_triangle2=(l25+l23-l35)/(2*sqrt(l23*l25));
+	cos_theta_triangle3=(l35+l34-l45)/(2*sqrt(l34*l35));
+	cos_theta_triangle4=(l45+l14-l15)/(2*sqrt(l14*l45));
+
+	//First triangle : nodes 1, 2 and 5
+	xyz_tria[0][0]=0;
+	xyz_tria[0][1]=0;
+	xyz_tria[1][0]=sqrt(l12);
+	xyz_tria[1][1]=0;
+	xyz_tria[2][0]=cos_theta_triangle1*sqrt(l15);
+	xyz_tria[2][1]=sqrt(1-pow(cos_theta_triangle1,2))*sqrt(l15);
+
+	//Second triangle : nodes 2, 3 and 5
+	xyz_tria[3][0]=0;
+	xyz_tria[3][1]=0;
+	xyz_tria[4][0]=sqrt(l23);
+	xyz_tria[4][1]=0;
+	xyz_tria[5][0]=cos_theta_triangle2*sqrt(l25);
+	xyz_tria[5][1]=sqrt(1-pow(cos_theta_triangle2,2))*sqrt(l25);
+	
+	//Third triangle : nodes 3, 4 and 5
+	xyz_tria[6][0]=0;
+	xyz_tria[6][1]=0;
+	xyz_tria[7][0]=sqrt(l34);
+	xyz_tria[7][1]=0;
+	xyz_tria[8][0]=cos_theta_triangle3*sqrt(l35);
+	xyz_tria[8][1]=sqrt(1-pow(cos_theta_triangle3,2))*sqrt(l35);
+
+	//Fourth triangle : nodes 4, 1 and 5
+	xyz_tria[9][0]=0;
+	xyz_tria[9][1]=0;
+	xyz_tria[10][0]=sqrt(l14);
+	xyz_tria[10][1]=0;
+	xyz_tria[11][0]=cos_theta_triangle4*sqrt(l45);
+	xyz_tria[11][1]=sqrt(1-pow(cos_theta_triangle4,2))*sqrt(l45);
+
+	
+
+	//Start  looping on the triangle's gaussian points: 
+	for(ig=0;ig<num_gauss;ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig);
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+        
+		tria->GetNodalFunctions(l1l2l3_tria,gauss_coord);
+
+		//Get the coordinates of gauss point for each triangle in penta/quad
+		r_tria=gauss_coord[1]-gauss_coord[0];
+		s_tria=-3/sqrt((double)3)*(gauss_coord[0]+gauss_coord[1]-2/3);
+
+		//Coordinates of gauss points in the reference triangle
+		r_quad[0]=r_tria;
+		s_quad[0]=1/sqrt((double)3)*s_tria-2/3;
+		r_quad[1]=-1/sqrt((double)3)*s_tria+2/3;
+		s_quad[1]=r_tria;
+		r_quad[2]=-r_tria;
+		s_quad[2]=-1/sqrt((double)3)*s_tria+2/3;
+		r_quad[3]=1/sqrt((double)3)*s_tria-2/3;
+		s_quad[3]=-r_tria;
+
+		//Get the nodal function of the quad for the gauss points of each triangle
+		for(i=0;i<4;i++){
+			l1l4_tria[i][0]=1.0/4.0*(
+					(r_quad[i]-1.0)*(s_quad[i]-1.0) 
+					); 
+			
+			l1l4_tria[i][1]=1.0/4.0*(
+					 -(r_quad[i]+1.0)*(s_quad[i]-1.0)
+					); 
+
+			l1l4_tria[i][2]=1.0/4.0*(
+					(r_quad[i]+1.0)*(s_quad[i]+1.0) 
+					);
+			
+			l1l4_tria[i][3]=1.0/4.0*(
+					 -(r_quad[i]-1.0)*(s_quad[i]+1.0)
+					);
+
+		} //for(i=0;i<4;i++)
+		
+		
+		//Compute jacobian of each triangle
+		for (i=0;i<4;i++){
+			double complete_list[3][3]; //a third coordinate is needed for the jacobian determinant calculation, here it is zero
+			for(j=0;j<3;j++){
+				complete_list[j][0]=xyz_tria[3*i+j][0];
+				complete_list[j][1]=xyz_tria[3*i+j][1];
+				complete_list[j][2]=0;
+			}
+			tria->GetJacobianDeterminant2d(&J[i],&complete_list[0][0],l1l2l3_tria);
+		}
+
+		//Calculation of the z coordinate for the gaussian point ig for each triangle
+		z_g[0]=z[0]*l1l2l3_tria[0]+z[1]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[1]=z[1]*l1l2l3_tria[0]+z[2]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[2]=z[2]*l1l2l3_tria[0]+z[3]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[3]=z[3]*l1l2l3_tria[0]+z[0]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		
+		//Loop on the triangles
+		for(i=0;i<4;i++){
+
+			//Loop on the grids of the quad
+			//Calculate the ice pressure
+			for(j=0;j<4;j++){
+				ice_pressure_tria[j]=gravity*rho_ice*(surface_list[j]-z_g[i]);
+			}
+			air_pressure_tria=0;
+
+			//Now deal with water pressure: 
+			if(fill==WaterEnum){ //icefront ends in water
+				water_level_above_g_tria=min(0,z_g[i]);//0 if the gaussian point is above water level
+				water_pressure_tria=rho_water*gravity*water_level_above_g_tria;
+			}
+			else if(fill==AirEnum){
+				water_pressure_tria=0;
+			}
+			else{
+				ISSMERROR("QuadPressureLoad error message: unknow fill type for icefront boundary condition");
+			}
+
+			//Add pressure from triangle i
+			//Loop on the grids of the quad
+			for(j=0;j<4;j++){
+				pressure_tria[j] = ice_pressure_tria[j] + water_pressure_tria + air_pressure_tria;
+			}
+
+
+			pe_g[0]+= J[i]*gauss_weight* pressure_tria[0]*l1l4_tria[i][0]*nx[i];
+			pe_g[1]+= J[i]*gauss_weight* pressure_tria[0]*l1l4_tria[i][0]*ny[i];
+			pe_g[2]+= J[i]*gauss_weight* pressure_tria[1]*l1l4_tria[i][1]*nx[i];
+			pe_g[3]+= J[i]*gauss_weight* pressure_tria[1]*l1l4_tria[i][1]*ny[i];
+			pe_g[4]+= J[i]*gauss_weight* pressure_tria[2]*l1l4_tria[i][2]*nx[i];
+			pe_g[5]+= J[i]*gauss_weight* pressure_tria[2]*l1l4_tria[i][2]*ny[i];
+			pe_g[6]+= J[i]*gauss_weight* pressure_tria[3]*l1l4_tria[i][3]*nx[i];
+			pe_g[7]+= J[i]*gauss_weight* pressure_tria[3]*l1l4_tria[i][3]*ny[i];
+
+			
+
+		} //for(i=0;i<4;i++)
+	} //for(ig=0;ig<num_gauss;ig++)
+	
+	/*Free ressources: */
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+	/*Delete fake tria: */
+	delete tria;
+}
+/*}}}*/
+/*FUNCTION Icefront QuadPressureLoadStokes {{{1*/
+void Icefront::QuadPressureLoadStokes(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, 
+		                              double* normal1,double* normal2,double* normal3,double* normal4,double* xyz_list){
+	
+	
+	//The quad is divided into four triangles tria1 tria2 tria3 and tria4 as follows
+	//
+	//   grid 4 +-----------------+ grid 3
+	//          |\2            1 /|
+	//          |1\    tria3    /2|
+	//          |  \           /  |
+	//          |   \         /   |
+	//          |    \       /    |
+	//          |     \     /     |
+	//          |      \ 3 /      |
+	//          |tria4  \ / 3     |
+	//          |      3 \grid5   |
+	//          |       / \       | 
+	//          |      / 3 \ tria2|
+	//          |     /     \     |
+	//          |    /       \    |
+	//          |   /         \   |
+	//          |  /   tria1   \  |
+	//          |2/1           2\1|
+	//   grid1  +-----------------+ grid 2
+	//
+	//
+
+	int      i,j;
+
+	double nx[4];
+	double ny[4];
+	double nz[4];
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* first_gauss_area_coord  =  NULL;
+	double* second_gauss_area_coord =  NULL;
+	double* third_gauss_area_coord  =  NULL;
+	double* gauss_weights           =  NULL;
+	double  gauss_weight;
+	double  gauss_coord[3];
+
+	double  surface_list[5];
+	double  x[5];
+	double  y[5];
+	double  z[5];
+	double l12,l14,l15,l23,l25,l34,l35,l45;
+	double cos_theta_triangle1,cos_theta_triangle2,cos_theta_triangle3,cos_theta_triangle4;
+
+	double xyz_tria[12][2];
+	double l1l2l3_tria[3];
+	double r_tria,s_tria;
+	double r_quad[4];
+	double s_quad[4];
+	double l1l4_tria[4][4];
+
+	double J[4];
+	double z_g[4];
+	double air_pressure_tria;
+	double water_level_above_g_tria;
+	double water_pressure_tria;
+	double pressure_tria;
+	int    fill;
+
+	/*To use tria functionalities: */
+	Tria* tria=NULL;
+
+	/*Recover inputs: */
+	inputs->GetParameterValue(&fill,FillEnum);
+
+	/*Initialize fake tria: */
+	tria=new Tria();
+
+	//Build the four normal vectors 
+	nx[0]=normal1[0]; nx[1]=normal2[0]; nx[2]=normal3[0]; nx[3]=normal4[0];
+	ny[0]=normal1[1]; ny[1]=normal2[1]; ny[2]=normal3[1]; ny[3]=normal4[1];
+	nz[0]=normal1[2]; nz[1]=normal2[2]; nz[2]=normal3[2]; nz[3]=normal4[2];
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	GaussTria( &num_gauss, &first_gauss_area_coord, &second_gauss_area_coord, &third_gauss_area_coord, &gauss_weights, 2);
+	
+	//Recover the surface of the four nodes
+	for(i=0;i<4;i++){
+		surface_list[i]=thickness_list[i]+bed_list[i];
+	}
+	//Add surface sor the fifth point (average of the surfaces)
+	surface_list[4]=(surface_list[0]+surface_list[1]+surface_list[2]+surface_list[3])/4.0;
+
+	//Recover grid coordinates
+	for(i=0;i<5;i++){
+		x[i]=*(xyz_list+3*i+0);
+		y[i]=*(xyz_list+3*i+1);
+		z[i]=*(xyz_list+3*i+2);
+	}
+	
+	//Build triangles in a 2D plan before using reference elements
+	l12=pow((x[1]-x[0]),2)+pow((y[1]-y[0]),2)+pow((z[1]-z[0]),2);
+	l14=pow((x[3]-x[0]),2)+pow((y[3]-y[0]),2)+pow((z[3]-z[0]),2);
+	l15=pow((x[4]-x[0]),2)+pow((y[4]-y[0]),2)+pow((z[4]-z[0]),2);
+	l23=pow((x[2]-x[1]),2)+pow((y[2]-y[1]),2)+pow((z[2]-z[1]),2);
+	l25=pow((x[4]-x[1]),2)+pow((y[4]-y[1]),2)+pow((z[4]-z[1]),2);
+	l34=pow((x[3]-x[2]),2)+pow((y[3]-y[2]),2)+pow((z[3]-z[2]),2);
+	l35=pow((x[4]-x[2]),2)+pow((y[4]-y[2]),2)+pow((z[4]-z[2]),2);
+	l45=pow((x[4]-x[3]),2)+pow((y[4]-y[3]),2)+pow((z[4]-z[3]),2);
+
+	cos_theta_triangle1=(l15+l12-l25)/(2*sqrt(l12*l15));
+	cos_theta_triangle2=(l25+l23-l35)/(2*sqrt(l23*l25));
+	cos_theta_triangle3=(l35+l34-l45)/(2*sqrt(l34*l35));
+	cos_theta_triangle4=(l45+l14-l15)/(2*sqrt(l14*l45));
+
+	//First triangle : nodes 1, 2 and 5
+	xyz_tria[0][0]=0;
+	xyz_tria[0][1]=0;
+	xyz_tria[1][0]=sqrt(l12);
+	xyz_tria[1][1]=0;
+	xyz_tria[2][0]=cos_theta_triangle1*sqrt(l15);
+	xyz_tria[2][1]=sqrt(1-pow(cos_theta_triangle1,2))*sqrt(l15);
+
+	//Second triangle : nodes 2, 3 and 5
+	xyz_tria[3][0]=0;
+	xyz_tria[3][1]=0;
+	xyz_tria[4][0]=sqrt(l23);
+	xyz_tria[4][1]=0;
+	xyz_tria[5][0]=cos_theta_triangle2*sqrt(l25);
+	xyz_tria[5][1]=sqrt(1-pow(cos_theta_triangle2,2))*sqrt(l25);
+	
+	//Third triangle : nodes 3, 4 and 5
+	xyz_tria[6][0]=0;
+	xyz_tria[6][1]=0;
+	xyz_tria[7][0]=sqrt(l34);
+	xyz_tria[7][1]=0;
+	xyz_tria[8][0]=cos_theta_triangle3*sqrt(l35);
+	xyz_tria[8][1]=sqrt(1-pow(cos_theta_triangle3,2))*sqrt(l35);
+
+	//Fourth triangle : nodes 4, 1 and 5
+	xyz_tria[9][0]=0;
+	xyz_tria[9][1]=0;
+	xyz_tria[10][0]=sqrt(l14);
+	xyz_tria[10][1]=0;
+	xyz_tria[11][0]=cos_theta_triangle4*sqrt(l45);
+	xyz_tria[11][1]=sqrt(1-pow(cos_theta_triangle4,2))*sqrt(l45);
+
+	
+
+	//Start  looping on the triangle's gaussian points: 
+	for(ig=0;ig<num_gauss;ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=*(gauss_weights+ig);
+		gauss_coord[0]=*(first_gauss_area_coord+ig);
+		gauss_coord[1]=*(second_gauss_area_coord+ig);
+		gauss_coord[2]=*(third_gauss_area_coord+ig);
+        
+		tria->GetNodalFunctions(l1l2l3_tria,gauss_coord);
+
+		//Get the coordinates of gauss point for each triangle in penta/quad
+		r_tria=gauss_coord[1]-gauss_coord[0];
+		s_tria=-3/sqrt((double)3)*(gauss_coord[0]+gauss_coord[1]-2/3);
+
+		//Coordinates of gauss points in the reference triangle
+		r_quad[0]=r_tria;
+		s_quad[0]=1/sqrt((double)3)*s_tria-2/3;
+		r_quad[1]=-1/sqrt((double)3)*s_tria+2/3;
+		s_quad[1]=r_tria;
+		r_quad[2]=-r_tria;
+		s_quad[2]=-1/sqrt((double)3)*s_tria+2/3;
+		r_quad[3]=1/sqrt((double)3)*s_tria-2/3;
+		s_quad[3]=-r_tria;
+
+		//Get the nodal function of the quad for the gauss points of each triangle
+		for(i=0;i<4;i++){
+			l1l4_tria[i][0]=1.0/4.0*(
+					(r_quad[i]-1.0)*(s_quad[i]-1.0) 
+					); 
+			
+			l1l4_tria[i][1]=1.0/4.0*(
+					 -(r_quad[i]+1.0)*(s_quad[i]-1.0)
+					); 
+
+			l1l4_tria[i][2]=1.0/4.0*(
+					(r_quad[i]+1.0)*(s_quad[i]+1.0) 
+					);
+			
+			l1l4_tria[i][3]=1.0/4.0*(
+					 -(r_quad[i]-1.0)*(s_quad[i]+1.0)
+					);
+
+		} //for(i=0;i<4;i++)
+		
+		
+		//Compute jacobian of each triangle
+		for (i=0;i<4;i++){
+			double complete_list[3][3]; //a third coordinate is needed for the jacobian determinant calculation, here it is zero
+			for(j=0;j<3;j++){
+				complete_list[j][0]=xyz_tria[3*i+j][0];
+				complete_list[j][1]=xyz_tria[3*i+j][1];
+				complete_list[j][2]=0;
+			}
+			tria->GetJacobianDeterminant2d(&J[i],&complete_list[0][0],l1l2l3_tria);
+		}
+
+		//Calculation of the z coordinate for the gaussian point ig for each triangle
+		z_g[0]=z[0]*l1l2l3_tria[0]+z[1]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[1]=z[1]*l1l2l3_tria[0]+z[2]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[2]=z[2]*l1l2l3_tria[0]+z[3]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		z_g[3]=z[3]*l1l2l3_tria[0]+z[0]*l1l2l3_tria[1]+z[4]*l1l2l3_tria[2];
+		
+		//Loop on the triangles
+		for(i=0;i<4;i++){
+
+			//Loop on the grids of the quad
+			//Calculate the ice pressure
+			air_pressure_tria=0;
+
+			//Now deal with water pressure: 
+			if(fill==WaterEnum){ //icefront ends in water
+				water_level_above_g_tria=min(0,z_g[i]);//0 if the gaussian point is above water level
+				water_pressure_tria=rho_water*gravity*water_level_above_g_tria;
+			}
+			else if(fill==AirEnum){
+				water_pressure_tria=0;
+			}
+			else{
+				ISSMERROR("QuadPressureLoadStokes error message: unknow fill type for icefront boundary condition");
+			}
+
+			//Add pressure 
+			pressure_tria = water_pressure_tria + air_pressure_tria;
+
+			pe_g[0]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][0]*nx[i];
+			pe_g[1]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][0]*ny[i];
+			pe_g[2]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][0]*nz[i];
+			pe_g[3]+= 0;
+			pe_g[4]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][1]*nx[i];
+			pe_g[5]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][1]*ny[i];
+			pe_g[6]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][1]*nz[i];
+			pe_g[7]+= 0;
+			pe_g[8]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][2]*nx[i];
+			pe_g[9]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][2]*ny[i];
+			pe_g[10]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][2]*nz[i];
+			pe_g[11]+= 0;
+			pe_g[12]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][3]*nx[i];
+			pe_g[13]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][3]*ny[i];
+			pe_g[14]+= J[i]*gauss_weight* pressure_tria*l1l4_tria[i][3]*nz[i];
+			pe_g[15]+= 0;
+
+		} //for(i=0;i<4;i++)
+	} //for(ig=0;ig<num_gauss;ig++)
+	
+	/*Free ressources: */
+	xfree((void**)&first_gauss_area_coord);
+	xfree((void**)&second_gauss_area_coord);
+	xfree((void**)&third_gauss_area_coord);
+	xfree((void**)&gauss_weights);
+
+	/*Delete fake tria: */
+	delete tria;
+}
+/*}}}*/
+/*FUNCTION Icefront SegmentPressureLoad {{{1*/
+
+void Icefront::SegmentPressureLoad(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, double* normal,double length){
+
+	double   nx,ny;
+	double   h1,h2,b1,b2;
+	int      num_gauss;
+	double*  segment_gauss_coord=NULL;
+	double*  gauss_weights=NULL;
+	int      ig;
+	double   Jdet;
+	double   thickness,bed;
+	double   ice_pressure,water_pressure,air_pressure;
+	double   surface_under_water,base_under_water;
+	double   pressure;
+	int    fill;
+
+	/*Recover inputs: */
+	inputs->GetParameterValue(&fill,FillEnum);
+
+	nx=normal[0];
+	ny=normal[1];
+
+
+	//Get gaussian points and weights. order 2 since we have a product of 2 nodal functions
+	num_gauss=3;
+	GaussSegment(&segment_gauss_coord, &gauss_weights, num_gauss);
+
+	//recover thickness and bed at two grids
+	h1=thickness_list[0];
+	h2=thickness_list[1];
+	b1=bed_list[0];
+	b2=bed_list[1];
+
+	//compute Jacobian of segment
+	Jdet=1./2.*length;
+
+	for(ig=0;ig<num_gauss;ig++){
+
+		thickness=h1*(1+segment_gauss_coord[ig])/2+h2*(1-segment_gauss_coord[ig])/2;
+		bed=b1*(1+segment_gauss_coord[ig])/2+b2*(1-segment_gauss_coord[ig])/2;
+
+		if (fill==WaterEnum){
+			//icefront ends in water: 
+			ice_pressure=1.0/2.0*gravity*rho_ice*pow(thickness,2);
+			air_pressure=0;
+
+			//Now deal with water pressure
+			surface_under_water=min(0,thickness+bed); // 0 if the top of the glacier is above water level
+			base_under_water=min(0,bed);              // 0 if the bottom of the glacier is above water level
+			water_pressure=1.0/2.0*gravity*rho_water*(pow(surface_under_water,2) - pow(base_under_water,2));
+		}
+		else if (fill==AirEnum){
+			ice_pressure=1.0/2.0*gravity*rho_ice*pow(thickness,2);
+			air_pressure=0;
+			water_pressure=0;
+		}
+		else{
+			ISSMERROR("fill type %i not supported yet",fill);
+		}
+
+		pressure = ice_pressure + water_pressure + air_pressure;
+
+		pe_g[2*0+0]+= pressure*Jdet*gauss_weights[ig]*(1+segment_gauss_coord[ig])/2*nx;
+		pe_g[2*0+1]+= pressure*Jdet*gauss_weights[ig]*(1+segment_gauss_coord[ig])/2*ny;
+		pe_g[2*1+0]+= pressure*Jdet*gauss_weights[ig]*(1-segment_gauss_coord[ig])/2*nx;
+		pe_g[2*1+1]+= pressure*Jdet*gauss_weights[ig]*(1-segment_gauss_coord[ig])/2*ny;
+
+	} //for(ig=0;ig<num_gauss;ig++)
+
+	xfree((void**)&segment_gauss_coord);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Loads/Icefront.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Icefront.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Icefront.h	(revision 3683)
@@ -0,0 +1,73 @@
+/*!\file Icefront.h
+ * \brief: header file for icefront object
+ */
+
+#ifndef _ICEFRONT_H_
+#define _ICEFRONT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Load.h"
+class Hook;
+class Inputs;
+class Parameters;
+class IoModel;
+
+#define MAX_ICEFRONT_GRIDS 4 //max number of grids for a certain load
+#define ICEFRONTSTRING 20 //max string length
+/*}}}*/
+
+class Icefront: public Load {
+
+	public:
+		int id;
+
+		/*hooks: */
+		Hook hnodes;
+		Hook helement;
+		Hook hmatpar;
+
+		/*inputs and parameters: */
+		Inputs* inputs;
+		Parameters* parameters;
+
+		/*constructors: {{{1*/
+		Icefront();
+		Icefront(int icefront_id,int* icefront_node_ids, int icefront_numnodes, int icefront_element_id,int icefront_matpar_id);
+		Icefront(int icefront_id, Hook* icefront_hnodes, Hook* icefront_helement, Hook* icefront_hmatpar, Parameters* parameters, Inputs* icefront_inputs);
+		Icefront(int icefront_id,int i, IoModel* iomodel);
+		~Icefront();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void  DistributeNumDofs(int* numdofspernode,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticHoriz( Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticHorizSegment( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticHorizQuad( Vec pg, int analysis_type,int sub_analysis_type);
+		void  CreatePVectorDiagnosticStokes( Vec pg, int analysis_type,int sub_analysis_type);
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  SegmentPressureLoad(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, double* normal,double length);
+		void  QuadPressureLoad(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, 
+		                              double* normal1,double* normal2,double* normal3,double* normal4,double* xyz_list);
+		void  QuadPressureLoadStokes(double* pe_g,double rho_water,double rho_ice,double gravity, double* thickness_list, double* bed_list, 
+		                              double* normal1,double* normal2,double* normal3,double* normal4,double* xyz_list);
+		void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type);
+		/*}}}*/
+};
+
+#endif  /* _ICEFRONT_H_ */
Index: /issm/trunk/src/c/objects/Loads/Load.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Load.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Load.h	(revision 3683)
@@ -0,0 +1,40 @@
+/*!\file:  Load.h
+ * \brief abstract class for Load object
+ * This class is a place holder for the Icefront  and the Penpair loads.
+ * It is derived from Load, so DataSets can contain them.
+ */ 
+
+
+#ifndef _LOAD_H_
+#define _LOAD_H_
+
+/*Headers:*/
+/*{{{1*/
+class Object;
+
+#include "../Object.h"
+#include "../../toolkits/toolkits.h"
+#include "../../DataSet/DataSet.h"
+/*}}}*/
+
+class Load: public Object{
+
+	public: 
+		virtual       ~Load(){};
+		virtual void  Echo()=0;
+		virtual void  DeepEcho()=0;
+		virtual int   Id()=0;
+		virtual int   MyRank()=0;
+		virtual void  Marshall(char** pmarshalled_dataset)=0;
+		virtual int   MarshallSize()=0;
+		virtual void  Demarshall(char** pmarshalled_dataset)=0;
+		virtual void  Configure(DataSet* elements,DataSet* loads,DataSet* nodes,DataSet* vertices,DataSet* materials,Parameters* parameters)=0;
+		virtual void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type)=0;
+		virtual void  CreatePVector(Vec pg, int analysis_type,int sub_analysis_type)=0;
+		virtual void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type)=0;
+		virtual void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type)=0;
+
+		int           Enum();
+
+};
+#endif
Index: /issm/trunk/src/c/objects/Loads/Numericalflux.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Numericalflux.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Numericalflux.cpp	(revision 3683)
@@ -0,0 +1,844 @@
+/*!\file Numericalflux.c
+ * \brief: implementation of the Numericalflux object
+ */
+
+#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 "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+#include "../objects.h"
+
+extern int my_rank;
+
+/*Object constructors and destructor*/
+/*FUNCTION Numericalflux::Numericalflux(){{{1*/
+Numericalflux::Numericalflux(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Numericalflux(int numericalflux_id,int* numericalflux_node_ids,...){{{1*/
+Numericalflux::Numericalflux(int numericalflux_id,int* numericalflux_node_ids,int numnodes,int* numericalflux_element_ids, int numelements):
+	hnodes(numericalflux_node_ids,numnodes),
+	helements(numericalflux_element_ids,numelements)
+{
+
+	id=numericalflux_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Numericalflux(int id, Hook* hnodes, Hook* helements, Parameters* parameters, Inputs* numericalflux_inputs) {{{1*/
+Numericalflux::Numericalflux(int numericalflux_id,Hook* numericalflux_hnodes, Hook* numericalflux_helements, Parameters* numericalflux_parameters, Inputs* numericalflux_inputs):
+	hnodes(numericalflux_hnodes),
+	helements(numericalflux_helements)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=numericalflux_id;
+	if(numericalflux_inputs){
+		this->inputs=(Inputs*)numericalflux_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=numericalflux_parameters;
+}
+/*}}}*//*FUNCTION Numericalflux::Numericalflux(int id, int i, IoModel* iomodel) {{{1*/
+Numericalflux::Numericalflux(int numericalflux_id,int i, IoModel* iomodel){
+
+	/* Intermediary */
+	int  e1,e2;
+	int  i1,i2;
+	int  j;
+	int  pos1,pos2;
+	int  num_nodes;
+	int  num_elems;
+
+	/*numericalflux constructor data: */
+	int   numericalflux_elem_ids[2];
+	int   numericalflux_mparid;
+	int   numericalflux_node_ids[4];
+	int   numericalflux_type;
+
+	/* Get MatPar id */
+	numericalflux_mparid=iomodel->numberofelements+1; //matlab indexing
+
+	/*Get left and right elements*/
+	e1=(int)iomodel->edges[4*i+2]; //edges are [node1 node2 elem1 elem2]
+	e2=(int)iomodel->edges[4*i+3]; //edges are [node1 node2 elem1 elem2]
+	if (isnan(e2)){
+		/* Boundary edge, only one element */
+		num_elems=1;
+		num_nodes=2;
+		numericalflux_type=BoundaryEnum;
+		numericalflux_elem_ids[0]=(int)e1;
+	}
+	else{
+		/* internal edge: connected to 2 elements */
+		num_elems=2;
+		num_nodes=4;
+		numericalflux_type=InternalEnum;
+		numericalflux_elem_ids[0]=(int)e1;
+		numericalflux_elem_ids[1]=(int)e2;
+	}
+
+	/*1: Get vertices ids*/
+	i1=(int)iomodel->edges[4*i+0];
+	i2=(int)iomodel->edges[4*i+1];
+
+	if (numericalflux_type==InternalEnum){
+
+		/*Now, we must get the nodes of the 4 nodes located on the edge*/
+
+		/*2: Get the column where these ids are located in the index*/
+		pos1=pos2=UNDEF;
+		for(j=0;j<3;j++){
+			if (iomodel->elements[3*(int)e1+j]==i1) pos1=j+1;
+			if (iomodel->elements[3*(int)e2+j]==i1) pos2=j+1;
+		}
+		ISSMASSERT(pos1!=UNDEF && pos2!=UNDEF);
+
+		/*3: We have the id of the elements and the position of the vertices in the index
+		 * we can compute their dofs!*/
+		numericalflux_node_ids[0]=3*(int)e1+pos1;       //ex: 1 2 3
+		numericalflux_node_ids[1]=3*(int)e1+(pos1%3)+1; //ex: 2 3 1
+		numericalflux_node_ids[2]=3*(int)e2+pos2;           //ex: 1 2 3
+		numericalflux_node_ids[3]=3*(int)e2+((pos2+1)%3)+1; //ex: 3 1 2
+	}
+	else{
+
+		/*2: Get the column where these ids are located in the index*/
+		pos1==UNDEF;
+		for(j=0;j<3;j++){
+			if (iomodel->elements[3*(int)e1+j]==i1) pos1=j+1;
+		}
+		ISSMASSERT(pos1!=UNDEF);
+
+		/*3: We have the id of the elements and the position of the vertices in the index
+		 * we can compute their dofs!*/
+		numericalflux_node_ids[0]=3*(int)e1+pos1;
+		numericalflux_node_ids[1]=3*(int)e1+(pos1%3)+1;
+
+	}
+
+	/*Ok, we have everything to build the object: */
+	this->id=numericalflux_id;
+
+	/*Hooks: */
+	this->hnodes.Init(numericalflux_node_ids,num_nodes);
+	this->helements.Init(numericalflux_elem_ids,num_elems);
+
+	//intialize  and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+	this->inputs->AddInput(new IntInput(TypeEnum,numericalflux_type));
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*FUNCTION Numericalflux::~Numericalflux(){{{1*/
+Numericalflux::~Numericalflux(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object marshall*/
+/*FUNCTION Numericalflux::Configure {{{1*/
+void  Numericalflux::Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin){
+
+	/*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: */
+	hnodes.configure(nodesin);
+	helements.configure(elementsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::copy {{{1*/
+Object* Numericalflux::copy() {
+	return new Numericalflux(this->id,&this->hnodes,&this->helements,this->parameters,this->inputs);
+}
+/*}}}*/
+/*FUNCTION Numericalflux::DeepEcho {{{1*/
+void Numericalflux::DeepEcho(void){
+
+	printf("Numericalflux:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	helements.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+	
+}		
+/*}}}*/
+/*FUNCTION Numericalflux::Demarshall {{{1*/
+void  Numericalflux::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	helements.Demarshall(&marshalled_dataset);
+	
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Echo {{{1*/
+void Numericalflux::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Enum {{{1*/
+int Numericalflux::Enum(void){
+
+	return NumericalfluxEnum;
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Marshall {{{1*/
+void  Numericalflux::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Numericalflux: */
+	enum_type=NumericalfluxEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Numericalflux data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	helements.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::MarshallSize{{{1*/
+int   Numericalflux::MarshallSize(){
+
+	return sizeof(id)
+		+hnodes.MarshallSize()
+		+helements.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Numericalflux::MyRank {{{1*/
+int    Numericalflux::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION Numericalflux::CreateKMatrix {{{1*/
+void  Numericalflux::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	int type;
+
+	/*recover type: */
+	inputs->GetParameterValue(&type,TypeEnum);
+
+	if (type==InternalEnum){
+
+		CreateKMatrixInternal(Kgg,analysis_type,sub_analysis_type);
+	}
+	else if (type==BoundaryEnum){
+
+		CreateKMatrixBoundary(Kgg,analysis_type,sub_analysis_type);
+	}
+	else ISSMERROR("type not supported yet");
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::CreateKMatrixInternal {{{1*/
+void  Numericalflux::CreateKMatrixInternal(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int numgrids=4;
+	const int NDOF1=1;
+	const int numdof=NDOF1*numgrids;
+	double    xyz_list[numgrids][3];
+	double    normal[2];
+	int       doflist[numdof];
+	int       numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* gauss_coords =NULL;
+	double  gauss_coord;
+	double* gauss_weights=NULL;
+	double  gauss_weight;
+
+	/* matrices: */
+	double B[numgrids];
+	double L[numgrids];
+	double DL1,DL2;
+	double Ke_gg1[numdof][numdof];
+	double Ke_gg2[numdof][numdof];
+	double Ke_gg[numdof][numdof]={0.0};
+	double Jdet;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double vx,vy;
+	double UdotN;
+	double dt;
+	int    found;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Tria**  trias=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	trias=(Tria**)helements.deliverp();
+
+	/*recover parameters: */
+	if (analysis_type==Prognostic2AnalysisEnum){
+		parameters->FindParam(&dt,DtEnum);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+		/*No transient term is involved*/
+		dt=1;
+	}
+	else{
+		ISSMERROR("analysis_type %i not supported yet");
+	}
+
+	/* Get node coordinates, dof list and normal vector: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetNormal(&normal[0],xyz_list);
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	num_gauss=2;
+	GaussSegment(&gauss_coords, &gauss_weights,num_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=gauss_weights[ig];
+		gauss_coord =gauss_coords[ig];
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant(&Jdet,xyz_list,gauss_coord);
+
+		//Get vx, vy and v.n
+		trias[0]->inputs->GetParameterValue(&vx, nodes[0],nodes[1],gauss_coord,VxAverageEnum);
+		trias[0]->inputs->GetParameterValue(&vy, nodes[0],nodes[1],gauss_coord,VyAverageEnum);
+		
+		UdotN=vx*normal[0]+vy*normal[1];
+		if (fabs(UdotN)<1.0e-9 && analysis_type==Balancedthickness2AnalysisEnum) printf("Edge number %i has a flux very small (u.n = %g ), which could lead to unaccurate results\n",id,UdotN);
+
+		/*Get L and B: */
+		GetL(&L[0],gauss_coord,numdof);
+		GetB(&B[0],gauss_coord);
+
+		/*Compute DLs*/
+		DL1=gauss_weight*Jdet*dt*UdotN/2;
+		DL2=gauss_weight*Jdet*dt*fabs(UdotN)/2;
+
+		/*  Do the triple products: */
+		TripleMultiply(&B[0],1,numdof,1,
+					&DL1,1,1,0,
+					&L[0],1,numdof,0,
+					&Ke_gg1[0][0],0);
+		TripleMultiply(&B[0],1,numdof,1,
+					&DL2,1,1,0,
+					&B[0],1,numdof,0,
+					&Ke_gg2[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg1[i][j];
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg2[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+	xfree((void**)&gauss_coords);
+	xfree((void**)&gauss_weights);
+}
+/*}}}*/
+/*FUNCTION Numericalflux::CreateKMatrixBoundary {{{1*/
+void  Numericalflux::CreateKMatrixBoundary(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int numgrids=2;
+	const int NDOF1=1;
+	const int numdof=NDOF1*numgrids;
+	double    xyz_list[numgrids][3];
+	double    normal[2];
+	int       doflist[numdof];
+	int       numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* gauss_coords =NULL;
+	double  gauss_coord;
+	double* gauss_weights=NULL;
+	double  gauss_weight;
+
+	/* matrices: */
+	double L[numgrids];
+	double DL;
+	double Ke_gg[numdof][numdof]={0.0};
+	double Ke_gg_gaussian[numdof][numdof];
+	double Jdet;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double vx,vy;
+	double mean_vx;
+	double mean_vy;
+	double UdotN;
+	double dt;
+	int    dofs[1]={0};
+	int    found;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Tria**  trias=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	trias=(Tria**)helements.deliverp();
+
+	/*recover parameters: */
+	if (analysis_type==Prognostic2AnalysisEnum){
+		parameters->FindParam(&dt,DtEnum);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+		/*No transient term is involved*/
+		dt=1;
+	}
+	else{
+		ISSMERROR("analysis_type %i not supported yet");
+	}
+	
+	/* Get node coordinates, dof list and normal vector: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetNormal(&normal[0],xyz_list);
+
+	/*Check wether it is an inflow or outflow BC*/
+	trias[0]->inputs->GetParameterValue(&mean_vx, nodes[0],nodes[1],.5,VxAverageEnum);
+	trias[0]->inputs->GetParameterValue(&mean_vy, nodes[0],nodes[1],.5,VyAverageEnum);
+	UdotN=mean_vx*normal[0]+mean_vy*normal[1];
+	if (UdotN<=0){
+		/*(u,n)<0 -> inflow, PenaltyCreatePVector will take care of it*/
+		return;
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	num_gauss=2;
+	GaussSegment(&gauss_coords, &gauss_weights,num_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=gauss_weights[ig];
+		gauss_coord =gauss_coords[ig];
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant(&Jdet,xyz_list,gauss_coord);
+
+		//Get vx, vy and v.n
+		trias[0]->inputs->GetParameterValue(&vx, nodes[0],nodes[1],gauss_coord,VxAverageEnum);
+		trias[0]->inputs->GetParameterValue(&vy, nodes[0],nodes[1],gauss_coord,VyAverageEnum);
+
+		UdotN=vx*normal[0]+vy*normal[1];
+
+		/*Get L*/
+		GetL(&L[0],gauss_coord,numdof);
+
+		/*Compute DLs*/
+		DL=gauss_weight*Jdet*dt*UdotN;
+
+		/*Do triple product*/
+		TripleMultiply(&L[0],1,numdof,1,
+					&DL,1,1,0,
+					&L[0],1,numdof,0,
+					&Ke_gg_gaussian[0][0],0);
+
+		/* Add the Ke_gg_gaussian, and optionally Ke_gg_drag_gaussian onto Ke_gg: */
+		for( i=0; i<numdof; i++) for(j=0;j<numdof;j++) Ke_gg[i][j]+=Ke_gg_gaussian[i][j];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add Ke_gg to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+
+	xfree((void**)&gauss_coords);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::CreatePVector {{{1*/
+void  Numericalflux::CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type){
+
+	int type;
+
+	/*recover type: */
+	inputs->GetParameterValue(&type,TypeEnum);
+
+	if (type==InternalEnum){
+
+		CreatePVectorInternal(pg,analysis_type,sub_analysis_type);
+	}
+	else if (type==BoundaryEnum){
+
+		CreatePVectorBoundary(pg,analysis_type,sub_analysis_type);
+	}
+	else ISSMERROR("type not supported yet");
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::CreatePVectorInternal{{{1*/
+void  Numericalflux::CreatePVectorInternal(Vec pg,int analysis_type,int sub_analysis_type){
+
+	/*Nothing added to PVector*/
+	return;
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::CreatePVectorBoundary{{{1*/
+void  Numericalflux::CreatePVectorBoundary(Vec pg,int analysis_type,int sub_analysis_type){
+
+	/* local declarations */
+	int             i,j;
+
+	/* node data: */
+	const int numgrids=2;
+	const int NDOF1=1;
+	const int numdof=NDOF1*numgrids;
+	double    xyz_list[numgrids][3];
+	double    normal[2];
+	int       doflist[numdof];
+	int       numberofdofspernode;
+
+	/* gaussian points: */
+	int     num_gauss,ig;
+	double* gauss_coords =NULL;
+	double  gauss_coord;
+	double* gauss_weights=NULL;
+	double  gauss_weight;
+
+	/* matrices: */
+	double L[numgrids];
+	double DL;
+	double pe_g[numdof]={0.0};
+	double Jdet;
+
+	/*input parameters for structural analysis (diagnostic): */
+	double vx,vy;
+	double mean_vx;
+	double mean_vy;
+	double UdotN;
+	double thickness;
+	double dt;
+	int    dofs[1]={0};
+	int    found;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	Tria**  trias=NULL;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	trias=(Tria**)helements.deliverp();
+
+	/*recover parameters: */
+	if (analysis_type==Prognostic2AnalysisEnum){
+		parameters->FindParam(&dt,DtEnum);
+	}
+	else if (analysis_type==Balancedthickness2AnalysisEnum){
+		/*No transient term is involved*/
+		dt=1;
+	}
+	else{
+		ISSMERROR("analysis_type %i not supported yet");
+	}
+	
+	/* Get node coordinates, dof list and normal vector: */
+	GetVerticesCoordinates(&xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+	GetNormal(&normal[0],xyz_list);
+
+	/*Check wether it is an inflow or outflow BC*/
+	trias[0]->inputs->GetParameterValue(&mean_vx, nodes[0],nodes[1],.5,VxAverageEnum);
+	trias[0]->inputs->GetParameterValue(&mean_vy, nodes[0],nodes[1],.5,VyAverageEnum);
+	UdotN=mean_vx*normal[0]+mean_vy*normal[1];
+	if (UdotN>0){
+		/*(u,n)>0 -> outflow, PenaltyCreateKMatrix will take care of it*/
+		return;
+	}
+
+	/* Get gaussian points and weights (make this a statically initialized list of points? fstd): */
+	num_gauss=2;
+	GaussSegment(&gauss_coords, &gauss_weights,num_gauss);
+
+	/* Start  looping on the number of gaussian points: */
+	for (ig=0; ig<num_gauss; ig++){
+
+		/*Pick up the gaussian point: */
+		gauss_weight=gauss_weights[ig];
+		gauss_coord =gauss_coords[ig];
+
+		/* Get Jacobian determinant: */
+		GetJacobianDeterminant(&Jdet,xyz_list,gauss_coord);
+
+		//Get vx, vy and v.n
+		trias[0]->inputs->GetParameterValue(&vx, nodes[0],nodes[1],gauss_coord,VxAverageEnum);
+		trias[0]->inputs->GetParameterValue(&vy, nodes[0],nodes[1],gauss_coord,VyAverageEnum);
+		trias[0]->inputs->GetParameterValue(&thickness, nodes[0],nodes[1],gauss_coord,ThicknessEnum);
+
+		UdotN=vx*normal[0]+vy*normal[1];
+
+		/*Get L*/
+		GetL(&L[0],gauss_coord,numdof);
+
+		/*Compute DL*/
+		DL= - gauss_weight*Jdet*dt*UdotN*thickness;
+
+		/* Add value into pe_g: */
+		for( i=0; i<numdof; i++) pe_g[i] += DL* L[i];
+
+	} // for (ig=0; ig<num_gauss; ig++)
+
+	/*Add pe_g to global matrix Kgg: */
+	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	xfree((void**)&gauss_coords);
+	xfree((void**)&gauss_weights);
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::DistributeNumDofs {{{1*/
+void  Numericalflux::DistributeNumDofs(int* numdofspernode,int analysis_type,int sub_analysis_type){
+	return;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetB {{{1*/
+void Numericalflux::GetB(double* B, double gauss_coord){
+
+	const int numgrids=4;
+	double l1l4[numgrids];
+
+	/*Get nodal functions: */
+	GetNodalFunctions(&l1l4[0],gauss_coord);
+
+	/*Build B: */
+	B[0] = +l1l4[0];
+	B[1] = +l1l4[1];
+	B[2] = -l1l4[0];
+	B[3] = -l1l4[1];
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetDofList{{{1*/
+
+void  Numericalflux::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+
+	/*dynamic objects pointed to by hooks: */
+	Node**  nodes=NULL;
+	int type;
+
+	/*recover objects from hooks: */
+	nodes=(Node**)hnodes.deliverp();
+	
+	/*recover type: */
+	inputs->GetParameterValue(&type,TypeEnum);
+
+	if (type==InternalEnum){
+		for(i=0;i<4;i++){
+			nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+			for(j=0;j<numberofdofspernode;j++){
+				doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+			}
+		}
+	}
+	else if (type==BoundaryEnum){
+		for(i=0;i<2;i++){
+			nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+			for(j=0;j<numberofdofspernode;j++){
+				doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+			}
+		}
+	}
+	else ISSMERROR("type %s not supported yet",type);
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::Id {{{1*/
+int    Numericalflux::Id(void){
+	return id;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetJacobianDeterminant{{{1*/
+void Numericalflux::GetJacobianDeterminant(double* pJdet,double xyz_list[4][3], double gauss_coord){
+
+	double Jdet,length;
+
+	length=sqrt(pow(xyz_list[1][0] - xyz_list[0][0],2.0) + pow(xyz_list[1][1] - xyz_list[0][1],2.0));
+	Jdet=1.0/2.0*length;
+
+	if(Jdet<0){
+		ISSMERROR(" negative jacobian determinant!");
+	}
+
+	*pJdet=Jdet;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetL {{{1*/
+void Numericalflux::GetL(double* L, double gauss_coord, int numdof){
+
+	const int numgrids=4;
+	double l1l4[numgrids];
+
+	/*Check numdof*/
+	ISSMASSERT(numdof==2 || numdof==4);
+
+	/*Get nodal functions: */
+	GetNodalFunctions(&l1l4[0],gauss_coord);
+
+	/*Luild L: */
+	L[0] = l1l4[0];
+	L[1] = l1l4[1];
+	if (numdof==4){
+		L[2] = l1l4[2];
+		L[3] = l1l4[3];
+	}
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetNodalFunctions{{{1*/
+void Numericalflux::GetNodalFunctions(double* l1l4, double gauss_coord){
+
+	/*This routine returns the values of the nodal functions  at the gaussian point.*/
+
+	l1l4[0]=-0.5*gauss_coord+0.5;
+	l1l4[1]=+0.5*gauss_coord+0.5;
+	l1l4[2]=-0.5*gauss_coord+0.5;
+	l1l4[3]=+0.5*gauss_coord+0.5;
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetNormal {{{1*/
+void Numericalflux:: GetNormal(double* normal,double xyz_list[4][3]){
+
+	/*Build unit outward pointing vector*/
+	const int numgrids=4;
+	double vector[2];
+	double norm;
+
+	vector[0]=xyz_list[1][0] - xyz_list[0][0];
+	vector[1]=xyz_list[1][1] - xyz_list[0][1];
+
+	norm=sqrt(pow(vector[0],2.0)+pow(vector[1],2.0));
+
+	normal[0]= + vector[1]/norm;
+	normal[1]= - vector[0]/norm;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::GetParameterValue {{{1*/
+void Numericalflux::GetParameterValue(double* pp, double* plist, double gauss_coord){
+
+	/*From node values of parameter p (plist[0],plist[1],plist[2]), return parameter value at gaussian 
+	 * point specifie by gauss_l1l2l3: */
+
+	/*nodal functions: */
+	double l1l4[4];
+
+	/*output: */
+	double p;
+
+	GetNodalFunctions(&l1l4[0],gauss_coord);
+
+	p=l1l4[0]*plist[0]+l1l4[1]*plist[1];
+
+	/*Assign output pointers:*/
+	*pp=p;
+}
+/*}}}*/
+/*FUNCTION Numericalflux::PenaltyCreateKMatrix {{{1*/
+void  Numericalflux::PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+
+	/*No stiffness loads applied, do nothing: */
+	return;
+
+}
+/*}}}*/
+/*FUNCTION Numericalflux::PenaltyCreatePVector{{{1*/
+void  Numericalflux::PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type){
+
+	/*No penalty loads applied, do nothing: */
+	return;
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Loads/Numericalflux.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Numericalflux.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Numericalflux.h	(revision 3683)
@@ -0,0 +1,71 @@
+/*!\file Numericalflux.h
+ * \brief: header file for icefront object
+ */
+
+#ifndef _NUMERICALFLUX_H_
+#define _NUMERICALFLUX_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Load.h"
+class Hook;
+class Parameters;
+class Inputs;
+class IoModel;
+
+/*}}}*/
+
+class Numericalflux: public Load {
+
+	public: 
+		int         id;
+
+		Hook        helements;
+		Hook        hnodes;
+		Parameters *parameters;
+		Inputs     *inputs;
+
+
+		/*Constructors {{{1*/
+		Numericalflux();
+		Numericalflux(int numericalflux_id,int* numericalflux_node_ids,int numnodes, int* numericalflux_element_ids, int numelements);
+		Numericalflux(int numericalflux_id,Hook* numericalflux_hnodes, Hook* numericalflux_helements, Parameters* parameters, Inputs* numericalflux_inputs);
+		Numericalflux(int numericalflux_id,int i, IoModel* iomodel);
+		~Numericalflux();
+		/*}}}*/
+		/*Object management: {{{1*/
+		Object* copy();
+		void  Configure(DataSet* elements,DataSet* loads,DataSet* nodes,DataSet* vertices,DataSet* materials,Parameters* parameters);
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Numerics: {{{1*/
+		void  GetJacobianDeterminant(double* pJdet,double xyz_list[4][3], double gauss_coord);
+		void  GetNodalFunctions(double* l1l4, double gauss_coord);
+		void  DistributeNumDofs(int* numdofspernode,int analysis_type,int sub_analysis_type);
+		void  GetB(double* B, double gauss_coord);
+		void  GetL(double* L, double gauss_coord,int numdof);
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  GetNormal(double* normal,double xyz_list[4][3]);
+		void  GetParameterValue(double* pp, double* plist, double gauss_coord);
+		void  UpdateFromInputs(void* inputs);
+		
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixInternal(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrixBoundary(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+		void  CreatePVectorInternal(Vec pg,int analysis_type,int sub_analysis_type);
+		void  CreatePVectorBoundary(Vec pg,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type);
+		/*}}}*/
+
+};
+
+#endif  /* _NUMERICALFLUX_H_ */
Index: /issm/trunk/src/c/objects/Loads/Pengrid.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Pengrid.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Pengrid.cpp	(revision 3683)
@@ -0,0 +1,711 @@
+/*!\file Pengrid.c
+ * \brief: implementation of the Pengrid object
+ */
+
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../include/macros.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+#include "../../DataSet/DataSet.h"
+	
+/*Object constructors and destructor*/
+/*FUNCTION Pengrid::constructor {{{1*/
+Pengrid::Pengrid(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+	
+	/*not active, not zigzagging: */
+	active=0;
+	zigzag_counter=0;
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::Pengrid(int id, int node_ids int matpar_id){{{1*/
+Pengrid::Pengrid(int pengrid_id,int pengrid_node_id, int pengrid_element_id,int pengrid_matpar_id): 
+	hnode(&pengrid_node_id,1),
+	helement(&pengrid_element_id,1),
+	hmatpar(&pengrid_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=pengrid_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+	/*not active, not zigzagging: */
+	active=0;
+	zigzag_counter=0;
+
+}
+/*}}}*/
+/*FUNCTION Pengrid::Pengrid(int id, Hook* hnodes, Hook* hmatice, Hook* hmatpar, Parameters* parameters, Inputs* pengrid_inputs) {{{1*/
+Pengrid::Pengrid(int pengrid_id,Hook* pengrid_hnode, Hook* pengrid_helement,Hook* pengrid_hmatpar, Parameters* pengrid_parameters, Inputs* pengrid_inputs):
+	hnode(pengrid_hnode),
+	helement(pengrid_helement),
+	hmatpar(pengrid_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=pengrid_id;
+	if(pengrid_inputs){
+		this->inputs=(Inputs*)pengrid_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=pengrid_parameters;
+	
+	/*not active, not zigzagging: */
+	active=0;
+	zigzag_counter=0;
+
+}
+/*}}}*/
+/*FUNCTION Pengrid::Pengrid(int index, int id, IoModel* iomodel){{{1*/
+Pengrid::Pengrid(int id, int index, IoModel* iomodel){ //i is the element index
+
+	int i,j;
+	int pengrid_node_id;
+	int pengrid_matpar_id;
+	int pengrid_element_id;
+
+	/*id: */
+	this->id=id;
+	
+	/*hooks: */
+	pengrid_node_id=index+1;
+	pengrid_element_id=iomodel->singlenodetoelementconnectivity[index];
+	pengrid_matpar_id=iomodel->numberofelements+1; //refers to the constant material parameters object
+
+	this->hnode.Init(&pengrid_node_id,1);
+	this->helement.Init(&pengrid_element_id,1);
+	this->hmatpar.Init(&pengrid_matpar_id,1);
+
+	//initialize inputs: none needed
+	this->inputs=new Inputs();
+
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+
+	//let's not forget internals
+	this->active=0;
+	this->zigzag_counter=0;
+
+}
+/*}}}*/
+/*FUNCTION Pengrid::destructor {{{1*/
+Pengrid::~Pengrid(){
+	return;
+}
+/*}}}1*/
+		
+/*Object management*/
+/*FUNCTION Pengrid::Configure {{{1*/
+void  Pengrid::Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin){
+
+	/*Take care of hooking up all objects for this load, ie links the objects in the hooks to their respective 
+	 * datasets, using internal ids and offsets hidden in hooks: */
+	hnode.configure(nodesin);
+	helement.configure(elementsin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+}
+/*}}}1*/
+/*FUNCTION Pengrid::copy {{{1*/
+Object* Pengrid::copy() {
+	return new Pengrid(this->id,&this->hnode,&this->helement,&this->hmatpar,this->parameters,this->inputs);
+}
+/*}}}1*/
+/*FUNCTION Pengrid::DeepEcho{{{1*/
+void Pengrid::DeepEcho(void){
+
+	printf("Pengrid:\n");
+	printf("   id: %i\n",id);
+	hnode.DeepEcho();
+	helement.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   active %i\n",this->active);
+	printf("   zigzag_counter %i\n",this->zigzag_counter);
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Pengrid::Demarshall {{{1*/
+void  Pengrid::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(&active,marshalled_dataset,sizeof(active));marshalled_dataset+=sizeof(active);
+	memcpy(&zigzag_counter,marshalled_dataset,sizeof(zigzag_counter));marshalled_dataset+=sizeof(zigzag_counter);
+
+	/*demarshall hooks: */
+	hnode.Demarshall(&marshalled_dataset);
+	helement.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+	
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Pengrid::Echo {{{1*/
+void Pengrid::Echo(void){
+	this->DeepEcho();
+}
+/*}}}1*/
+/*FUNCTION Pengrid::Enum {{{1*/
+int Pengrid::Enum(void){
+
+	return PengridEnum;
+}
+/*}}}1*/
+/*FUNCTION Pengrid::Id {{{1*/
+int    Pengrid::Id(void){ return id; }
+/*}}}1*/
+/*FUNCTION Pengrid::Marshall {{{1*/
+void  Pengrid::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Tria: */
+	enum_type=PengridEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Tria data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(marshalled_dataset,&active,sizeof(active));marshalled_dataset+=sizeof(active);
+	memcpy(marshalled_dataset,&zigzag_counter,sizeof(zigzag_counter));marshalled_dataset+=sizeof(zigzag_counter);
+
+	/*Marshall hooks: */
+	hnode.Marshall(&marshalled_dataset);
+	helement.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Pengrid::MarshallSize {{{1*/
+int   Pengrid::MarshallSize(){
+	
+	return sizeof(id)
+		+sizeof(active)
+		+sizeof(zigzag_counter)
+		+hnode.MarshallSize()
+		+helement.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Pengrid::MyRank {{{1*/
+int    Pengrid::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Pengrid::CreateKMatrix {{{1*/
+
+void  Pengrid::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*No loads applied, do nothing: */
+	return;
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::CreatePVector {{{1*/
+void  Pengrid::CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type){
+
+	/*No loads applied, do nothing: */
+	return;
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::DistributenumDofs {{{1*/
+void  Pengrid::DistributeNumDofs(int* numdofpernode,int analysis_type,int sub_analysis_type){return;}
+/*}}}1*/
+/*FUNCTION Pengrid::GetDofList {{{1*/
+void  Pengrid::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+
+	/*dynamic objects pointed to by hooks: */
+	Node* node=NULL;
+
+	/*recover objects from hooks: */
+	node=(Node*)hnode.delivers();
+	
+	node->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+	for(j=0;j<numberofdofspernode;j++){
+		doflist[j]=doflist_per_node[j];
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+
+}
+/*}}}*/
+/*FUNCTION Pengrid::PenaltyConstrain {{{1*/
+void  Pengrid::PenaltyConstrain(int* punstable,int analysis_type,int sub_analysis_type){
+
+	if ((analysis_type==DiagnosticAnalysisEnum) && ((sub_analysis_type==StokesAnalysisEnum))){
+
+		/*No penalty to check*/
+		return;
+
+	}
+	else if (analysis_type==ThermalAnalysisEnum){
+		
+		PenaltyConstrainThermal(punstable,analysis_type,sub_analysis_type);
+		
+	}
+	else if (analysis_type==MeltingAnalysisEnum){
+			
+		/*No penalty to check*/
+		return;
+
+	}
+	else{
+		ISSMERROR("%s%i%s%i%s","analysis: ",analysis_type," and sub_analysis_type: ",sub_analysis_type," not supported yet");
+	}
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyConstrainThermal {{{1*/
+void  Pengrid::PenaltyConstrainThermal(int* punstable,int analysis_type,int sub_analysis_type){
+
+	//   The penalty is stable if it doesn't change during to successive iterations.   
+
+	int    found=0;
+	const int numgrids=1;
+	double pressure;
+	double temperature;
+	double beta,t_pmp;
+	double meltingpoint;
+	int    new_active;
+	int    unstable=0;
+	int    reset_penalties=0;
+	int    stabilize_constraints;
+
+	/*pointers: */
+	Node* node=NULL;
+	Penta* penta=NULL;
+	Matpar*  matpar=NULL;
+	
+	/*check that pengrid is not a clone (penalty to be added only once)*/
+	if (node->IsClone()){
+		unstable=0;
+		*punstable=unstable;
+		return;
+	}
+
+	/*recover pointers: */
+	node=(Node*)hnode.delivers();
+	penta=(Penta*)helement.delivers();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	//First recover pressure and temperature values, using the element: */
+	penta->inputs->GetParameterValue(&pressure,node,PressureEnum);
+	penta->inputs->GetParameterValue(&temperature,node,TemperatureEnum);
+
+	//Recover our data:
+	inputs->GetParameterValue(&reset_penalties,ResetPenaltiesEnum);
+	meltingpoint=matpar->GetMeltingPoint();
+	beta=matpar->GetBeta();
+	parameters->FindParam(&stabilize_constraints,StabilizeConstraintsEnum);
+	
+	if(reset_penalties)zigzag_counter=0;
+
+	//Compute pressure melting point
+	t_pmp=meltingpoint-beta*pressure;
+
+	//Figure out if temperature is over melting_point, in which case, this penalty needs to be activated.
+
+	if (temperature>t_pmp){
+		new_active=1;
+	}
+	else{
+		new_active=0;
+	}
+
+
+	//Figure out stability of this penalty
+	if (active==new_active){
+		unstable=0;
+	}
+	else{
+		unstable=1;
+		if(stabilize_constraints)zigzag_counter++;
+	}
+
+	/*If penalty keeps zigzagging more than 5 times: */
+	if(stabilize_constraints){
+		if(zigzag_counter>stabilize_constraints){
+			unstable=0;
+			active=1;
+		}
+	}
+
+	//Set penalty flag
+	active=new_active;
+
+	//*Assign output pointers:*/
+	*punstable=unstable;
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreateMatrix {{{1*/
+void  Pengrid::PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+
+	if ((analysis_type==DiagnosticAnalysisEnum) && ((sub_analysis_type==StokesAnalysisEnum))){
+
+		PenaltyCreateKMatrixDiagnosticStokes( Kgg,kmax,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==ThermalAnalysisEnum){
+		
+		PenaltyCreateKMatrixThermal( Kgg,kmax,analysis_type,sub_analysis_type);
+		
+	}
+	else if (analysis_type==MeltingAnalysisEnum){
+			
+		PenaltyCreateKMatrixMelting( Kgg,kmax,analysis_type,sub_analysis_type);
+
+	}
+	else{
+		ISSMERROR("%s%i%s%i%s","analysis: ",analysis_type," and sub_analysis_type: ",sub_analysis_type," not supported yet");
+	}
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreateKMatrixDiagnosticStokes {{{1*/
+void  Pengrid::PenaltyCreateKMatrixDiagnosticStokes(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+	
+	const int numgrids=1;
+	const int NDOF4=4;
+	const int numdof=numgrids*NDOF4;
+	int       doflist[numdof];
+	int       numberofdofspernode;
+
+	int dofs1[1]={0};
+	int dofs2[1]={1};
+	double slope[2];
+	int found=0;
+	double Ke[4][4]={0.0};
+	double penalty_offset;
+
+	/*pointers: */
+	Node* node=NULL;
+	Penta* penta=NULL;
+
+	/*Get dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*recover pointers: */
+	node=(Node*)hnode.delivers();
+	penta=(Penta*)helement.delivers();
+
+	//recover slope: */
+	penta->inputs->GetParameterValue(&slope[0],node,BedSlopexEnum);
+	penta->inputs->GetParameterValue(&slope[1],node,BedSlopeyEnum);
+	
+	/*recover parameters: */
+	parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+
+	//Create elementary matrix: add penalty to contrain wb (wb=ub*db/dx+vb*db/dy)
+	Ke[2][0]=-slope[0]*kmax*pow((double)10.0,penalty_offset);
+	Ke[2][1]=-slope[1]*kmax*pow((double)10.0,penalty_offset);
+	Ke[2][2]=kmax*pow((double)10,penalty_offset);
+	
+	/*Add Ke to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke,ADD_VALUES);
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreateKMatrixMelting {{{1*/
+void  Pengrid::PenaltyCreateKMatrixMelting(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+
+
+	int found=0;
+	const int numgrids=1;
+	const int NDOF1=1;
+	const int numdof=numgrids*NDOF1;
+	double Ke[numdof][numdof]={0.0};
+	int     dofs1[1]={0};
+	int       doflist[numdof];
+	int      numberofdofspernode;
+	double  meltingpoint;
+
+	double pressure;
+	double temperature;
+	double beta,t_pmp;
+	double penalty_offset;
+
+	/*pointers: */
+	Node* node=NULL;
+	Penta* penta=NULL;
+	Matpar*  matpar=NULL;
+
+	/*recover pointers: */
+	node=(Node*)hnode.delivers();
+	penta=(Penta*)helement.delivers();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/*check that pengrid is not a clone (penalty to be added only once)*/
+	if (node->IsClone()) return;
+
+	//First recover pressure and temperature values, using the element: */
+	penta->inputs->GetParameterValue(&pressure,node,PressureEnum);
+	penta->inputs->GetParameterValue(&temperature,node,TemperatureEnum);
+
+	/*recover parameters: */
+	parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+
+	/*Get dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+	
+	//Compute pressure melting point
+	meltingpoint=matpar->GetMeltingPoint();
+	beta=matpar->GetBeta();
+	t_pmp=meltingpoint-beta*pressure;
+
+	//Add penalty load
+	if (temperature<t_pmp){ //If T<Tpmp, there must be no melting. Therefore, melting should be  constrained to 0 when T<Tpmp, instead of using spcs, use penalties
+		Ke[0][0]=kmax*pow((double)10,penalty_offset);
+	}
+	
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke,ADD_VALUES);
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreateKMatrixThermal {{{1*/
+void  Pengrid::PenaltyCreateKMatrixThermal(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+
+	int found=0;
+	
+	const int numgrids=1;
+	const int NDOF1=1;
+	const int numdof=numgrids*NDOF1;
+	double Ke[numdof][numdof];
+	int       doflist[numdof];
+	int       numberofdofspernode;
+	double    penalty_offset;
+
+	if(!this->active)return;
+
+	/*recover parameters: */
+	parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+
+	/*Get dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	Ke[0][0]=kmax*pow((double)10,penalty_offset);
+	
+	/*Add Ke to global matrix Kgg: */
+	MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke,ADD_VALUES);
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreatePVector {{{1*/
+void  Pengrid::PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type){
+
+	if (analysis_type==ThermalAnalysisEnum){
+		
+		PenaltyCreatePVectorThermal( pg,kmax,analysis_type,sub_analysis_type);
+		
+	}
+	else if (analysis_type==MeltingAnalysisEnum){
+			
+		PenaltyCreatePVectorMelting( pg,kmax,analysis_type,sub_analysis_type);
+
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum){
+
+		/*No loads applied, do nothing: */
+		return;
+
+	}
+	else{
+		ISSMERROR("%s%i%s%i%s","analysis: ",analysis_type," and sub_analysis_type: ",sub_analysis_type," not supported yet");
+	}
+
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreatePVectorMelting {{{1*/
+void  Pengrid::PenaltyCreatePVectorMelting(Vec pg, double kmax,int analysis_type,int sub_analysis_type){
+	
+	const int numgrids=1;
+	const int NDOF1=1;
+	const int numdof=numgrids*NDOF1;
+	int    doflist[numdof];
+	double P_terms[numdof]={0.0};
+	int    numberofdofspernode;
+	int    found=0;
+	int    dofs1[1]={0};
+	double pressure;
+	double temperature;
+	double melting_offset;
+	double meltingpoint;
+	double beta, heatcapacity;
+	double latentheat;
+	double t_pmp;
+	double dt,penalty_offset;
+
+	/*pointers: */
+	Node* node=NULL;
+	Penta* penta=NULL;
+	Matpar*  matpar=NULL;
+
+	/*recover pointers: */
+	node=(Node*)hnode.delivers();
+	penta=(Penta*)helement.delivers();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/*check that pengrid is not a clone (penalty to be added only once)*/
+	if (node->IsClone()) return;
+
+	/*Get dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//First recover pressure and temperature values, using the element: */
+	penta->inputs->GetParameterValue(&pressure,node,PressureEnum);
+	penta->inputs->GetParameterValue(&temperature,node,TemperatureEnum);
+	inputs->GetParameterValue(&melting_offset,MeltingOffsetEnum);
+	parameters->FindParam(&dt,DtEnum);
+	parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+
+	meltingpoint=matpar->GetMeltingPoint();
+	beta=matpar->GetBeta();
+	heatcapacity=matpar->GetHeatCapacity();
+	latentheat=matpar->GetLatentHeat();
+
+	//Compute pressure melting point
+	t_pmp=meltingpoint-beta*pressure;
+
+	//Add penalty load
+	//This time, the penalty must have the same value as the one used for the thermal computation
+	//so that the corresponding melting can be computed correctly
+	//In the thermal computation, we used kmax=melting_offset, and the same penalty_offset
+	if (temperature<t_pmp){ //%no melting
+		P_terms[0]=0;
+	}
+	else{
+		if (dt){
+			P_terms[0]=melting_offset*pow((double)10,penalty_offset)*(temperature-t_pmp)/dt;
+		}
+		else{
+			P_terms[0]=melting_offset*pow((double)10,penalty_offset)*(temperature-t_pmp);
+		}
+	}
+
+	/*Add P_terms to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+}
+/*}}}1*/
+/*FUNCTION Pengrid::PenaltyCreatePVectorThermal {{{1*/
+void  Pengrid::PenaltyCreatePVectorThermal(Vec pg,  double kmax,int analysis_type,int sub_analysis_type){
+
+	const int numgrids=1;
+	const int NDOF1=1;
+	const int numdof=numgrids*NDOF1;
+	int       doflist[numdof];
+	double  P_terms[numdof]={0.0};
+	int    numberofdofspernode;
+	int    found=0;
+	double pressure;
+	int dofs1[1]={0};
+	double meltingpoint;
+	double beta;
+	double t_pmp;
+	double penalty_offset;
+
+	/*pointers: */
+	Node* node=NULL;
+	Penta* penta=NULL;
+	Matpar*  matpar=NULL;
+
+	/*recover pointers: */
+	node=(Node*)hnode.delivers();
+	penta=(Penta*)helement.delivers();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	if(!this->active)return;
+
+	/*Get dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	//First recover pressure  and penalty_offset
+	penta->inputs->GetParameterValue(&pressure,node,PressureEnum);
+	parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+
+	//Compute pressure melting point
+	meltingpoint=matpar->GetMeltingPoint();
+	beta=matpar->GetBeta();
+	t_pmp=meltingpoint-beta*pressure;
+
+	//Add penalty load
+	P_terms[0]=kmax*pow((double)10,penalty_offset)*t_pmp;
+
+	/*Add P_terms to global vector pg: */
+	VecSetValues(pg,numdof,doflist,(const double*)P_terms,ADD_VALUES);
+}
+/*}}}1*/
+
+/*Updates: */
+/*FUNCTION Pengrid::UpdateFromDakota {{{1*/
+void  Pengrid::UpdateFromDakota(void* inputs){
+	ISSMERROR("not supported yet!");
+}
+/*}}}1*/
+/*FUNCTION Pengrid::UpdateInputs {{{1*/
+void  Pengrid::UpdateInputs(double* solution, int analysis_type, int sub_analysis_type){
+	ISSMERROR("not supported yet!");
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Loads/Pengrid.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Pengrid.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Pengrid.h	(revision 3683)
@@ -0,0 +1,78 @@
+/*!\file Pengrid.h
+ * \brief: header file for pengrid object */
+
+#ifndef _PENGRID_H_
+#define _PENGRID_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Load.h"
+class Hook;
+class Inputs;
+class Parameters;
+class IoModel;
+/*}}}*/
+
+class Pengrid: public Load{
+
+	private: 
+
+		int		id;
+		
+		Hook hnode;  //hook to 1 node
+		Hook helement;  //hook to 1 element
+		Hook hmatpar; //hook to 1 matpar
+
+		Parameters* parameters; //pointer to solution parameters
+		Inputs*  inputs;
+	
+		/*internals: */
+		int active;
+		int zigzag_counter;
+
+	public:
+
+		/*FUNCTION constructors, destructors {{{1*/
+		Pengrid();
+		Pengrid(int pengrid_id,int pengrid_node_id, int pengrid_element_id,int pengrid_matpar_id);
+		Pengrid(int pengrid_id,Hook* pengrid_hnode, Hook* pengrid_helement,Hook* pengrid_hmatpar, Parameters* pengrid_parameters, Inputs* pengrid_inputs);
+		Pengrid(int index, int id, IoModel* iomodel);
+		~Pengrid();
+		/*}}}*/
+		/*FUNCTION object management {{{1*/
+		void  Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*FUNCTION element numerical routines {{{1*/
+		void  DistributeNumDofs(int* numdofspernode,int analysis_type,int sub_analysis_type);
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg, int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrixDiagnosticStokes(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  GetDofList(int* doflist,int* pnumberofdofspernode);
+		void  PenaltyCreateKMatrixThermal(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrixMelting(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVectorThermal(Vec pg, double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVectorMelting(Vec pg, double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyConstrain(int* punstable,int analysis_type,int sub_analysis_type);
+		void  PenaltyConstrainThermal(int* punstable,int analysis_type,int sub_analysis_type);
+		
+		/*updates:*/
+		void  UpdateFromDakota(void* inputs);
+		void  UpdateInputs(double* solution, int analysis_type, int sub_analysis_type);
+		/*}}}*/
+
+};
+
+#endif  /* _PENGRID_H_ */
+
+
Index: /issm/trunk/src/c/objects/Loads/Penpair.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Penpair.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Penpair.cpp	(revision 3683)
@@ -0,0 +1,194 @@
+/*!\file Penpair.c
+ * \brief: implementation of the Penpair object
+ */
+
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../include/macros.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+
+		
+/*Object constructors and destructor*/
+/*FUNCTION Penpair::constructor {{{1*/
+Penpair::Penpair(){
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::creation {{{1*/
+Penpair::Penpair(int penpair_id, int* penpair_node_ids):
+	hnodes(penpair_node_ids,2)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=penpair_id;
+	
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::creation {{{1*/
+Penpair::Penpair(int penpair_id, Hook* penpair_hnodes):
+	hnodes(penpair_hnodes)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=penpair_id;
+	
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::destructor {{{1*/
+Penpair::~Penpair(){
+	return;
+}
+/*}}}1*/
+		
+/*Object marshall*/
+/*FUNCTION Penpair::Configure {{{1*/
+void  Penpair::Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin){
+
+	/*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: */
+	hnodes.configure(nodesin);
+
+}
+/*}}}1*/
+/*FUNCTION Penpair::copy {{{1*/
+Object* Penpair::copy() {
+	return new Penpair(this->id,&this->hnodes); 
+}
+/*}}}1*/
+/*FUNCTION Penpair::DeepEcho {{{1*/
+void Penpair::DeepEcho(void){
+
+	printf("Penpair:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+
+	return;
+}		
+/*}}}1*/
+/*FUNCTION Penpair::Echo {{{1*/
+void Penpair::Echo(void){
+
+	int i;
+
+	printf("Penpair:\n");
+	printf("   id: %i\n",id);
+	hnodes.Echo();
+	
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::Marshall {{{1*/
+void  Penpair::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Penpair: */
+	enum_type=PenpairEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Penpair data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*Marshall hooks*/
+	hnodes.Marshall(&marshalled_dataset);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::MarshallSize {{{1*/
+int   Penpair::MarshallSize(){
+
+	return sizeof(id)+
+		+hnodes.MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}1*/
+/*FUNCTION Penpair::Demarshall {{{1*/
+void  Penpair::Demarshall(char** pmarshalled_dataset){
+
+	int i;
+	char* marshalled_dataset=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Penpair::CreateKMatrix {{{1*/
+
+void  Penpair::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+
+	/*No loads applied, do nothing: */
+	return;
+
+}
+/*}}}1*/
+/*FUNCTION Penpair::CreatePVector {{{1*/
+void  Penpair::CreatePVector(Vec pg, int analysis_type,int sub_analysis_type){
+
+	/*No loads applied, do nothing: */
+	return;
+
+}
+/*}}}1*/
+/*FUNCTION Penpair::Enum {{{1*/
+int Penpair::Enum(void){
+
+	return PenpairEnum;
+}
+/*}}}1*/
+/*FUNCTION Penpair::Id {{{1*/
+int    Penpair::Id(void){ return id; }
+/*}}}1*/
+/*FUNCTION Penpair::MyRank {{{1*/
+int    Penpair::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
+/*FUNCTION Penpair::PenaltyCreateKMatrix {{{1*/
+void  Penpair::PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+	
+	/*If you code this piece, don't forget that a penalty will be inactive if it is dealing with clone nodes*/
+	/*No loads applied, do nothing: */
+	return;
+}
+/*}}}1*/
+/*FUNCTION Penpair::PenaltyCreatePVector {{{1*/
+void  Penpair::PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type){
+	/*No loads applied, do nothing: */
+	return;
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Loads/Penpair.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Penpair.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Penpair.h	(revision 3683)
@@ -0,0 +1,50 @@
+/*!\file Penpair.h
+ * \brief: header file for penpair object */
+
+#ifndef _PENPAIR_H_
+#define _PENPAIR_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Load.h"
+#include "../Node.h"
+#include "../Elements/Element.h"
+
+class Element;
+/*}}}*/
+
+class Penpair: public Load{
+
+	private: 
+
+		int		id;
+		
+		Hook hnodes;  //hook to 2 nodes
+
+	public:
+
+		Penpair();
+		Penpair(int penpair_id,int* penpair_node_ids);
+		Penpair(int penpair_id,Hook* penpair_hnodes);
+		~Penpair();
+
+		void  Echo();
+		void  DeepEcho();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   Id(); 
+		int   MyRank();
+		void  Configure(DataSet* elements,DataSet* loads,DataSet* nodes,DataSet* vertices,DataSet* materials,Parameters* parameters);
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg, int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type);
+		Object* copy();
+
+};
+
+#endif  /* _PENPAIR_H_ */
+
+
Index: /issm/trunk/src/c/objects/Loads/Riftfront.cpp
===================================================================
--- /issm/trunk/src/c/objects/Loads/Riftfront.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Riftfront.cpp	(revision 3683)
@@ -0,0 +1,931 @@
+/*!\file Riftfront.cpp
+ * \brief: implementation of the Riftfront object
+ */
+
+/*Headers:*/
+/*{{{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 "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+#include "../../ModelProcessorx/ModelProcessorx.h"
+#include "../objects.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION Riftfront::Riftfront(){{{1*/
+Riftfront::Riftfront(){
+	this->inputs=NULL;
+	this->parameters=NULL;
+}
+/*}}}*/
+/*FUNCTION Riftfront::Riftfront(int id, int* node_ids, int matice_id, int matpar_id){{{1*/
+Riftfront::Riftfront(int riftfront_id,int* riftfront_node_ids, int riftfront_matpar_id): 
+	hnodes(riftfront_node_ids,2),
+	hmatpar(&riftfront_matpar_id,1)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=riftfront_id;
+	this->parameters=NULL;
+	this->inputs=new Inputs();
+
+}
+/*}}}*/
+/*FUNCTION Riftfront::Riftfront(int id, Hook* hnodes, Hook* hmatice, Hook* hmatpar, Parameters* parameters, Inputs* riftfront_inputs) {{{1*/
+Riftfront::Riftfront(int riftfront_id,Hook* riftfront_hnodes, Hook* riftfront_hmatpar, Parameters* riftfront_parameters, Inputs* riftfront_inputs):
+	hnodes(riftfront_hnodes),
+	hmatpar(riftfront_hmatpar)
+{
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=riftfront_id;
+	if(riftfront_inputs){
+		this->inputs=(Inputs*)riftfront_inputs->Copy();
+	}
+	else{
+		this->inputs=new Inputs();
+	}
+	/*point parameters: */
+	this->parameters=riftfront_parameters;
+}
+/*}}}*/
+/*FUNCTION Riftfront::Riftfront(int id, int i, IoModel* iomodel){{{1*/
+Riftfront::Riftfront(int riftfront_id,int i, IoModel* iomodel){
+
+	/*data: */
+	int    riftfront_node_ids[2];
+	int    riftfront_matpar_id;
+	int    riftfront_type;
+	double riftfront_fill;
+	double riftfront_friction;
+	double riftfront_fractionincrement;
+	bool   riftfront_shelf;
+
+	/*intermediary: */
+	int el1    ,el2;
+	int grid1  ,grid2;
+
+	/*Ok, retrieve all the data needed to add a penalty between the two grids: */
+	el1=(int)*(iomodel->riftinfo+RIFTINFOSIZE*i+2);
+	el2=(int)*(iomodel->riftinfo+RIFTINFOSIZE*i+3); 
+
+	grid1=(int)*(iomodel->riftinfo+RIFTINFOSIZE*i+0); 
+	grid2=(int)*(iomodel->riftinfo+RIFTINFOSIZE*i+1);
+
+	/*id: */
+	this->id=riftfront_id;
+
+	/*hooks: */
+	riftfront_node_ids[0]=grid1;
+	riftfront_node_ids[1]=grid2;
+	riftfront_matpar_id=iomodel->numberofelements+1; //matlab indexing
+
+	this->hnodes.Init(riftfront_node_ids,2);
+	this->hmatpar.Init(&riftfront_matpar_id,1);
+
+	/*computational parameters: */
+	this->active=0;
+	this->frozen=0;
+	this->counter=0;
+	this->prestable=0;
+	this->penalty_lock=0;
+	this->material_converged=0;
+	this->normal[0]=*(iomodel->riftinfo+RIFTINFOSIZE*i+4);
+	this->normal[1]=*(iomodel->riftinfo+RIFTINFOSIZE*i+5);
+	this->length=*(iomodel->riftinfo+RIFTINFOSIZE*i+6);
+	this->fraction=*(iomodel->riftinfo+RIFTINFOSIZE*i+9);
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+		
+	riftfront_type=SegmentRiftfrontEnum;
+	riftfront_fill = (int)*(iomodel->riftinfo+RIFTINFOSIZE*i+7);
+	riftfront_friction=*(iomodel->riftinfo+RIFTINFOSIZE*i+8);
+	riftfront_fractionincrement=*(iomodel->riftinfo+RIFTINFOSIZE*i+10);
+	riftfront_shelf=(bool)iomodel->gridoniceshelf[grid1-1];
+
+	this->inputs->AddInput(new IntInput(TypeEnum,riftfront_type));
+	this->inputs->AddInput(new DoubleInput(FillEnum,riftfront_fill));
+	this->inputs->AddInput(new DoubleInput(FrictionEnum,riftfront_friction));
+	this->inputs->AddInput(new DoubleInput(FractionIncrementEnum,riftfront_fractionincrement));
+	this->inputs->AddInput(new BoolInput(SegmentOnIceShelfEnum,riftfront_shelf));
+	
+	//this->parameters: we still can't point to it, it may not even exist. Configure will handle this.
+	this->parameters=NULL;
+		
+}
+/*}}}1*/
+/*FUNCTION Riftfront::~Riftfront(){{{1*/
+Riftfront::~Riftfront(){
+	delete inputs;
+	this->parameters=NULL;
+}
+/*}}}*/
+
+/*Object marshall*/
+/*FUNCTION Riftfront::copy {{{1*/
+Object* Riftfront::copy() {
+	return new Riftfront(*this); 
+}
+/*}}}1*/
+/*FUNCTION Riftfront::Configure {{{1*/
+void  Riftfront::Configure(DataSet* elementsin,DataSet* loadsin,DataSet* nodesin,DataSet* verticesin,DataSet* materialsin,Parameters* parametersin){
+
+	/*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: */
+	hnodes.configure(nodesin);
+	hmatpar.configure(materialsin);
+
+	/*point parameters to real dataset: */
+	this->parameters=parametersin;
+
+}
+/*}}}*/
+/*FUNCTION Riftfront::DeepEcho{{{1*/
+void Riftfront::DeepEcho(void){
+
+	printf("Riftfront:\n");
+	printf("   id: %i\n",id);
+	hnodes.DeepEcho();
+	hmatpar.DeepEcho();
+	printf("   parameters\n");
+	parameters->DeepEcho();
+	printf("   inputs\n");
+	inputs->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION Riftfront::Demarshall {{{1*/
+void  Riftfront::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&id,marshalled_dataset,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(&active,marshalled_dataset,sizeof(active));marshalled_dataset+=sizeof(active);
+	memcpy(&normal,marshalled_dataset,sizeof(normal));marshalled_dataset+=sizeof(normal);
+	memcpy(&length,marshalled_dataset,sizeof(length));marshalled_dataset+=sizeof(length);
+	memcpy(&fraction,marshalled_dataset,sizeof(fraction));marshalled_dataset+=sizeof(fraction);
+	memcpy(&frozen,marshalled_dataset,sizeof(frozen));marshalled_dataset+=sizeof(frozen);
+	memcpy(&counter,marshalled_dataset,sizeof(counter));marshalled_dataset+=sizeof(counter);
+	memcpy(&prestable,marshalled_dataset,sizeof(prestable));marshalled_dataset+=sizeof(prestable);
+	memcpy(&penalty_lock,marshalled_dataset,sizeof(penalty_lock));marshalled_dataset+=sizeof(penalty_lock);
+	memcpy(&material_converged,marshalled_dataset,sizeof(material_converged));marshalled_dataset+=sizeof(material_converged);
+
+	/*demarshall hooks: */
+	hnodes.Demarshall(&marshalled_dataset);
+	hmatpar.Demarshall(&marshalled_dataset);
+	
+	/*demarshall inputs: */
+	inputs=(Inputs*)DataSetDemarshallRaw(&marshalled_dataset); 
+
+	/*parameters: may not exist even yet, so let Configure handle it: */
+	this->parameters=NULL;
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION Riftfront::Echo {{{1*/
+void Riftfront::Echo(void){
+	this->DeepEcho();
+}
+/*}}}1*/
+/*FUNCTION Riftfront::Enum {{{1*/
+int Riftfront::Enum(void){
+
+	return RiftfrontEnum;
+
+}
+/*}}}1*/
+/*FUNCTION Riftfront::Id {{{1*/
+int    Riftfront::Id(void){ return id; }
+/*}}}1*/
+/*FUNCTION Riftfront::Marshall {{{1*/
+void  Riftfront::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+	char* marshalled_inputs=NULL;
+	int   marshalled_inputs_size;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Riftfront: */
+	enum_type=RiftfrontEnum;
+
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	/*marshall Riftfront data: */
+	memcpy(marshalled_dataset,&id,sizeof(id));marshalled_dataset+=sizeof(id);
+	memcpy(marshalled_dataset,&active,sizeof(active));marshalled_dataset+=sizeof(active);
+	memcpy(marshalled_dataset,&normal,sizeof(normal));marshalled_dataset+=sizeof(normal);
+	memcpy(marshalled_dataset,&length,sizeof(length));marshalled_dataset+=sizeof(length);
+	memcpy(marshalled_dataset,&fraction,sizeof(fraction));marshalled_dataset+=sizeof(fraction);
+	memcpy(marshalled_dataset,&frozen,sizeof(frozen));marshalled_dataset+=sizeof(frozen);
+	memcpy(marshalled_dataset,&counter,sizeof(counter));marshalled_dataset+=sizeof(counter);
+	memcpy(marshalled_dataset,&prestable,sizeof(prestable));marshalled_dataset+=sizeof(prestable);
+	memcpy(marshalled_dataset,&penalty_lock,sizeof(penalty_lock));marshalled_dataset+=sizeof(penalty_lock);
+
+	/*Marshall hooks: */
+	hnodes.Marshall(&marshalled_dataset);
+	hmatpar.Marshall(&marshalled_dataset);
+
+	/*Marshall inputs: */
+	marshalled_inputs_size=inputs->MarshallSize();
+	marshalled_inputs=inputs->Marshall();
+	memcpy(marshalled_dataset,marshalled_inputs,marshalled_inputs_size*sizeof(char));
+	marshalled_dataset+=marshalled_inputs_size;
+
+	/*parameters: don't do anything about it. parameters are marshalled somewhere else!*/
+
+	xfree((void**)&marshalled_inputs);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Riftfront::MarshallSize {{{1*/
+int   Riftfront::MarshallSize(){
+	
+	return sizeof(id)
+		+sizeof(active)
+		+sizeof(normal)
+		+sizeof(length)
+		+sizeof(fraction)
+		+sizeof(frozen)
+		+sizeof(counter)
+		+sizeof(prestable)
+		+sizeof(penalty_lock)
+		+hnodes.MarshallSize()
+		+hmatpar.MarshallSize()
+		+inputs->MarshallSize()
+		+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Riftfront::MyRank {{{1*/
+int    Riftfront::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Riftfront::Constrain {{{1*/
+#define _ZIGZAGCOUNTER_
+
+int   Riftfront::Constrain(int* punstable,  int analysis_type){
+
+	const int   numgrids        = 2;
+	double      max_penetration;
+	double      penetration;
+	int         activate;
+	int         found;
+	int         unstable;
+	double      vx1;
+	double      vy1;
+	double      vx2;
+	double      vy2;
+	double      fractionincrement;
+
+
+	/*Objects: */
+	Element   **elements        = NULL;
+	Node      **nodes           = NULL;
+	Tria       *tria1           = NULL;
+	Tria       *tria2           = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	/*Is this constraint frozen? In which case we don't touch: */
+	if (this->frozen){
+		*punstable=0;
+		return 1;
+	}
+
+	/*recover parameters: */
+	this->inputs->GetParameterValue(&fractionincrement,FractionIncrementEnum);
+
+	/*First recover velocity: */
+	tria1->inputs->GetParameterValue(&vx1,nodes[0],VxEnum);
+	tria2->inputs->GetParameterValue(&vx2,nodes[1],VxEnum);
+	tria1->inputs->GetParameterValue(&vy1,nodes[0],VyEnum);
+	tria2->inputs->GetParameterValue(&vy2,nodes[1],VyEnum);
+
+	/*Node 1 faces node 2, compute penetration of 2 into 1 (V2-V1).N (with N normal vector, and V velocity vector: */
+	penetration=(vx2-vx1)*normal[0]+(vy2-vy1)*normal[1];
+
+	/*activation: */
+	if(penetration<0)activate=1;
+	else  activate=0;
+
+	/*Here, we try to avoid zigzaging. When a penalty activates and deactivates for more than penalty_lock times, 
+	 * we increase the fraction of melange:*/
+	if(this->counter>this->penalty_lock){
+		/*reset counter: */
+		this->counter=0;
+		/*increase melange fraction: */
+		this->fraction+=fractionincrement;
+		if (this->fraction>1)this->fraction=(double)1.0;
+		//printf("riftfront %i fraction: %g\n",this->Id(),this->fraction);
+	}
+
+	//Figure out stability of this penalty
+	if(this->active==activate){
+		unstable=0;
+	}
+	else{
+		unstable=1;
+		this->counter++;
+	}
+
+	//Set penalty flag
+	this->active=activate;
+
+	//if ((penetration>0) & (this->active==1))printf("Riftfront %i wants to be released\n",Id());
+
+	/*assign output pointer: */
+	*punstable=unstable;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::CreateKMatrix {{{1*/
+void  Riftfront::CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type){
+	/*do nothing: */
+}
+/*}}}1*/
+/*FUNCTION Riftfront::CreatePVector {{{1*/
+void  Riftfront::CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type){
+	/*do nothing: */
+}
+/*}}}1*/
+/*FUNCTION Riftfront::FreezeConstraints{{{1*/
+void   Riftfront::FreezeConstraints( int analysis_type){
+
+	/*Just set frozen flag to 1: */
+	this->frozen=1;
+
+}
+/*}}}1*/
+/*FUNCTION Riftfront::GetDofList {{{1*/
+
+void  Riftfront::GetDofList(int* doflist,int* pnumberofdofspernode){
+
+	int i,j;
+	int doflist_per_node[MAXDOFSPERNODE];
+	int numberofdofspernode;
+	Node      **nodes           = NULL;
+	
+	nodes=(Node**)hnodes.deliverp();
+
+	for(i=0;i<MAX_RIFTFRONT_GRIDS;i++){
+		nodes[i]->GetDofList(&doflist_per_node[0],&numberofdofspernode);
+		for(j=0;j<numberofdofspernode;j++){
+			doflist[i*numberofdofspernode+j]=doflist_per_node[j];
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pnumberofdofspernode=numberofdofspernode;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::IsFrozen{{{1*/
+bool   Riftfront::IsFrozen(void){
+
+	/*Just set frozen flag to 1: */
+	if(this->frozen)return 1;
+	else return 0;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::IsMaterialStable {{{1*/
+int   Riftfront::IsMaterialStable( int analysis_type){
+
+	int found=0;
+	double converged=0;
+
+	this->inputs->GetParameterValue(&converged,ConvergedEnum);
+
+	if(converged){
+		/*ok, material non-linearity has converged. If that was already the case, we keep 
+		 * constraining the rift front. If it was not, and this is the first time the material 
+		 * has converged, we start constraining now!: */
+		this->material_converged=1;
+	}
+
+	return this->material_converged;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::MaxPenetration {{{1*/
+int   Riftfront::MaxPenetration(double* ppenetration,  int analysis_type){
+
+	const int     numgrids=2;
+	double        max_penetration;
+	double        penetration=0;
+	int           found;
+	double      vx1;
+	double      vy1;
+	double      vx2;
+	double      vy2;
+
+	/*Objects: */
+	Element   **elements        = NULL;
+	Node      **nodes           = NULL;
+	Tria       *tria1           = NULL;
+	Tria       *tria2           = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	//initialize: 
+	penetration=-1;
+
+	/*recover velocity: */
+	tria1->inputs->GetParameterValue(&vx1,nodes[0],VxEnum);
+	tria2->inputs->GetParameterValue(&vx2,nodes[1],VxEnum);
+	tria1->inputs->GetParameterValue(&vy1,nodes[0],VyEnum);
+	tria2->inputs->GetParameterValue(&vy2,nodes[1],VyEnum);
+
+	/*Grid 1 faces grid2, compute penetration of 2 into 1 (V2-V1).N (with N normal vector, and V velocity vector: */
+	penetration=(vx2-vx1)*normal[0]+(vy2-vy1)*normal[1];
+
+	/*Now, we return penetration only if we are active!: */
+	if(this->active==0)penetration=-1;
+
+	/*If we are zigzag locked, same thing: */
+	if(this->counter>this->penalty_lock)penetration=-1;
+	
+	/*assign output pointer: */
+	*ppenetration=penetration;
+
+}
+/*}}}1*/
+/*FUNCTION Riftfront::OutputProperties {{{1*/
+void  Riftfront::OutputProperties(Vec riftproperties){
+
+	int row_id=0;
+	double value;
+
+	/*recover id of penalty: */
+	row_id=this->Id()-1; //c indexing, ids were matlab indexed
+	value=(double)this->fraction;
+
+	/*Plug id and fraction  into riftproperties matrix: */
+	VecSetValues(riftproperties,1,&row_id,&value,INSERT_VALUES);
+}
+/*}}}1*/
+/*FUNCTION Riftfront::PenaltyCreateKMatrix {{{1*/
+void  Riftfront::PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type){
+
+	int         i;
+	int         j;
+	const int   numgrids            = MAX_RIFTFRONT_GRIDS;
+	int         dofs[1]             = {0};
+	double      Ke_gg[4][4];
+	const int   numdof              = 2 *numgrids;
+	int         doflist[numdof];
+	int         numberofdofspernode;
+	double      thickness;
+	double      h[2];
+	double      penalty_offset;
+	double      friction;
+
+	/*Objects: */
+	Element   **elements            = NULL;
+	Node      **nodes               = NULL;
+	Tria       *tria1               = NULL;
+	Tria       *tria2               = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	
+	/* Get node coordinates and dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Set Ke_gg to 0: */
+	for(i=0;i<numdof;i++) for(j=0;j<numdof;j++) Ke_gg[i][j]=0.0;
+
+	/*Get some parameters: */
+	this->parameters->FindParam(&penalty_offset,PenaltyOffsetEnum);
+	this->inputs->GetParameterValue(&friction,FrictionEnum);
+
+	if(this->active){
+	
+		/*There is contact, we need to constrain the normal velocities (zero penetration), and the 
+		 *contact slip friction. */
+		  
+		/*Recover thickness: */
+		tria1->inputs->GetParameterValue(&h[0],nodes[0],ThicknessEnum);
+		tria2->inputs->GetParameterValue(&h[1],nodes[1],ThicknessEnum);
+
+		if (h[0]!=h[1])ISSMERROR(" different thicknesses not supported for rift fronts");
+		thickness=h[0];
+
+		/*From Peter Wriggers book (Computational Contact Mechanics, p191): */
+		//First line:
+		Ke_gg[0][0]+=pow(normal[0],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[0][1]+=normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[0][2]+=-pow(normal[0],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[0][3]+=-normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		//Second line:
+		Ke_gg[1][0]+=normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[1][1]+=pow(normal[1],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[1][2]+=-normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[1][3]+=-pow(normal[1],2)*kmax*pow(10,penalty_offset);
+		//Third line:
+		Ke_gg[2][0]+=-pow(normal[0],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[2][1]+=-normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[2][2]+=pow(normal[0],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[2][3]+=normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		//Fourth line:
+		Ke_gg[3][0]+=-normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[3][1]+=-pow(normal[1],2)*kmax*pow(10,penalty_offset);
+		Ke_gg[3][2]+=normal[0]*normal[1]*kmax*pow(10,penalty_offset);
+		Ke_gg[3][3]+=pow(normal[1],2)*kmax*pow(10,penalty_offset);
+
+		/*Now take care of the friction: of type sigma=frictiontangent_velocity2-tangent_velocity1)*/
+		
+		//First line:
+		Ke_gg[0][0]+=pow(normal[1],2)*thickness*length*friction;
+		Ke_gg[0][1]+=-normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[0][2]+=-pow(normal[1],2)*thickness*length*friction;
+		Ke_gg[0][3]+=normal[0]*normal[1]*thickness*length*friction;
+		//Second line:
+		Ke_gg[1][0]+=-normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[1][1]+=pow(normal[0],2)*thickness*length*friction;
+		Ke_gg[1][2]+=normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[1][3]+=-pow(normal[0],2)*thickness*length*friction;
+		//Third line:
+		Ke_gg[2][0]+=-pow(normal[1],2)*thickness*length*friction;
+		Ke_gg[2][1]+=normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[2][2]+=pow(normal[1],2)*thickness*length*friction;
+		Ke_gg[2][3]+=-normal[0]*normal[1]*thickness*length*friction;
+		//Fourth line:
+		Ke_gg[3][0]+=normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[3][1]+=-pow(normal[0],2)*thickness*length*friction;
+		Ke_gg[3][2]+=-normal[0]*normal[1]*thickness*length*friction;
+		Ke_gg[3][3]+=pow(normal[0],2)*thickness*length*friction;
+
+		/*Add Ke_gg to global matrix Kgg: */
+		MatSetValues(Kgg,numdof,doflist,numdof,doflist,(const double*)Ke_gg,ADD_VALUES);
+	}
+	else{
+		/*the grids on both sides of the rift do not penetrate.  PenaltyCreatePVector will 
+		 *take care of adding point loads to simulate pressure on the rift flanks. But as far as stiffness, 
+		 there is none (0 stiffness implies decoupling of the flank rifts, which is exactly what we want): */
+	}
+
+}
+/*}}}1*/
+/*FUNCTION Riftfront::PenaltyCreatePVector {{{1*/
+void  Riftfront::PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type){
+
+	int         i                     ,j;
+	const int   numgrids            = MAX_RIFTFRONT_GRIDS;
+	double      pe_g[4]={0.0};
+	const int   numdof              = 2 *numgrids;
+	int         doflist[numdof];
+	int         numberofdofspernode;
+
+	double      rho_ice;
+	double      rho_water;
+	double      gravity;
+	double      thickness;
+	double      h[2];
+	double      bed;
+	double      b[2];
+	double      pressure;
+	double      pressure_litho;
+	double      pressure_air;
+	double      pressure_melange;
+	double      pressure_water;
+	double      fill;
+	bool        shelf;
+
+
+	/*Objects: */
+	Element   **elements            = NULL;
+	Node      **nodes               = NULL;
+	Tria       *tria1               = NULL;
+	Tria       *tria2               = NULL;
+	Matpar     *matpar              = NULL;
+
+	
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+	matpar=(Matpar*)hmatpar.delivers();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	/* Get node coordinates and dof list: */
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/*Get some inputs: */
+	this->inputs->GetParameterValue(&fill,FillEnum);
+	this->inputs->GetParameterValue(&shelf,SegmentOnIceShelfEnum);
+
+	if(!this->active){
+		/*Ok, this rift is opening. We should put loads on both sides of the rift flanks. Because we are dealing with contact mechanics, 
+		 * and we want to avoid zigzagging of the loads, we want lump the loads onto grids, not onto surfaces between grids.:*/
+	
+		/*Ok, to compute the pressure, we are going to need material properties, thickness and bed for the two grids. We assume those properties to 
+		 * be the same across the rift.: */
+
+		rho_ice=matpar->GetRhoIce();
+		rho_water=matpar->GetRhoWater();
+		gravity=matpar->GetG();
+
+		/*get thickness: */
+		tria1->inputs->GetParameterValue(&h[0],nodes[0],ThicknessEnum);
+		tria2->inputs->GetParameterValue(&h[1],nodes[1],ThicknessEnum);
+
+		if (h[0]!=h[1])ISSMERROR(" different thicknesses not supported for rift fronts");
+		thickness=h[0];
+
+		tria1->inputs->GetParameterValue(&b[0],nodes[0],BedEnum);
+		tria2->inputs->GetParameterValue(&b[1],nodes[1],BedEnum);
+
+		if (b[0]!=b[1])ISSMERROR(" different beds not supported for rift fronts");
+		bed=b[0];
+
+		/*Ok, now compute the pressure (in norm) that is being applied to the flanks, depending on the type of fill: */
+		if(fill==WaterEnum){
+			if(shelf){
+				/*We are on an ice shelf, hydrostatic equilibrium is used to determine the pressure for water fill: */
+				pressure=rho_ice*gravity*pow(thickness,(double)2)/(double)2  - rho_water*gravity*pow(bed,(double)2)/(double)2; 
+			}
+			else{
+				//We are on an icesheet, we assume the water column fills the entire front: */
+				pressure=rho_ice*gravity*pow(thickness,(double)2)/(double)2  - rho_water*gravity*pow(thickness,(double)2)/(double)2; 
+			}
+		}
+		else if(fill==AirEnum){
+			pressure=rho_ice*gravity*pow(thickness,(double)2)/(double)2;   //icefront on an ice sheet, pressure imbalance ice vs air.
+		}
+		else if(fill==IceEnum){ //icefront finding itself against another icefront (pressure imbalance is fully compensated, ice vs ice)
+			pressure=0;
+		}
+		else if(fill==MelangeEnum){ //icefront finding itself against another icefront (pressure imbalance is fully compensated, ice vs ice)
+			
+			if(!shelf) ISSMERROR("%s%i%s","fill type ",fill," not supported on ice sheets yet.");
+
+			pressure_litho=rho_ice*gravity*pow(thickness,(double)2)/(double)2;
+			pressure_air=0;
+			pressure_melange=rho_ice*gravity*pow(fraction*thickness,(double)2)/(double)2;
+			pressure_water=1.0/2.0*rho_water*gravity*  ( pow(bed,2.0)-pow(rho_ice/rho_water*fraction*thickness,2.0) );
+
+			pressure=pressure_litho-pressure_air-pressure_melange-pressure_water;
+		}
+		else{
+			ISSMERROR("%s%i%s","fill type ",fill," not supported yet.");
+		}
+
+		/*Ok, add contribution to first grid, along the normal i==0: */
+		for (j=0;j<2;j++){
+			pe_g[j]+=pressure*normal[j]*length;
+		}
+	
+		/*Add contribution to second grid, along the opposite normal: i==1 */
+		for (j=0;j<2;j++){
+			pe_g[2+j]+= -pressure*normal[j]*length;
+		}	
+		/*Add pe_g to global vector pg; */
+		VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
+
+	}
+	else{
+		/*The penalty is active. No loads implied here.*/
+	}
+}
+/*}}}1*/
+/*FUNCTION Riftfront::Penetration {{{1*/
+int   Riftfront::Penetration(double* ppenetration,  int analysis_type){
+
+	double    vx1;
+	double    vy1;
+	double    vx2;
+	double    vy2;
+
+	double    penetration;
+	int       found;
+
+	/*Objects: */
+	Element **elements    = NULL;
+	Node    **nodes       = NULL;
+	Tria     *tria1       = NULL;
+	Tria     *tria2       = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	/*First recover velocity: */
+	tria1->inputs->GetParameterValue(&vx1,nodes[0],VxEnum);
+	tria2->inputs->GetParameterValue(&vx2,nodes[1],VxEnum);
+	tria1->inputs->GetParameterValue(&vy1,nodes[0],VyEnum);
+	tria2->inputs->GetParameterValue(&vy2,nodes[1],VyEnum);
+
+	/*Node 1 faces node 2, compute penetration of 2 into 1 (V2-V1).N (with N normal vector, and V velocity vector: */
+	penetration=(vx2-vx1)*normal[0]+(vy2-vy1)*normal[1];
+
+	/*Now, we return penetration only if we are active!: */
+	if(this->active==0)penetration=0;
+	
+	/*assign output pointer: */
+	*ppenetration=penetration;
+
+}
+/*}}}1*/
+/*FUNCTION Riftfront::PotentialUnstableConstraint {{{1*/
+int   Riftfront::PotentialUnstableConstraint(int* punstable,  int analysis_type){
+
+
+	const int   numgrids        = 2;
+	double      max_penetration;
+	double      penetration;
+	int         activate;
+	int         unstable;
+	int         found;
+	double      vx1;
+	double      vy1;
+	double      vx2;
+	double      vy2;
+
+
+	/*Objects: */
+	Element   **elements        = NULL;
+	Node      **nodes           = NULL;
+	Tria       *tria1           = NULL;
+	Tria       *tria2           = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	/*First recover velocity: */
+	tria1->inputs->GetParameterValue(&vx1,nodes[0],VxEnum);
+	tria2->inputs->GetParameterValue(&vx2,nodes[1],VxEnum);
+	tria1->inputs->GetParameterValue(&vy1,nodes[0],VyEnum);
+	tria2->inputs->GetParameterValue(&vy2,nodes[1],VyEnum);
+
+	/*Node 1 faces node 2, compute penetration of 2 into 1 (V2-V1).N (with N normal vector, and V velocity vector: */
+	penetration=(vx2-vx1)*normal[0]+(vy2-vy1)*normal[1];
+
+	/*Ok, we are looking for positive penetration in an active constraint: */
+	if(this->active){
+		if (penetration>=0){
+			unstable=1;
+		}
+		else{
+			unstable=0;
+		}
+	}
+	else{
+		unstable=0;
+	}
+
+	/*assign output pointer: */
+	*punstable=unstable;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::PreConstrain {{{1*/
+int   Riftfront::PreConstrain(int* punstable,  int analysis_type){
+
+	const int   numgrids    = 2;
+	double      penetration;
+	int         unstable;
+	int         found;
+	double      vx1;
+	double      vy1;
+	double      vx2;
+	double      vy2;
+
+
+	/*Objects: */
+	Element   **elements    = NULL;
+	Node      **nodes       = NULL;
+	Tria       *tria1       = NULL;
+	Tria       *tria2       = NULL;
+
+	/*Recover hook objects: */
+	elements=(Element**)helements.deliverp();
+	nodes=(Node**)hnodes.deliverp();
+
+	/*enum of element? */
+	if(elements[0]->Enum()!=TriaEnum)ISSMERROR(" only Tria element allowed for Riftfront load!");
+
+	/*recover elements on both side of rift: */
+	tria1=(Tria*)elements[0];
+	tria2=(Tria*)elements[1];
+
+	/*First recover velocity: */
+	tria1->inputs->GetParameterValue(&vx1,nodes[0],VxEnum);
+	tria2->inputs->GetParameterValue(&vx2,nodes[1],VxEnum);
+	tria1->inputs->GetParameterValue(&vy1,nodes[0],VyEnum);
+	tria2->inputs->GetParameterValue(&vy2,nodes[1],VyEnum);
+
+	/*Node 1 faces node 2, compute penetration of 2 into 1 (V2-V1).N (with N normal vector, and V velocity vector: */
+	penetration=(vx2-vx1)*normal[0]+(vy2-vy1)*normal[1];
+
+	/*Ok, we are preconstraining here. Ie, anything that penetrates is constrained until stability of the entire set 
+	 * of constraints is reached.: */
+	if(penetration<0){
+		if (!this->active){
+			/*This is the first time penetration happens: */
+			this->active=1;
+			unstable=1;
+		}
+		else{
+			/*This constraint was already active: */
+			this->active=1;
+			unstable=0;
+		}
+	}
+	else{
+		/*No penetration happening. : */
+		if (!this->active){
+			/*This penalty was not active, and no penetration happening. Do nonthing: */
+			this->active=0;
+			unstable=0; 
+		}
+		else{
+			/*Ok, this penalty wants to get released. But not now, this is preconstraint, not constraint: */
+			this->active=1;
+			unstable=0;
+		}
+	}
+
+	/*assign output pointer: */
+	*punstable=unstable;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::PreStable {{{1*/
+bool  Riftfront::PreStable(){
+	return prestable;
+}
+/*}}}1*/
+/*FUNCTION Riftfront::SetPreStable {{{1*/
+void Riftfront::SetPreStable(){
+	prestable=1;
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Loads/Riftfront.h
===================================================================
--- /issm/trunk/src/c/objects/Loads/Riftfront.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Loads/Riftfront.h	(revision 3683)
@@ -0,0 +1,84 @@
+/*!\file Riftfront.h
+ * \brief: header file for riftfront object
+ */
+
+#ifndef _RIFTFRONT_H_
+#define _RIFTFRONT_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Load.h"
+class Hook;
+class Parameters;
+class Inputs;
+class IoModel;
+
+#define MAX_RIFTFRONT_GRIDS 2 //max number of grids on a rift flank, only 2 because 2d for now.
+#define RIFTFRONTSTRING 20 //max string length
+/*}}}*/
+
+class Riftfront: public Load {
+
+	public:
+		int		id;
+
+		Hook hnodes; //2 nodes
+		Hook helements; //2 elements
+		Hook hmatpar;
+		
+		/*computational: */
+		int      penalty_lock;
+		bool     active;
+		bool     frozen;
+		int      counter;
+		bool     prestable;
+		bool     material_converged;
+		double   normal[2];
+		double   length;
+		double   fraction;
+		
+		Parameters* parameters; //pointer to solution parameters
+		Inputs*  inputs;
+
+
+		/*constructors,destructors: {{{1*/
+		Riftfront();
+		Riftfront(int riftfront_id,int* riftfront_node_ids, int riftfront_matpar_id);
+		Riftfront(int riftfront_id,Hook* riftfront_hnodes, Hook* riftfront_hmatpar, Parameters* parameters, Inputs* riftfront_inputs);
+		Riftfront(int riftfront_id,int i, IoModel* iomodel);
+		~Riftfront();
+		/*}}}*/
+		/*object management: {{{1*/
+		void  Configure(DataSet* elements,DataSet* loads,DataSet* nodes,DataSet* vertices,DataSet* materials,Parameters* parameters);
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id(); 
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+
+		/*}}}*/
+		/*numerics: {{{1*/
+		void  GetDofList(int* doflist,int* pnumberofdofs);
+		void  CreateKMatrix(Mat Kgg,int analysis_type,int sub_analysis_type);
+		void  CreatePVector(Vec pg,  int analysis_type,int sub_analysis_type);
+		void  PenaltyCreateKMatrix(Mat Kgg,double kmax,int analysis_type,int sub_analysis_type);
+		void  PenaltyCreatePVector(Vec pg,double kmax,int analysis_type,int sub_analysis_type);
+		bool  PreStable();
+		void  SetPreStable();
+		int   PreConstrain(int* punstable,  int analysis_type);
+		int   Constrain(int* punstable,  int analysis_type);
+		void  FreezeConstraints( int analysis_type);
+		bool  IsFrozen(void);
+		int   Penetration(double* ppenetration,  int analysis_type);
+		int   MaxPenetration(double* ppenetration,  int analysis_type);
+		int   PotentialUnstableConstraint(int* punstable,  int analysis_type);
+		int   IsMaterialStable( int analysis_type);
+		void  OutputProperties(Vec riftproperties);
+		/*}}}*/
+};
+
+#endif  /* _RIFTFRONT_H_ */
Index: /issm/trunk/src/c/objects/Materials/Material.cpp
===================================================================
--- /issm/trunk/src/c/objects/Materials/Material.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Material.cpp	(revision 3683)
@@ -0,0 +1,15 @@
+/*!\file: Material.cpp 
+ * \brief: implementation of the Enum routine, which is the only non-virtual routine from 
+ * the Object derived class Material.
+ */ 
+
+
+#include "../objects.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+
+int Material::Enum(void){
+
+	return MaterialEnum;
+}
+		
+
Index: /issm/trunk/src/c/objects/Materials/Material.h
===================================================================
--- /issm/trunk/src/c/objects/Materials/Material.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Material.h	(revision 3683)
@@ -0,0 +1,31 @@
+/*!\file:  Material.h
+ * \brief abstract class for Material object
+ */ 
+
+
+#ifndef _MATERIAL_H_
+#define _MATERIAL_H_
+
+/*Headers:*/
+/*{{{1*/
+class Object;
+#include "../Object.h"
+#include "../../toolkits/toolkits.h"
+/*}}}*/
+
+class Material: public Object{
+
+	public: 
+		virtual       ~Material(){};
+		virtual void  Echo()=0;
+		virtual void  DeepEcho()=0;
+		virtual int   Id()=0;
+		virtual int   MyRank()=0;
+		virtual void  Marshall(char** pmarshalled_dataset)=0;
+		virtual int   MarshallSize()=0;
+		virtual void  Demarshall(char** pmarshalled_dataset)=0;
+		virtual void  UpdateFromInputs(void* inputs)=0;
+		int           Enum();
+		
+};
+#endif
Index: /issm/trunk/src/c/objects/Materials/Matice.cpp
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Matice.cpp	(revision 3683)
@@ -0,0 +1,440 @@
+/*!\file Matice.c
+ * \brief: implementation of the Matice object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/macros.h"
+#include "../../include/typedefs.h"
+		
+/*Object constructors and destructor*/
+/*FUNCTION Matice::Matice(){{{1*/
+Matice::Matice(){
+	return;
+}
+/*}}}*/
+/*FUNCTION Matice::Matice(int in_mid,double in_B,double in_n){{{1*/
+Matice::Matice(int in_mid,double in_B,double in_n){
+	this->Init(in_mid,in_B,in_n);
+}
+/*}}}*/
+/*FUNCTION Matice::Init {{{1*/
+void Matice::Init(int in_mid,double in_B,double in_n){
+	this->mid=in_mid;
+	this->B=in_B;
+	this->n=in_n;
+}
+/*}}}*/
+/*FUNCTION Matice::Matice(int id, int i, IoModel* iomodel, int num_vertices){{{1*/
+Matice::Matice(int matice_mid,int i, IoModel* iomodel, int num_vertices){
+
+	int j;
+	
+	/*needed for Init routine:*/
+	double matice_B;
+	double matice_n;
+
+	/*intermediary: */
+	double B_avg;
+ 
+	/*Compute B on the element if provided*/
+	if (num_vertices==3 || num_vertices==6){
+		if (iomodel->rheology_B){
+			B_avg=0;
+			for(j=0;j<num_vertices;j++){
+				B_avg+=*(iomodel->rheology_B+((int)*(iomodel->elements+num_vertices*i+j)-1));
+			}
+			B_avg=B_avg/num_vertices;
+		}
+	}
+	else if (num_vertices==1 || num_vertices==2){
+		if (iomodel->rheology_B){
+			B_avg=*(iomodel->rheology_B+i);
+		}
+	}
+	else ISSMERROR("num_vertices = %i not supported yet",num_vertices);
+	
+	if (iomodel->rheology_B) matice_B=B_avg;
+	else            matice_B=UNDEF;
+	if (iomodel->rheology_n){
+		if (num_vertices==3 || num_vertices==6){
+			matice_n=(double)*(iomodel->rheology_n+i);
+		}
+		else if (num_vertices==1 || num_vertices==2){
+			/*n is on the elements for now, so just take the first one*/
+			matice_n=(double)*(iomodel->rheology_n);
+		}
+		else ISSMERROR("num_vertices = %i not supported yet",num_vertices);
+	}
+	else            matice_n=UNDEF;
+
+	this->Init(matice_mid,matice_B,matice_n);
+}
+/*}}}*/
+/*FUNCTION Matice::~Matice(){{{1*/
+Matice::~Matice(){
+	return;
+}
+/*}}}*/
+
+/*Object marshall*/
+/*FUNCTION Matice::Marshall {{{1*/
+void  Matice::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Matice: */
+	enum_type=MaticeEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Matice data: */
+	memcpy(marshalled_dataset,&mid,sizeof(mid));marshalled_dataset+=sizeof(mid);
+	memcpy(marshalled_dataset,&B,sizeof(B));marshalled_dataset+=sizeof(B);
+	memcpy(marshalled_dataset,&n,sizeof(n));marshalled_dataset+=sizeof(n);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION Matice::MarshallSize{{{1*/
+int   Matice::MarshallSize(){
+
+	return sizeof(mid)+sizeof(B)+sizeof(n)+sizeof(int); //sizeof(int) for enum type
+}
+/*}}}*/
+/*FUNCTION Matice::Demarshall {{{1*/
+void  Matice::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&mid,marshalled_dataset,sizeof(mid));marshalled_dataset+=sizeof(mid);
+	memcpy(&B,marshalled_dataset,sizeof(B));marshalled_dataset+=sizeof(B);
+	memcpy(&n,marshalled_dataset,sizeof(n));marshalled_dataset+=sizeof(n);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+
+/*Object functions*/
+/*FUNCTION Matice::copy {{{1*/
+Object* Matice::copy() {
+	return new Matice(*this); 
+}
+/*}}}*/
+/*FUNCTION Matice::DeepEcho {{{1*/
+void Matice::DeepEcho(void){
+
+	printf("Matice:\n");
+	printf("   mid: %i\n",mid);
+	printf("   B: %g\n",B);
+	printf("   n: %g\n",n);
+	return;
+}		
+/*}}}*/
+/*FUNCTION Matice::DistributeNumDofs {{{1*/
+void  Matice::DistributeNumDofs(int* numdofspernode,int analysis_type){return;}
+/*}}}*/
+/*FUNCTION Matice::Echo {{{1*/
+void Matice::Echo(void){
+
+	printf("Matice:\n");
+	printf("   mid: %i\n",mid);
+	printf("   B: %g\n",B);
+	printf("   n: %g\n",n);
+	return;
+}
+/*}}}*/
+/*FUNCTION Matice::Enum {{{1*/
+int Matice::Enum(void){
+
+	return MaticeEnum;
+
+}
+/*}}}*/
+/*FUNCTION Matice::GetB {{{1*/
+double Matice::GetB(){
+	return B;
+}
+/*}}}*/
+/*FUNCTION Matice::Id {{{1*/
+int    Matice::Id(void){ return mid; }
+/*}}}*/
+/*FUNCTION Matice::GetN {{{1*/
+double Matice::GetN(){
+	return n;
+}
+/*}}}*/
+/*FUNCTION Matice::GetViscosity2d {{{1*/
+void  Matice::GetViscosity2d(double* pviscosity, double* epsilon){
+
+
+	/*From a string tensor and a material object, return viscosity, using Glen's flow law.
+	                                  2*B
+	  viscosity= -------------------------------------------------------------------
+	      2[ exx^2+eyy^2+exx*eyy+exy^2+exz^2+eyz^2 ]^[(n-1)/2n]
+	 
+	      where viscosity is the viscotiy, B the flow law parameter , (u,v) the velocity 
+	      vector, and n the flow law exponent.
+	 
+	  If epsilon is NULL, it means this is the first time SystemMatrices is being run, and we 
+	  return 10^14, initial viscosity.
+*/
+
+
+
+	/*output: */
+	double viscosity;
+
+	/*input strain rate: */
+	double exx,eyy,exy;
+
+	/*Intermediary value A and exponent e: */
+	double A,e;
+
+	if (n==1){
+		/*Viscous behaviour! viscosity=B: */
+		viscosity=B;
+	}
+	else{
+		if((epsilon[0]==0) && (epsilon[1]==0) && (epsilon[2]==0)){
+			viscosity=pow((double)10,(double)14);
+		}
+		else{
+			/*Retrive strain rate components: */
+			exx=*(epsilon+0);
+			eyy=*(epsilon+1);
+			exy=*(epsilon+2);
+
+			/*Build viscosity: viscosity=2*B/(2*A^e) */
+			A=pow(exx,2)+pow(eyy,2)+pow(exy,2)+exx*eyy;
+			if(A==0){
+				/*Maxiviscositym viscosity for 0 shear areas: */
+				viscosity=4.5*pow((double)10,(double)17);
+			}
+			else{
+				e=(n-1)/2/n;
+				viscosity=2*B/(2*pow(A,e));
+			}
+		}
+	}
+
+	/*Return: */
+	*pviscosity=viscosity;
+}
+/*}}}*/
+/*FUNCTION Matice::GetViscosity3d {{{1*/
+void  Matice::GetViscosity3d(double* pviscosity3d, double* epsilon){
+
+	/*Return viscosity accounting for steady state power law creep [Thomas and MacAyeal, 1982]: 
+	 *
+	 *                                 2*B
+	 * viscosity3d= -------------------------------------------------------------------
+	 *     2[ exx^2+eyy^2+exx*eyy+exy^2+exz^2+eyz^2 ]^[(n-1)/2n]
+	 *
+	 *     where mu is the viscotiy, B the flow law parameter , (u,v) the velocity 
+	 *     vector, and n the flow law exponent.
+	 *
+	 * If epsilon is NULL, it means this is the first time Emg is being run, and we 
+	 * return g, initial viscosity.
+	 */
+	
+	/*output: */
+	double viscosity3d;
+
+	/*input strain rate: */
+	double exx,eyy,exy,exz,eyz;
+
+	/*Intermediary value A and exponent e: */
+	double A,e;
+
+	if (n==1){
+		/*Viscous behaviour! viscosity3d=B: */
+		viscosity3d=B;
+	}
+	else{
+		if((epsilon[0]==0) && (epsilon[1]==0) && (epsilon[2]==0) && 
+				(epsilon[3]==0) && (epsilon[4]==0)){
+			viscosity3d=pow((double)10,(double)14);
+		}
+		else{
+
+			/*Retrive strain rate components: */
+			exx=*(epsilon+0);
+			eyy=*(epsilon+1);
+			exy=*(epsilon+2);
+			exz=*(epsilon+3);
+			eyz=*(epsilon+4);
+
+			/*Build viscosity: viscosity3d=2*B/(2*A^e) */
+			A=pow(exx,2)+pow(eyy,2)+pow(exy,2)+pow(exz,2)+pow(eyz,2)+exx*eyy;
+			if(A==0){
+				/*Maxiviscosity3dm viscosity for 0 shear areas: */
+				viscosity3d=4.5*pow((double)10,(double)17);
+			}
+			else{
+				e=(n-1)/2/n;
+			
+				viscosity3d=2*B/(2*pow(A,e));
+			}
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pviscosity3d=viscosity3d;
+}
+/*}}}*/
+/*FUNCTION Matice::GetViscosity3dStokes {{{1*/
+void  Matice::GetViscosity3dStokes(double* pviscosity3d, double* epsilon){
+
+	/*Return viscosity accounting for steady state power law creep [Thomas and MacAyeal, 1982]: 
+	 *
+	 *                                 2*B
+	 * viscosity3d= -------------------------------------------------------------------
+	 *     2[ exx^2+eyy^2+exx*eyy+exy^2+exz^2+eyz^2 ]^[(n-1)/2n]
+	 *
+	 *     where mu is the viscotiy, B the flow law parameter , (u,v) the velocity 
+	 *     vector, and n the flow law exponent.
+	 *
+	 * If epsilon is NULL, it means this is the first time Emg is being run, and we 
+	 * return g, initial viscosity.
+	 */
+	
+	/*output: */
+	double viscosity3d;
+
+	/*input strain rate: */
+	double exx,eyy,exy,exz,eyz,ezz;
+
+	/*Intermediary value A and exponent e: */
+	double A,e;
+	double eps0;
+
+	eps0=pow((double)10,(double)-27);
+	
+	if (n==1){
+		/*Viscous behaviour! viscosity3d=B: */
+		viscosity3d=B;
+	}
+	else{
+		if((epsilon[0]==0) && (epsilon[1]==0) && (epsilon[2]==0) && 
+				(epsilon[3]==0) && (epsilon[4]==0) && (epsilon[5]==0)){
+			viscosity3d=pow((double)10,(double)14);
+		}
+		else{
+
+			/*Retrive strain rate components: */
+			exx=*(epsilon+0);
+			eyy=*(epsilon+1);
+			ezz=*(epsilon+2); //not used
+			exy=*(epsilon+3);
+			exz=*(epsilon+4);
+			eyz=*(epsilon+5);
+
+			/*Build viscosity: viscosity3d=2*B/(2*A^e) */
+			A=pow(exx,2)+pow(eyy,2)+pow(exy,2)+pow(exz,2)+pow(eyz,2)+exx*eyy+pow(eps0,2);
+			if(A==0){
+				/*Maxiviscosity3dm viscosity for 0 shear areas: */
+				viscosity3d=4.5*pow((double)10,(double)17);
+			}
+			else{
+				e=(n-1)/2/n;
+				viscosity3d=2*B/(2*pow(A,e));
+			}
+		}
+	}
+
+	/*Assign output pointers:*/
+	*pviscosity3d=viscosity3d;
+}
+/*}}}*/
+/*FUNCTION Matice::GetViscosityComplement {{{1*/
+void  Matice::GetViscosityComplement(double* pviscosity_complement, double* epsilon){
+
+	/*Return viscosity accounting for steady state power law creep [Thomas and MacAyeal, 1982]: 
+	 *
+	 *                                  2* (1-n)/2n
+	 * mu2= -------------------------------------------------------------------
+	 *     2[ (du/dx)^2+(dv/dy)^2+1/4*(du/dy+dv/dx)^2+du/dx*dv/dy ]^[(3n-1)/2n]
+	 *
+	 *     where mu2 is the second viscosity, (u,v) the velocity 
+	 *     vector, and n the flow law exponent.
+	 *
+	 * If epsilon is NULL, it means this is the first time Gradjb is being run, and we 
+	 * return mu20, initial viscosity.
+	 */
+	
+	/*output: */
+	double viscosity_complement;
+
+	/*input strain rate: */
+	double exx,eyy,exy;
+
+	/*Intermediary value A and exponent e: */
+	double A,e;
+
+	if(epsilon){
+		exx=*(epsilon+0);
+		eyy=*(epsilon+1);
+		exy=*(epsilon+2);
+
+		/*Build viscosity: mu2=B/(2*A^e) */
+		A=pow(exx,2)+pow(eyy,2)+pow(exy,2)+exx*eyy;
+		if(A==0){
+			/*Maximum viscosity_complement for 0 shear areas: */
+			viscosity_complement=4.5*pow((double)10,(double)17);
+		}
+		else{
+			e=(n-1)/2/n;
+		
+			viscosity_complement=1/(2*pow(A,e));
+		}
+	}
+	else{
+		viscosity_complement=4.5*pow((double)10,(double)17);
+	}
+		
+	/*Return: */
+	*pviscosity_complement=viscosity_complement;
+}
+/*}}}*/
+/*FUNCTION Matice::MyRank {{{1*/
+int    Matice::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Matice::SetB {{{1*/
+void  Matice::SetB(double B_param){
+	B=B_param;
+}
+/*}}}*/
+/*FUNCTION Matice::UpdateFromInputs {{{1*/
+void  Matice::UpdateFromInputs(void* inputs){
+	
+	//ISSMERROR(" not supported yet!");
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Materials/Matice.h
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matice.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Matice.h	(revision 3683)
@@ -0,0 +1,50 @@
+/*!\file Matice.h
+ * \brief: header file for matice object
+ */
+
+#ifndef MATICE_H_
+#define MATICE_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Material.h"
+class IoModel;
+/*}}}*/
+
+class Matice: public Material{
+
+	private: 
+		int	   mid;
+		double B;
+		double n;
+
+	public:
+
+		Matice();
+		Matice(int mid,double B,double n);
+		Matice(int mid,int i, IoModel* iomodel, int num_vertices);
+		void Init(int mid,double B,double n);
+		~Matice();
+
+		void  Echo();
+		void  DeepEcho();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   Id(); 
+		int   MyRank();
+		void  DistributeNumDofs(int* numdofspernode,int analysis_type);
+		void  UpdateFromInputs(void* inputs);
+		void  SetB(double B_param);
+		void  GetViscosity2d(double* pviscosity, double* pepsilon);
+		void  GetViscosity3d(double* pviscosity3d, double* pepsilon);
+		void  GetViscosity3dStokes(double* pviscosity3d, double* epsilon);
+		void  GetViscosityComplement(double* pviscosity_complement, double* pepsilon);
+		Object* copy();
+		double GetB();
+		double GetN();
+
+};
+
+#endif  /* _MATICE_H_ */
Index: /issm/trunk/src/c/objects/Materials/Matpar.cpp
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matpar.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Matpar.cpp	(revision 3683)
@@ -0,0 +1,283 @@
+/*!\file Matpar.c
+ * \brief: implementation of the Matpar object
+ */
+
+
+#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 "../objects.h"
+#include "../../shared/shared.h"
+#include "../../include/macros.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+
+		
+/*Object constructors and destructor*/
+/*FUNCTION Matpar::Matpar() {{{1*/
+Matpar::Matpar(){
+	return;
+}
+/*}}}1*/
+/*FUNCTION Matpar::Matpar(int matpar_mid, double matpar_rho_ice, double matpar_rho_water, double matpar_heatcapacity, ...){{{1*/
+Matpar::Matpar(int	matpar_mid, double	matpar_rho_ice, double	matpar_rho_water, double  matpar_heatcapacity, double  matpar_thermalconductivity, double  matpar_latentheat, double  matpar_beta, double  matpar_meltingpoint, double  matpar_mixed_layer_capacity, double  matpar_thermal_exchange_velocity, double  matpar_g){
+
+	this->Init(matpar_mid, matpar_rho_ice, matpar_rho_water, matpar_heatcapacity, matpar_thermalconductivity, matpar_latentheat, matpar_beta, matpar_meltingpoint, matpar_mixed_layer_capacity, matpar_thermal_exchange_velocity, matpar_g);
+
+}
+/*}}}1*/
+/*FUNCTION Matpar::Matpar(int matpar_mid,IoModel* iomodel){{{1*/
+Matpar::Matpar(int matpar_mid, IoModel* iomodel){
+
+	double  matpar_rho_ice;
+	double  matpar_rho_water;
+	double  matpar_heatcapacity;
+	double  matpar_thermalconductivity;
+	double  matpar_latentheat;
+	double  matpar_beta;
+	double  matpar_meltingpoint;
+	double  matpar_mixed_layer_capacity;
+	double  matpar_thermal_exchange_velocity;
+	double  matpar_g;
+
+	matpar_g=iomodel->g; 
+	matpar_rho_ice=iomodel->rho_ice; 
+	matpar_rho_water=iomodel->rho_water; 
+	matpar_thermalconductivity=iomodel->thermalconductivity; 
+	matpar_heatcapacity=iomodel->heatcapacity; 
+	matpar_latentheat=iomodel->latentheat; 
+	matpar_beta=iomodel->beta; 
+	matpar_meltingpoint=iomodel->meltingpoint; 
+	matpar_mixed_layer_capacity=iomodel->mixed_layer_capacity; 
+	matpar_thermal_exchange_velocity=iomodel->thermal_exchange_velocity; 
+
+	this->Init(matpar_mid, matpar_rho_ice, matpar_rho_water, matpar_heatcapacity, matpar_thermalconductivity, matpar_latentheat, matpar_beta, matpar_meltingpoint, matpar_mixed_layer_capacity, matpar_thermal_exchange_velocity, matpar_g);
+
+}
+/*}}}1*/
+/*FUNCTION Matpar::Init {{{1*/
+void Matpar::Init(int	matpar_mid, double	matpar_rho_ice, double	matpar_rho_water, double  matpar_heatcapacity, double  matpar_thermalconductivity, double  matpar_latentheat, double  matpar_beta, double  matpar_meltingpoint, double  matpar_mixed_layer_capacity, double  matpar_thermal_exchange_velocity, double  matpar_g){
+
+	this->mid=matpar_mid; 
+	this->rho_ice=matpar_rho_ice; 
+	this->rho_water=matpar_rho_water; 
+	this->heatcapacity=matpar_heatcapacity; 
+	this->thermalconductivity=matpar_thermalconductivity; 
+	this->latentheat=matpar_latentheat; 
+	this->beta=matpar_beta; 
+	this->meltingpoint=matpar_meltingpoint; 
+	this->mixed_layer_capacity=matpar_mixed_layer_capacity; 
+	this->thermal_exchange_velocity=matpar_thermal_exchange_velocity; 
+	this->g=matpar_g; 
+
+	return;
+}
+/*}}}1*/
+/*FUNCTION Matpar::~Matpar() {{{1*/
+Matpar::~Matpar(){
+	return;
+}
+/*}}}1*/
+
+/*Object marshall*/
+/*FUNCTION Matpar::Demarshall {{{1*/
+void  Matpar::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+
+	memcpy(&mid,marshalled_dataset,sizeof(mid));marshalled_dataset+=sizeof(mid);
+	memcpy(&rho_ice,marshalled_dataset,sizeof(rho_ice));marshalled_dataset+=sizeof(rho_ice);
+	memcpy(&rho_water,marshalled_dataset,sizeof(rho_water));marshalled_dataset+=sizeof(rho_water);
+	memcpy(&heatcapacity,marshalled_dataset,sizeof(heatcapacity));marshalled_dataset+=sizeof(heatcapacity);
+	memcpy(&thermalconductivity,marshalled_dataset,sizeof(thermalconductivity));marshalled_dataset+=sizeof(thermalconductivity);
+	memcpy(&latentheat,marshalled_dataset,sizeof(latentheat));marshalled_dataset+=sizeof(latentheat);
+	memcpy(&beta,marshalled_dataset,sizeof(beta));marshalled_dataset+=sizeof(beta);
+	memcpy(&meltingpoint,marshalled_dataset,sizeof(meltingpoint));marshalled_dataset+=sizeof(meltingpoint);
+	memcpy(&mixed_layer_capacity,marshalled_dataset,sizeof(mixed_layer_capacity));marshalled_dataset+=sizeof(mixed_layer_capacity);
+	memcpy(&thermal_exchange_velocity,marshalled_dataset,sizeof(thermal_exchange_velocity));marshalled_dataset+=sizeof(thermal_exchange_velocity);
+	memcpy(&g,marshalled_dataset,sizeof(g));marshalled_dataset+=sizeof(g);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+/*FUNCTION Matpar::Marshall {{{1*/
+void  Matpar::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_type=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum type of Matpar: */
+	enum_type=MatparEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*marshall Matpar data: */
+	memcpy(marshalled_dataset,&mid,sizeof(mid));marshalled_dataset+=sizeof(mid);
+	memcpy(marshalled_dataset,&rho_ice,sizeof(rho_ice));marshalled_dataset+=sizeof(rho_ice);
+	memcpy(marshalled_dataset,&rho_water,sizeof(rho_water));marshalled_dataset+=sizeof(rho_water);
+	memcpy(marshalled_dataset,&heatcapacity,sizeof(heatcapacity));marshalled_dataset+=sizeof(heatcapacity);
+	memcpy(marshalled_dataset,&thermalconductivity,sizeof(thermalconductivity));marshalled_dataset+=sizeof(thermalconductivity);
+	memcpy(marshalled_dataset,&latentheat,sizeof(latentheat));marshalled_dataset+=sizeof(latentheat);
+	memcpy(marshalled_dataset,&beta,sizeof(beta));marshalled_dataset+=sizeof(beta);
+	memcpy(marshalled_dataset,&meltingpoint,sizeof(meltingpoint));marshalled_dataset+=sizeof(meltingpoint);
+	memcpy(marshalled_dataset,&mixed_layer_capacity,sizeof(mixed_layer_capacity));marshalled_dataset+=sizeof(mixed_layer_capacity);
+	memcpy(marshalled_dataset,&thermal_exchange_velocity,sizeof(thermal_exchange_velocity));marshalled_dataset+=sizeof(thermal_exchange_velocity);
+	memcpy(marshalled_dataset,&g,sizeof(g));marshalled_dataset+=sizeof(g);
+
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}1*/
+/*FUNCTION Matpar::MarshallSize {{{1*/
+int   Matpar::MarshallSize(){
+
+	return sizeof(mid)+
+		sizeof(rho_ice)+
+		sizeof(rho_water)+
+		sizeof(heatcapacity)+
+		sizeof(thermalconductivity)+
+		sizeof(latentheat)+
+		sizeof(beta)+
+		sizeof(meltingpoint)+
+		sizeof(mixed_layer_capacity)+
+		sizeof(thermal_exchange_velocity)+
+		sizeof(g)+
+		sizeof(int); //sizeof(int) for enum type
+}
+/*}}}1*/
+
+/*Object functions*/
+/*FUNCTION Matpar::copy {{{1*/
+Object* Matpar::copy() {
+	return new Matpar(*this); 
+}
+/*}}}1*/
+/*FUNCTION Matpar::DeepEcho {{{1*/
+void Matpar::DeepEcho(void){
+
+	printf("Matpar:\n");
+	printf("   mid: %i\n",mid);
+	printf("   rho_ice: %g\n",rho_ice);
+	printf("   rho_water: %g\n",rho_water);
+	printf("   heatcapacity: %g\n",heatcapacity);
+	printf("   thermalconductivity: %g\n",thermalconductivity);
+	printf("   latentheat: %g\n",latentheat);
+	printf("   beta: %g\n",beta);
+	printf("   meltingpoint: %g\n",meltingpoint);
+	printf("   mixed_layer_capacity: %g\n",mixed_layer_capacity);
+	printf("   thermal_exchange_velocity: %g\n",thermal_exchange_velocity);
+	printf("   g: %g\n",g);
+	return;
+}		
+/*}}}1*/
+/*FUNCTION Matpar::DistributeNumDofs {{{1*/
+void  Matpar::DistributeNumDofs(int* numdofspernode,int analysis_type){return;}
+/*}}}1*/
+/*FUNCTION Matpar::Echo {{{1*/
+void Matpar::Echo(void){
+
+	printf("Matpar:\n");
+	printf("   mid: %i\n",mid);
+	printf("   rho_ice: %g\n",rho_ice);
+	printf("   rho_water: %g\n",rho_water);
+	printf("   heatcapacity: %g\n",heatcapacity);
+	printf("   thermalconductivity: %g\n",thermalconductivity);
+	printf("   latentheat: %g\n",latentheat);
+	printf("   beta: %g\n",beta);
+	printf("   meltingpoint: %g\n",meltingpoint);
+	printf("   mixed_layer_capacity: %g\n",mixed_layer_capacity);
+	printf("   thermal_exchange_velocity: %g\n",thermal_exchange_velocity);
+	printf("   g: %g\n",g);
+	return;
+}
+/*}}}1*/
+/*FUNCTION Matpar::Enum {{{1*/
+int Matpar::Enum(void){
+
+	return MatparEnum;
+
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetBeta {{{1*/
+double Matpar::GetBeta(){
+	return beta;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetG {{{1*/
+double Matpar::GetG(){
+	return g;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetHeatCapacity {{{1*/
+double Matpar::GetHeatCapacity(){
+	return heatcapacity;
+}
+/*}}}1*/
+/*FUNCTION Matpar::Id {{{1*/
+int    Matpar::Id(void){ return mid; }
+/*}}}1*/
+/*FUNCTION Matpar::GetLatentHeat {{{1*/
+double Matpar::GetLatentHeat(){
+	return latentheat;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetMeltingPoint {{{1*/
+double Matpar::GetMeltingPoint(){
+	return meltingpoint;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetMixedLayerCapacity {{{1*/
+double Matpar::GetMixedLayerCapacity(){
+	return mixed_layer_capacity;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetRhoIce {{{1*/
+double Matpar::GetRhoIce(){
+	
+	return rho_ice;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetRhoWater {{{1*/
+double Matpar::GetRhoWater(){
+	return rho_water;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetThermalConductivity {{{1*/
+double Matpar::GetThermalConductivity(){
+	return thermalconductivity;
+}
+/*}}}1*/
+/*FUNCTION Matpar::GetThermalExchangeVelocity {{{1*/
+double Matpar::GetThermalExchangeVelocity(){
+	return thermal_exchange_velocity;
+}
+/*}}}1*/
+/*FUNCTION Matpar::MyRank {{{1*/
+int    Matpar::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}1*/
+/*FUNCTION Matpar::UpdateFromInputs {{{1*/
+void  Matpar::UpdateFromInputs(void* inputs){
+	
+	//ISSMERROR(" not supported yet!");
+
+}
+/*}}}1*/
Index: /issm/trunk/src/c/objects/Materials/Matpar.h
===================================================================
--- /issm/trunk/src/c/objects/Materials/Matpar.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Materials/Matpar.h	(revision 3683)
@@ -0,0 +1,62 @@
+/*!\file Matpar.h
+ * \brief: header file for matpar object
+ */
+
+#ifndef _MATPAR_H_
+#define _MATPAR_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Material.h"
+class IoModel;
+/*}}}*/
+
+class Matpar: public Material{
+
+	private: 
+		int	mid;
+		double	rho_ice; 
+		double	rho_water;
+		double  heatcapacity;
+		double  thermalconductivity;
+		double  latentheat;
+		double  beta;
+		double  meltingpoint;
+		double  mixed_layer_capacity;
+		double  thermal_exchange_velocity;
+		double  g;
+
+	public:
+
+		Matpar();
+	
+		Matpar(int	mid, double	rho_ice, double	rho_water, double  heatcapacity, double  thermalconductivity, double  latentheat, double  beta, double  meltingpoint, double  mixed_layer_capacity, double  thermal_exchange_velocity, double  g);
+		void Init(int	mid, double	rho_ice, double	rho_water, double  heatcapacity, double  thermalconductivity, double  latentheat, double  beta, double  meltingpoint, double  mixed_layer_capacity, double  thermal_exchange_velocity, double  g);
+		Matpar(int matpar_id, IoModel* iomodel);
+		~Matpar();
+
+		void  Echo();
+		void  DeepEcho();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		void  Demarshall(char** pmarshalled_dataset);
+		int   Enum();
+		int   Id(); 
+		int   MyRank();
+		void  DistributeNumDofs(int* numdofspernode,int analysis_type);
+		void  UpdateFromInputs(void* inputs);
+		double GetG();
+		double GetRhoIce();
+		double GetRhoWater();
+		double GetMixedLayerCapacity();
+		double GetThermalExchangeVelocity();
+		double GetHeatCapacity();
+		double GetThermalConductivity();
+		double GetLatentHeat();
+		double GetBeta();
+		double GetMeltingPoint();
+		Object* copy();
+
+};
+
+#endif  /* _MATPAR_H_ */
Index: /issm/trunk/src/c/objects/Params/BoolParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/BoolParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/BoolParam.cpp	(revision 3683)
@@ -0,0 +1,141 @@
+/*!\file BoolParam.c
+ * \brief: implementation of the BoolParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION BoolParam::BoolParam(){{{1*/
+BoolParam::BoolParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION BoolParam::BoolParam(int enum_type,IssmBool value){{{1*/
+BoolParam::BoolParam(int in_enum_type,IssmBool in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION BoolParam::~BoolParam(){{{1*/
+BoolParam::~BoolParam(){
+	return;
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION BoolParam::copy{{{1*/
+Object* BoolParam::copy() {
+	
+	return new BoolParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION BoolParam::DeepEcho{{{1*/
+void BoolParam::DeepEcho(void){
+
+	printf("BoolParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %s\n",this->value?"true":"false");
+}
+/*}}}*/
+/*FUNCTION BoolParam::Demarshall{{{1*/
+void  BoolParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION BoolParam::Echo {{{1*/
+void BoolParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION BoolParam::Enum{{{1*/
+int BoolParam::Enum(void){
+
+	return BoolParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION BoolParam::Id{{{1*/
+int    BoolParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION BoolParam::Marshall{{{1*/
+void  BoolParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of BoolParam: */
+	enum_value=BoolParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall BoolParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION BoolParam::MarshallSize{{{1*/
+int   BoolParam::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION BoolParam::MyRank{{{1*/
+int    BoolParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION BoolParam::GetParameterName(void); {{{1*/
+char* BoolParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION BoolParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  BoolParam::SetMatlabField(mxArray* dataref){
+	char* name=NULL;
+	name=this->GetParameterName();
+	mxSetField( dataref, 0, name,mxCreateDoubleScalar((double)value));
+	xfree((void**)&name);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/BoolParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/BoolParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/BoolParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file BoolParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _BOOLPARAM_H_
+#define _BOOLPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class BoolParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		IssmBool value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		BoolParam();
+		BoolParam(int enum_type,IssmBool value);
+		~BoolParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){*pbool=value;}
+		void  GetParameterValue(int* pinteger){ISSMERROR("Bool param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("Bool param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("Bool param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("Bool param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("Bool param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("Bool param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("Bool param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("Bool param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _BOOLPARAM_H */
Index: /issm/trunk/src/c/objects/Params/DoubleMatParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleMatParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleMatParam.cpp	(revision 3683)
@@ -0,0 +1,196 @@
+/*!\file DoubleMatParam.c
+ * \brief: implementation of the DoubleMatParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION DoubleMatParam::DoubleMatParam(){{{1*/
+DoubleMatParam::DoubleMatParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::DoubleMatParam(int enum_type,IssmDoubleMat value){{{1*/
+DoubleMatParam::DoubleMatParam(int in_enum_type,double* in_value, int in_M,int in_N){
+
+	enum_type=in_enum_type;
+	M=in_M;
+	N=in_N;
+
+	value=(double*)xmalloc(M*N*sizeof(double));
+	memcpy(value,in_value,M*N*sizeof(double));
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::~DoubleMatParam(){{{1*/
+DoubleMatParam::~DoubleMatParam(){
+	xfree((void**)&value);
+	return;
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION DoubleMatParam::copy{{{1*/
+Object* DoubleMatParam::copy() {
+	
+	return new DoubleMatParam(this->enum_type,this->value,this->M,this->N);
+
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::DeepEcho{{{1*/
+void DoubleMatParam::DeepEcho(void){
+
+	int i,j;
+	
+	printf("DoubleMatParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   matrix size: %ix%i\n",this->M,this->N);
+	for(i=0;i<this->M;i++){
+		for(i=0;i<this->N;i++){
+			printf("%i %i %g\n",i,j,*(this->value+N*i+j));
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::Demarshall{{{1*/
+void  DoubleMatParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*data: */
+	memcpy(&M,marshalled_dataset,sizeof(M));marshalled_dataset+=sizeof(M);
+	memcpy(&N,marshalled_dataset,sizeof(N));marshalled_dataset+=sizeof(N);
+	value=(double*)xmalloc(M*N*sizeof(double));
+	memcpy(value,marshalled_dataset,M*N*sizeof(double));marshalled_dataset+=M*N*sizeof(double);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::Echo {{{1*/
+void DoubleMatParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::Enum{{{1*/
+int DoubleMatParam::Enum(void){
+
+	return DoubleMatParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::Id{{{1*/
+int    DoubleMatParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION DoubleMatParam::Marshall{{{1*/
+void  DoubleMatParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of DoubleMatParam: */
+	enum_value=DoubleMatParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall DoubleMatParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+	memcpy(marshalled_dataset,&N,sizeof(N));marshalled_dataset+=sizeof(N);
+	memcpy(marshalled_dataset,value,M*N*sizeof(double));marshalled_dataset+=M*N*sizeof(double);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::MarshallSize{{{1*/
+int   DoubleMatParam::MarshallSize(){
+	
+	return sizeof(M)
+		+sizeof(N)
+		+M*N*sizeof(double)
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::MyRank{{{1*/
+int    DoubleMatParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::GetParameterValue(double** pdoublearray,int* pM,int* pN){{{1*/
+void  DoubleMatParam::GetParameterValue(double** pdoublearray,int* pM,int* pN){
+	double* output=NULL;
+	int M,N;
+
+	M=this->M;
+	N=this->N;
+	output=(double*)xmalloc((int)(M*N*sizeof(double)));
+	memcpy(output,value,M*N*sizeof(double));
+
+	/*Assign output pointers:*/
+	*pM=M;
+	*pN=N;
+	*pdoublearray=output;
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::GetParameterName(void); {{{1*/
+char* DoubleMatParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION DoubleMatParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  DoubleMatParam::SetMatlabField(mxArray* dataref){
+
+	mxArray* pfield=NULL;
+	mxArray* pfield2=NULL;
+	double* doublemat=NULL;
+	int M,N;
+	char* name=NULL;
+	
+	name=this->GetParameterName();
+	this->GetParameterValue(&doublemat,&M,&N);
+				
+	pfield=mxCreateDoubleMatrix(0,0,mxREAL);
+	mxSetM(pfield,N);
+	mxSetN(pfield,M);
+	mxSetPr(pfield,doublemat);
+	
+	//transpose the matrix, written directly to matlab! from C to matlab.
+	mexCallMATLAB(1,&pfield2, 1, &pfield, "'");
+	mxSetField( dataref, 0, name,pfield2);
+	
+	/*Free ressources:*/
+	xfree((void**)&name);
+	xfree((void**)&doublemat);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/DoubleMatParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleMatParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleMatParam.h	(revision 3683)
@@ -0,0 +1,59 @@
+/*! \file DoubleMatParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _DOUBLEMATPARAM_H_
+#define _DOUBLEMATPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class DoubleMatParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		IssmDouble* value;
+		int M;
+		int N;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		DoubleMatParam();
+		DoubleMatParam(int enum_type,IssmDouble* value,int M,int N);
+		~DoubleMatParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("DoubleMat param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("DoubleMat param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("DoubleMat param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("DoubleMat param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("DoubleMat param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("DoubleMat param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM,int* pN);
+		void  GetParameterValue(Vec* pvec){ISSMERROR("DoubleMat param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("DoubleMat param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _DOUBLEMATPARAM_H */
Index: /issm/trunk/src/c/objects/Params/DoubleParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleParam.cpp	(revision 3683)
@@ -0,0 +1,139 @@
+/*!\file DoubleParam.c
+ * \brief: implementation of the DoubleParam object
+ */
+
+#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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION DoubleParam::DoubleParam(){{{1*/
+DoubleParam::DoubleParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleParam::DoubleParam(int enum_type,IssmDouble value){{{1*/
+DoubleParam::DoubleParam(int in_enum_type,IssmDouble in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION DoubleParam::~DoubleParam(){{{1*/
+DoubleParam::~DoubleParam(){
+	return;
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION DoubleParam::copy{{{1*/
+Object* DoubleParam::copy() {
+	
+	return new DoubleParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION DoubleParam::DeepEcho{{{1*/
+void DoubleParam::DeepEcho(void){
+
+	printf("DoubleParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %g\n",this->value);
+}
+/*}}}*/
+/*FUNCTION DoubleParam::Demarshall{{{1*/
+void  DoubleParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleParam::Echo {{{1*/
+void DoubleParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION DoubleParam::Enum{{{1*/
+int DoubleParam::Enum(void){
+
+	return DoubleParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION DoubleParam::Id{{{1*/
+int    DoubleParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION DoubleParam::Marshall{{{1*/
+void  DoubleParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of DoubleParam: */
+	enum_value=DoubleParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall DoubleParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION DoubleParam::MarshallSize{{{1*/
+int   DoubleParam::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION DoubleParam::MyRank{{{1*/
+int    DoubleParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION DoubleParam::GetParameterName(void); {{{1*/
+char* DoubleParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION DoubleParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  DoubleParam::SetMatlabField(mxArray* dataref){
+
+	char* name=NULL;
+	name=this->GetParameterName();
+	mxSetField( dataref, 0, name,mxCreateDoubleScalar(value));
+	xfree((void**)&name);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/DoubleParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file DoubleParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _DOUBLEPARAM_H_
+#define _DOUBLEPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class DoubleParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		IssmDouble value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		DoubleParam();
+		DoubleParam(int enum_type,IssmDouble value);
+		~DoubleParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("Double param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("Double param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){*pdouble=value;}
+		void  GetParameterValue(char** pstring){ISSMERROR("Double param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("Double param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("Double param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("Double param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("Double param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("Double param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _DOUBLEPARAM_H */
Index: /issm/trunk/src/c/objects/Params/DoubleVecParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleVecParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleVecParam.cpp	(revision 3683)
@@ -0,0 +1,186 @@
+/*!\file DoubleVecParam.c
+ * \brief: implementation of the DoubleVecParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION DoubleVecParam::DoubleVecParam(){{{1*/
+DoubleVecParam::DoubleVecParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::DoubleVecParam(int enum_type,IssmDoubleVec value){{{1*/
+DoubleVecParam::DoubleVecParam(int in_enum_type,double* in_value, int in_M){
+
+	enum_type=in_enum_type;
+	M=in_M;
+
+	value=(double*)xmalloc(M*sizeof(double));
+	memcpy(value,in_value,M*sizeof(double));
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::~DoubleVecParam(){{{1*/
+DoubleVecParam::~DoubleVecParam(){
+	xfree((void**)&value);
+	return;
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION DoubleVecParam::copy{{{1*/
+Object* DoubleVecParam::copy() {
+	
+	return new DoubleVecParam(this->enum_type,this->value,this->M);
+
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::DeepEcho{{{1*/
+void DoubleVecParam::DeepEcho(void){
+
+	int i;
+	
+	printf("DoubleVecParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   vector size: %i\n",this->M);
+	for(i=0;i<this->M;i++){
+		printf("%i %g\n",i,this->value[i]);
+	}
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::Demarshall{{{1*/
+void  DoubleVecParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*data: */
+	memcpy(&M,marshalled_dataset,sizeof(M));marshalled_dataset+=sizeof(M);
+	value=(double*)xmalloc(M*sizeof(double));
+	memcpy(value,marshalled_dataset,M*sizeof(double));marshalled_dataset+=M*sizeof(double);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::Echo {{{1*/
+void DoubleVecParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::Enum{{{1*/
+int DoubleVecParam::Enum(void){
+
+	return DoubleVecParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::Id{{{1*/
+int    DoubleVecParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION DoubleVecParam::Marshall{{{1*/
+void  DoubleVecParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of DoubleVecParam: */
+	enum_value=DoubleVecParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall DoubleVecParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+	memcpy(marshalled_dataset,value,M*sizeof(double));marshalled_dataset+=M*sizeof(double);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::MarshallSize{{{1*/
+int   DoubleVecParam::MarshallSize(){
+	
+	return sizeof(M)
+		+M*sizeof(double)
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::MyRank{{{1*/
+int    DoubleVecParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::GetParameterValue(double** pdoublearray,int* pM){{{1*/
+void  DoubleVecParam::GetParameterValue(double** pdoublearray,int* pM){
+	double* output=NULL;
+	double M;
+
+
+	M=this->M;
+	output=(double*)xmalloc(M*sizeof(double));
+	memcpy(output,value,M*sizeof(double));
+
+	/*Assign output pointers:*/
+	*pM=M;
+	*pdoublearray=output;
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::GetParameterName(void); {{{1*/
+char* DoubleVecParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION DoubleVecParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  DoubleVecParam::SetMatlabField(mxArray* dataref){
+
+	char* name=NULL;
+	double* doublevec=NULL;
+	int M;
+	mxArray* pfield=NULL;
+
+	this->GetParameterValue(&doublevec,&M);
+	name=this->GetParameterName();
+				
+	pfield=mxCreateDoubleMatrix(0,0,mxREAL);
+	mxSetM(pfield,M);
+	mxSetN(pfield,1);
+	mxSetPr(pfield,doublevec);
+	
+	mxSetField( dataref, 0, name, pfield);
+
+	/*Free ressources:*/
+	xfree((void**)&name);
+	xfree((void**)&doublevec);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/DoubleVecParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/DoubleVecParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/DoubleVecParam.h	(revision 3683)
@@ -0,0 +1,58 @@
+/*! \file DoubleVecParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _DOUBLEVECPARAM_H_
+#define _DOUBLEVECPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class DoubleVecParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		IssmDouble* value;
+		int M;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		DoubleVecParam();
+		DoubleVecParam(int enum_type,IssmDouble* value,int M);
+		~DoubleVecParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("DoubleVec param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("DoubleVec param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("DoubleVec param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("DoubleVec param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("DoubleVec param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM);
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("DoubleVec param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("DoubleVec param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("DoubleVec param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _DOUBLEVECPARAM_H */
Index: /issm/trunk/src/c/objects/Params/IntParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/IntParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/IntParam.cpp	(revision 3683)
@@ -0,0 +1,143 @@
+/*!\file IntParam.c
+ * \brief: implementation of the IntParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION IntParam::IntParam(){{{1*/
+IntParam::IntParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION IntParam::IntParam(int enum_type,IssmInt value){{{1*/
+IntParam::IntParam(int in_enum_type,IssmInt in_value){
+
+	enum_type=in_enum_type;
+	value=in_value;
+}
+/*}}}*/
+/*FUNCTION IntParam::~IntParam(){{{1*/
+IntParam::~IntParam(){
+	return;
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION IntParam::copy{{{1*/
+Object* IntParam::copy() {
+	
+	return new IntParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION IntParam::DeepEcho{{{1*/
+void IntParam::DeepEcho(void){
+
+	printf("IntParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %i\n",this->value);
+}
+/*}}}*/
+/*FUNCTION IntParam::Demarshall{{{1*/
+void  IntParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(&value,marshalled_dataset,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION IntParam::Echo {{{1*/
+void IntParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION IntParam::Enum{{{1*/
+int IntParam::Enum(void){
+
+	return IntParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION IntParam::Id{{{1*/
+int    IntParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION IntParam::Marshall{{{1*/
+void  IntParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of IntParam: */
+	enum_value=IntParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall IntParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&value,sizeof(value));marshalled_dataset+=sizeof(value);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION IntParam::MarshallSize{{{1*/
+int   IntParam::MarshallSize(){
+	
+	return sizeof(value)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION IntParam::MyRank{{{1*/
+int    IntParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION IntParam::GetParameterName(void); {{{1*/
+char* IntParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION IntParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  IntParam::SetMatlabField(mxArray* dataref){
+	
+	char* name=NULL;
+	name=this->GetParameterName();
+	mxSetField( dataref, 0, name,mxCreateDoubleScalar((double)value));
+	xfree((void**)&name);
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/IntParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/IntParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/IntParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file IntParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _INTPARAM_H_
+#define _INTPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class IntParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		IssmInt value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		IntParam();
+		IntParam(int enum_type,IssmInt value);
+		~IntParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("Int param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){*pinteger=value;}
+		void  GetParameterValue(double* pdouble){ISSMERROR("Int param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("Int param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("Int param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("Int param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("Int param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("Int param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("Int param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _INTPARAM_H */
Index: /issm/trunk/src/c/objects/Params/Param.h
===================================================================
--- /issm/trunk/src/c/objects/Params/Param.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/Param.h	(revision 3683)
@@ -0,0 +1,37 @@
+/*!\file:  Param.h
+ * \brief abstract class for Param object
+ */ 
+
+
+#ifndef _PARAM_H_
+#define _PARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "../Object.h"
+#include "../Node.h"
+/*}}}*/
+
+class Param: public Object{
+
+	public: 
+		
+		virtual        ~Param(){};
+
+		/*methods:{{{1*/
+		virtual int   EnumType()=0;
+		virtual void  GetParameterValue(bool* pbool)=0;
+		virtual void  GetParameterValue(int* pinteger)=0;
+		virtual void  GetParameterValue(double* pdouble)=0;
+		virtual void  GetParameterValue(char** pstring)=0;
+		virtual void  GetParameterValue(char*** pstringarray,int* pM)=0;
+		virtual void  GetParameterValue(double** pdoublearray,int* pM)=0;
+		virtual void  GetParameterValue(double** pdoublearray,int* pM,int* pN)=0;
+		virtual void  GetParameterValue(Vec* pvec)=0;
+		virtual void  GetParameterValue(Mat* pmat)=0;
+		virtual char* GetParameterName(void)=0;
+		virtual void  SetMatlabField(mxArray* dataref)=0;
+		/*}}}*/
+
+};
+#endif
Index: /issm/trunk/src/c/objects/Params/PetscMatParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/PetscMatParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/PetscMatParam.cpp	(revision 3683)
@@ -0,0 +1,224 @@
+/*!\file PetscMatParam.c
+ * \brief: implementation of the PetscMatParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION PetscMatParam::PetscMatParam(){{{1*/
+PetscMatParam::PetscMatParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::PetscMatParam(int enum_type,IssmPetscMat value){{{1*/
+PetscMatParam::PetscMatParam(int in_enum_type,Mat in_value){
+
+	enum_type=in_enum_type;
+
+	value=NULL;
+
+	if(in_value){
+		MatDuplicate(in_value,MAT_COPY_VALUES,&value);
+	}
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::~PetscMatParam(){{{1*/
+PetscMatParam::~PetscMatParam(){
+	MatFree(&value);
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION PetscMatParam::copy{{{1*/
+Object* PetscMatParam::copy() {
+	
+	return new PetscMatParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::DeepEcho{{{1*/
+void PetscMatParam::DeepEcho(void){
+
+	int i;
+	printf("PetscMatParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	MatView(value,PETSC_VIEWER_STDOUT_WORLD);
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::Demarshall{{{1*/
+void  PetscMatParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i,j;
+	int   M,N;
+	double* serial_mat=NULL;
+	int*    idxm=NULL;
+	int*    idxn=NULL;
+	double sparsity=.001;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*data: */
+	memcpy(&M,marshalled_dataset,sizeof(M));marshalled_dataset+=sizeof(M);
+	memcpy(&N,marshalled_dataset,sizeof(N));marshalled_dataset+=sizeof(N);
+	if(M!=0 && N!=0){
+		serial_mat=(double*)xmalloc(M*N*sizeof(double));
+		memcpy(serial_mat,marshalled_dataset,M*N*sizeof(double));marshalled_dataset+=(M*N*sizeof(double));
+		value=NewMat(M,N,&sparsity,NULL,NULL);
+		idxm=(int*)xmalloc(M*sizeof(int));
+		idxn=(int*)xmalloc(N*sizeof(int));
+		for(i=0;i<M;i++)idxm[i]=i;
+		for(i=0;i<N;i++)idxn[i]=i;
+		MatSetValues(value,M,idxm,N,idxn,serial_mat,INSERT_VALUES); 
+		MatAssemblyBegin(value,MAT_FINAL_ASSEMBLY); 
+		MatAssemblyEnd(value,MAT_FINAL_ASSEMBLY);
+
+			}
+	else{
+		value=NULL;
+	}
+
+	/*Free ressources:*/
+	xfree((void**)&serial_mat);
+	xfree((void**)&idxm);
+	xfree((void**)&idxn);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::Echo {{{1*/
+void PetscMatParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::Enum{{{1*/
+int PetscMatParam::Enum(void){
+
+	return PetscMatParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::Id{{{1*/
+int    PetscMatParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION PetscMatParam::Marshall{{{1*/
+void  PetscMatParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+	int   M,N;
+	double* serial_mat=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of PetscMatParam: */
+	enum_value=PetscMatParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall PetscMatParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	if(value){
+		MatGetSize(value,&M,&N);
+		MatToSerial(&serial_mat,value);
+		memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+		memcpy(marshalled_dataset,&N,sizeof(N));marshalled_dataset+=sizeof(N);
+		memcpy(marshalled_dataset,serial_mat,M*N*sizeof(double));marshalled_dataset+=(M*N*sizeof(double));
+	}
+	else{
+		M=0;
+		N=0;
+		memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+		memcpy(marshalled_dataset,&N,sizeof(N));marshalled_dataset+=sizeof(N);
+	}
+	
+	/*Free ressources:*/
+	xfree((void**)&serial_mat);
+
+	/*return:*/
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::MarshallSize{{{1*/
+int   PetscMatParam::MarshallSize(){
+
+	int M=0;
+	int N=0;
+	if(value)MatGetSize(value,&M,&N);
+			
+	return sizeof(M)+
+		sizeof(N)+
+		M*N*sizeof(double)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::MyRank{{{1*/
+int    PetscMatParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::GetParameterValue(Mat* pvalue){{{1*/
+void  PetscMatParam::GetParameterValue(Mat* poutput){
+	Mat output=NULL;
+
+	if(value){
+		MatDuplicate(value,MAT_COPY_VALUES,&output);
+	}
+	*poutput=output;
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::GetParameterName(void); {{{1*/
+char* PetscMatParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION PetscMatParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  PetscMatParam::SetMatlabField(mxArray* dataref){
+	
+	char* name=NULL;
+	int   M,N;
+	double* doublemat=NULL;
+	mxArray* pfield=NULL;
+
+	MatToSerial(&doublemat,value);
+	MatGetSize(value,&M,&N);
+	name=this->GetParameterName();
+				
+	pfield=mxCreateDoubleMatrix(0,0,mxREAL);
+	mxSetM(pfield,M);
+	mxSetN(pfield,N);
+	mxSetPr(pfield,doublemat);
+	mxSetField( dataref, 0, name, pfield);
+
+	/*Free ressources:*/
+	xfree((void**)&name);
+	xfree((void**)&doublemat);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/PetscMatParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/PetscMatParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/PetscMatParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file PetscMatParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _PETSCMATPARAM_H_
+#define _PETSCMATPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class PetscMatParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		Mat value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		PetscMatParam();
+		PetscMatParam(int enum_type,Mat value);
+		~PetscMatParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("PetscMat param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("PetscMat param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("PetscMat param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("PetscMat param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("PetscMat param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("PetscMat param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("PetscMat param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("PetscMat param cannot return a vec");}
+		void  GetParameterValue(Mat* poutput);
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _PETSCMATPARAM_H */
Index: /issm/trunk/src/c/objects/Params/PetscVecParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/PetscVecParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/PetscVecParam.cpp	(revision 3683)
@@ -0,0 +1,218 @@
+/*!\file PetscVecParam.c
+ * \brief: implementation of the PetscVecParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION PetscVecParam::PetscVecParam(){{{1*/
+PetscVecParam::PetscVecParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::PetscVecParam(int enum_type,IssmPetscVec value){{{1*/
+PetscVecParam::PetscVecParam(int in_enum_type,Vec in_value){
+
+	enum_type=in_enum_type;
+
+	value=NULL;
+
+	if(in_value){
+		VecDuplicate(in_value,&value);
+		VecCopy(in_value,value);
+	}
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::~PetscVecParam(){{{1*/
+PetscVecParam::~PetscVecParam(){
+	VecFree(&value);
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION PetscVecParam::copy{{{1*/
+Object* PetscVecParam::copy() {
+	
+	return new PetscVecParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::DeepEcho{{{1*/
+void PetscVecParam::DeepEcho(void){
+
+	int i;
+	printf("PetscVecParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	VecView(value,PETSC_VIEWER_STDOUT_WORLD);
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::Demarshall{{{1*/
+void  PetscVecParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+	int   M;
+	double* serial_vec=NULL;
+	int*    idxm=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	
+	/*data: */
+	
+	memcpy(&M,marshalled_dataset,sizeof(M));marshalled_dataset+=sizeof(M);
+	if(M){
+		serial_vec=(double*)xmalloc(M*sizeof(double));
+		memcpy(serial_vec,marshalled_dataset,M*sizeof(double));marshalled_dataset+=(M*sizeof(double));
+
+		value=NewVec(M);
+		idxm=(int*)xmalloc(M*sizeof(int));
+		for(i=0;i<M;i++)idxm[i]=i;
+		VecSetValues(value,M,idxm,serial_vec,INSERT_VALUES);
+
+		VecAssemblyBegin(value);
+		VecAssemblyEnd(value);
+
+		
+	}
+	else{
+		value=NULL;
+	}
+
+	/*Free ressources:*/
+	xfree((void**)&serial_vec);
+	xfree((void**)&idxm);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::Echo {{{1*/
+void PetscVecParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::Enum{{{1*/
+int PetscVecParam::Enum(void){
+
+	return PetscVecParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::Id{{{1*/
+int    PetscVecParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION PetscVecParam::Marshall{{{1*/
+void  PetscVecParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+	int   M;
+	double* serial_value=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of PetscVecParam: */
+	enum_value=PetscVecParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall PetscVecParam data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	if(value){
+		VecGetSize(value,&M);
+		VecToMPISerial(&serial_value,value);
+		memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+		memcpy(marshalled_dataset,serial_value,M*sizeof(double));marshalled_dataset+=(M*sizeof(double));
+	}
+	else{
+		M=0;
+		memcpy(marshalled_dataset,&M,sizeof(M));marshalled_dataset+=sizeof(M);
+	}
+	/*Free ressources:*/
+	xfree((void**)&serial_value);
+
+	/*return:*/
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::MarshallSize{{{1*/
+int   PetscVecParam::MarshallSize(){
+
+	int M=0;
+	if(value)VecGetSize(value,&M);
+
+	return sizeof(M)+M*sizeof(double)
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::MyRank{{{1*/
+int    PetscVecParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::GetParameterValue(Vec* pvalue){{{1*/
+void  PetscVecParam::GetParameterValue(Vec* poutput){
+	Vec output=NULL;
+
+	if(value){
+		VecDuplicate(value,&output);
+		VecCopy(value,output);
+	}
+	*poutput=output;
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::GetParameterName(void); {{{1*/
+char* PetscVecParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION PetscVecParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  PetscVecParam::SetMatlabField(mxArray* dataref){
+
+	mxArray* pfield=NULL;
+	char* name=NULL;
+	double* doublevec=NULL;
+	int M;
+	
+	VecToMPISerial(&doublevec,value);
+	VecGetSize(value,&M);
+	name=this->GetParameterName();
+	
+	pfield=mxCreateDoubleMatrix(0,0,mxREAL);
+	mxSetM(pfield,M);
+	mxSetN(pfield,1);
+	mxSetPr(pfield,doublevec);
+	
+	mxSetField( dataref, 0, name, pfield);
+
+	/*Free ressources:*/
+	xfree((void**)&name);
+	xfree((void**)&doublevec);
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/PetscVecParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/PetscVecParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/PetscVecParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file PetscVecParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _PETSCVECPARAM_H_
+#define _PETSCVECPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class PetscVecParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		Vec value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		PetscVecParam();
+		PetscVecParam(int enum_type,Vec value);
+		~PetscVecParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("PetscVec param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("PetscVec param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("PetscVec param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("PetscVec param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("PetscVec param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("PetscVec param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("PetscVec param cannot return a double array");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("PetscVec param cannot return a Mat");}
+		void  GetParameterValue(Vec* poutput);
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _PETSCVECPARAM_H */
Index: /issm/trunk/src/c/objects/Params/StringArrayParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/StringArrayParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/StringArrayParam.cpp	(revision 3683)
@@ -0,0 +1,250 @@
+/*!\file StringArrayParam.c
+ * \brief: implementation of the StringArrayParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION StringArrayParam::StringArrayParam(){{{1*/
+StringArrayParam::StringArrayParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::StringArrayParam(int enum_type,char** in_values,int in_numstrings){{{1*/
+StringArrayParam::StringArrayParam(int in_enum_type,char** in_values, int in_numstrings){
+
+	int i;
+		int size;
+
+	enum_type=in_enum_type;
+	numstrings=in_numstrings;
+
+	value=(char**)xmalloc(numstrings*sizeof(char*));
+	for(i=0;i<numstrings;i++){
+		char* string=NULL;
+		size=strlen(in_values[i])+1;
+		string=(char*)xmalloc(size*sizeof(char));
+		memcpy(string,in_values[i],size*sizeof(char));
+		value[i]=string;
+	}
+	
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::~StringArrayParam(){{{1*/
+StringArrayParam::~StringArrayParam(){
+		
+	int i;
+	
+	char* string=NULL;
+	for(i=0;i<this->numstrings;i++){
+		string=value[i];
+		xfree((void**)&string);
+	}
+	xfree((void**)&value);
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION StringArrayParam::copy{{{1*/
+Object* StringArrayParam::copy() {
+	
+	return new StringArrayParam(this->enum_type,this->value,this->numstrings);
+
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::DeepEcho{{{1*/
+void StringArrayParam::DeepEcho(void){
+
+	int i;
+	char* string=NULL;
+
+	printf("StringArrayParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	for(i=0;i<this->numstrings;i++){
+		string=this->value[i];
+		printf("   %i: %s\n",i,string);
+	}
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::Demarshall{{{1*/
+void  StringArrayParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+	int   stringsize;
+	char* string=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	memcpy(&numstrings,marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);
+	this->value=(char**)xmalloc(numstrings*sizeof(char*));
+
+	for(i=0;i<numstrings;i++){
+		memcpy(&stringsize,marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);
+	
+		string=(char*)xmalloc(stringsize*sizeof(char));
+		memcpy(string,marshalled_dataset,stringsize*sizeof(char));marshalled_dataset+=stringsize*sizeof(char);
+
+		this->value[i]=string;
+	}
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::Echo {{{1*/
+void StringArrayParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::Enum{{{1*/
+int StringArrayParam::Enum(void){
+
+	return StringArrayParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::Id{{{1*/
+int    StringArrayParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION StringArrayParam::Marshall{{{1*/
+void  StringArrayParam::Marshall(char** pmarshalled_dataset){
+
+	int   i;
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+	int   stringsize;
+	char* string=NULL;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of StringArrayParam: */
+	enum_value=StringArrayParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+	
+	/*marshall data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	memcpy(marshalled_dataset,&numstrings,sizeof(numstrings));marshalled_dataset+=sizeof(numstrings);
+	for(i=0;i<numstrings;i++){
+		string=this->value[i];
+		stringsize=strlen(string)+1;
+		
+		memcpy(marshalled_dataset,&stringsize,sizeof(stringsize));marshalled_dataset+=sizeof(stringsize);
+		memcpy(marshalled_dataset,string,stringsize*sizeof(char));marshalled_dataset+=stringsize*sizeof(char);
+	}
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::MarshallSize{{{1*/
+int   StringArrayParam::MarshallSize(){
+
+	int i;
+	int marshallsize;
+	int stringsize;
+	char* string=NULL;
+
+	marshallsize+=sizeof(numstrings);
+
+	for(i=0;i<numstrings;i++){
+		string=this->value[i];
+		stringsize=strlen(string)+1;
+		marshallsize+=sizeof(stringsize);
+		marshallsize+=stringsize*sizeof(char);
+	}
+	
+	marshallsize+=sizeof(enum_type);
+	marshallsize+=sizeof(int); //sizeof(int) for enum value
+
+	return marshallsize;
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::MyRank{{{1*/
+int    StringArrayParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::GetParameterValue(char*** pstringarray, int* pnumstrings){{{1*/
+void  StringArrayParam::GetParameterValue(char*** pstringarray,int* pM){
+	
+	int   i;
+	char** outstrings=NULL;
+	int   M;
+	char* string=NULL;
+	char* string2=NULL;
+	int   stringsize;
+
+	M=this->numstrings;
+	outstrings=(char**)xmalloc(this->numstrings*sizeof(char*));
+
+	for(i=0;i<this->numstrings;i++){
+		string=this->value[i];
+		stringsize=strlen(string)+1;
+
+		string2=(char*)xmalloc(stringsize*sizeof(char));
+		memcpy(string2,string,stringsize*sizeof(char));
+
+		outstrings[i]=string2;
+	}
+
+	/*Assign output pointers:*/
+	*pM=M;
+	*pstringarray=outstrings;
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::GetParameterName(void); {{{1*/
+char* StringArrayParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION StringArrayParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  StringArrayParam::SetMatlabField(mxArray* dataref){
+	
+	int      i;
+	char*    name=NULL;
+	mwSize   dims[2]={0};
+	mxArray* pfield=NULL;
+	
+	name=this->GetParameterName();
+
+	dims[0]=this->numstrings;
+	dims[1]=1;
+	pfield=mxCreateCellArray(2,dims);
+	for(i=0;i<this->numstrings;i++){
+		char* string=value[i];
+		mxSetCell(pfield,i,mxCreateString(string));
+	}
+	mxSetField( dataref, 0, name,pfield);
+
+	/*Free ressources:*/
+	xfree((void**)&name);
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/StringArrayParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/StringArrayParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/StringArrayParam.h	(revision 3683)
@@ -0,0 +1,59 @@
+/*! \file StringArrayParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _STRINGARRAYPARAM_H_
+#define _STRINGARRAYPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class StringArrayParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int      enum_type;
+		char**   value;
+		int      numstrings;
+
+
+	public:
+		/*constructors, destructors: {{{1*/
+		StringArrayParam();
+		StringArrayParam(int enum_type,char** values, int numstrings);
+		~StringArrayParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("StringArray param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("StringArray param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("StringArray param cannot return a double");}
+		void  GetParameterValue(char** pstring){ISSMERROR("StringArray param cannot return a string");}
+		void  GetParameterValue(char*** pstringarray,int* pM);
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("StringArray param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("StringArray param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("StringArray param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("StringArray param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _STRINGARRAYPARAM_H */
Index: /issm/trunk/src/c/objects/Params/StringParam.cpp
===================================================================
--- /issm/trunk/src/c/objects/Params/StringParam.cpp	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/StringParam.cpp	(revision 3683)
@@ -0,0 +1,177 @@
+/*!\file StringParam.c
+ * \brief: implementation of the StringParam object
+ */
+
+/*header files: */
+/*{{{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 "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../DataSet/DataSet.h"
+#include "../../include/typedefs.h"
+#include "../../include/types.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+/*Object constructors and destructor*/
+/*FUNCTION StringParam::StringParam(){{{1*/
+StringParam::StringParam(){
+	return;
+}
+/*}}}*/
+/*FUNCTION StringParam::StringParam(int enum_type,IssmString value){{{1*/
+StringParam::StringParam(int in_enum_type,char* in_value){
+
+	enum_type=in_enum_type;
+	value=(char*)xmalloc((strlen(in_value)+1)*sizeof(char));
+	strcpy(value,in_value);
+	
+}
+/*}}}*/
+/*FUNCTION StringParam::~StringParam(){{{1*/
+StringParam::~StringParam(){
+	xfree((void**)&value);
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION StringParam::copy{{{1*/
+Object* StringParam::copy() {
+	
+	return new StringParam(this->enum_type,this->value);
+
+}
+/*}}}*/
+/*FUNCTION StringParam::DeepEcho{{{1*/
+void StringParam::DeepEcho(void){
+
+	printf("StringParam:\n");
+	printf("   enum: %i\n",this->enum_type);
+	printf("   %s\n",this->value);
+}
+/*}}}*/
+/*FUNCTION StringParam::Demarshall{{{1*/
+void  StringParam::Demarshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   i;
+	int   stringsize;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*this time, no need to get enum type, the pointer directly points to the beginning of the 
+	 *object data (thanks to DataSet::Demarshall):*/
+	memcpy(&enum_type,marshalled_dataset,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+
+	memcpy(&stringsize,marshalled_dataset,sizeof(int));marshalled_dataset+=sizeof(int);
+	
+	this->value=(char*)xmalloc(stringsize*sizeof(char));
+	memcpy(this->value,marshalled_dataset,stringsize*sizeof(char));marshalled_dataset+=stringsize*sizeof(char);
+
+	/*return: */
+	*pmarshalled_dataset=marshalled_dataset;
+	return;
+}
+/*}}}*/
+/*FUNCTION StringParam::Echo {{{1*/
+void StringParam::Echo(void){
+	this->DeepEcho();
+}
+/*}}}*/
+/*FUNCTION StringParam::Enum{{{1*/
+int StringParam::Enum(void){
+
+	return StringParamEnum;
+
+}
+/*}}}*/
+/*FUNCTION StringParam::Id{{{1*/
+int    StringParam::Id(void){ return -1; }
+/*}}}*/
+/*FUNCTION StringParam::Marshall{{{1*/
+void  StringParam::Marshall(char** pmarshalled_dataset){
+
+	char* marshalled_dataset=NULL;
+	int   enum_value=0;
+	int   stringsize;
+
+	/*recover marshalled_dataset: */
+	marshalled_dataset=*pmarshalled_dataset;
+
+	/*get enum value of StringParam: */
+	enum_value=StringParamEnum;
+	
+	/*marshall enum: */
+	memcpy(marshalled_dataset,&enum_value,sizeof(enum_value));marshalled_dataset+=sizeof(enum_value);
+
+	/*marshall data: */
+	memcpy(marshalled_dataset,&enum_type,sizeof(enum_type));marshalled_dataset+=sizeof(enum_type);
+	stringsize=strlen(this->value)+1;
+	
+	memcpy(marshalled_dataset,&stringsize,sizeof(stringsize));marshalled_dataset+=sizeof(stringsize);
+	memcpy(marshalled_dataset,this->value,stringsize*sizeof(char));marshalled_dataset+=stringsize*sizeof(char);
+
+	*pmarshalled_dataset=marshalled_dataset;
+}
+/*}}}*/
+/*FUNCTION StringParam::MarshallSize{{{1*/
+int   StringParam::MarshallSize(){
+
+	int stringsize;
+	stringsize=strlen(this->value)+1;
+	
+	return sizeof(value)+
+		sizeof(int)+
+		stringsize*sizeof(char)+
+		+sizeof(enum_type)+
+		+sizeof(int); //sizeof(int) for enum value
+}
+/*}}}*/
+/*FUNCTION StringParam::MyRank{{{1*/
+int    StringParam::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION StringParam::GetParameterValue(char** pstring){{{1*/
+void  StringParam::GetParameterValue(char** pstring){
+	
+	char* outstring=NULL;
+	int   stringsize;
+
+	stringsize=strlen(this->value)+1;
+
+	outstring=(char*)xmalloc(stringsize*sizeof(char));
+	memcpy(outstring,this->value,stringsize*sizeof(char));
+
+	*pstring=outstring;
+
+}
+/*}}}*/
+/*FUNCTION StringParam::GetParameterName(void); {{{1*/
+char* StringParam::GetParameterName(void){
+	return  EnumAsString(this->enum_type);
+}
+/*}}}*/
+/*FUNCTION StringParam::SetMatlabField(mxArray* dataref);{{{1*/
+void  StringParam::SetMatlabField(mxArray* dataref){
+	
+	char* name=NULL;
+
+	name=this->GetParameterName();
+	mxSetField( dataref, 0, name, mxCreateString(value));
+
+	/*Free ressources:*/
+	xfree((void**)&name);
+
+}
+/*}}}*/
Index: /issm/trunk/src/c/objects/Params/StringParam.h
===================================================================
--- /issm/trunk/src/c/objects/Params/StringParam.h	(revision 3683)
+++ /issm/trunk/src/c/objects/Params/StringParam.h	(revision 3683)
@@ -0,0 +1,57 @@
+/*! \file StringParam.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+
+#ifndef _STRINGPARAM_H_
+#define _STRINGPARAM_H_
+
+/*Headers:*/
+/*{{{1*/
+#include "./Param.h"
+#include "../../include/types.h"
+#include "../../shared/shared.h"
+#include "../../include/typedefs.h"
+#include "../../include/macros.h"
+/*}}}*/
+
+class StringParam: public Param{
+
+	private: 
+		/*just hold 3 values for 3 vertices: */
+		int enum_type;
+		char* value;
+
+	public:
+		/*constructors, destructors: {{{1*/
+		StringParam();
+		StringParam(int enum_type,char* value);
+		~StringParam();
+		/*}}}*/
+		/*Object methods: {{{1*/
+		Object* copy();
+		void  DeepEcho();
+		void  Demarshall(char** pmarshalled_dataset);
+		void  Echo();
+		int   Enum();
+		int   Id();
+		void  Marshall(char** pmarshalled_dataset);
+		int   MarshallSize();
+		int   MyRank();
+		/*}}}*/
+		/*Param methods: {{{1*/
+		int   EnumType(){return enum_type;}
+		void  GetParameterValue(bool* pbool){ISSMERROR("String param cannot return a bool");}
+		void  GetParameterValue(int* pinteger){ISSMERROR("String param cannot return an integer");}
+		void  GetParameterValue(double* pdouble){ISSMERROR("String param cannot return a double");}
+		void  GetParameterValue(char** pstring);
+		void  GetParameterValue(char*** pstringarray,int* pM){ISSMERROR("String param cannot return a string arrayl");}
+		void  GetParameterValue(double** pdoublearray,int* pM){ISSMERROR("String param cannot return a double array");}
+		void  GetParameterValue(double** pdoublearray,int* pM, int* pN){ISSMERROR("String param cannot return a double array");}
+		void  GetParameterValue(Vec* pvec){ISSMERROR("String param cannot return a Vec");}
+		void  GetParameterValue(Mat* pmat){ISSMERROR("String param cannot return a Mat");}
+		char* GetParameterName(void);
+		void  SetMatlabField(mxArray* dataref);
+		/*}}}*/
+};
+#endif  /* _STRINGPARAM_H */
