Index: /issm/trunk/src/c/objects/Tria.cpp
===================================================================
--- /issm/trunk/src/c/objects/Tria.cpp	(revision 2704)
+++ /issm/trunk/src/c/objects/Tria.cpp	(revision 2705)
@@ -24,12 +24,15 @@
 //#define _DEBUGGAUSS_
 
+/*FUNCTION Tria constructor {{{1*/
 Tria::Tria(){
 	return;
 }
-
+/*}}}*/
+/*FUNCTION Tria destructor {{{1*/
 Tria::~Tria(){
 	return;
 }
-
+/*}}}*/
+/*FUNCTION Tria creation {{{1*/
 Tria::Tria(int tria_id,int tria_mid,int tria_mparid,int tria_numparid,int tria_node_ids[3],double tria_h[3],double tria_s[3],double tria_b[3],double tria_k[3],double tria_melting[3],
 				double tria_accumulation[3],double tria_geothermalflux[3],int tria_friction_type,double tria_p,double tria_q,int tria_shelf, bool tria_onwater){
@@ -68,5 +71,6 @@
 	return;
 }
-
+/*}}}*/
+/*FUNCTION Echo {{{1*/
 #undef __FUNCT__
 #define __FUNCT__ "Tria::Echo"
@@ -104,4 +108,6 @@
 	return;
 }
+/*}}}*/
+/*FUNCTION DeepEcho{{{1*/
 #undef __FUNCT__
 #define __FUNCT__ "Tria::DeepEcho"
@@ -139,4 +145,6 @@
 	return;
 }
+/*}}}*/
+/*FUNCTION Marshall {{{1*/
 void  Tria::Marshall(char** pmarshalled_dataset){
 
@@ -184,5 +192,6 @@
 	return;
 }
-		
+/*}}}*/
+/*FUNCTION MarshallSize {{{1*/
 int   Tria::MarshallSize(){
 	return sizeof(id)
@@ -214,9 +223,11 @@
 		+sizeof(int); //sizeof(int) for enum type
 }
-
+/*}}}*/
+/*FUNCTION GetName {{{1*/
 char* Tria::GetName(void){
 	return "tria";
 }
-
+/*}}}*/
+/*FUNCTION Demarshall {{{1*/
 void  Tria::Demarshall(char** pmarshalled_dataset){
 
@@ -267,4 +278,6 @@
 	return;
 }
+/*}}}*/
+/*FUNCTION Enum {{{1*/
 int Tria::Enum(void){
 
@@ -272,12 +285,15 @@
 
 }
+/*}}}*/
+/*FUNCTION GetId {{{1*/
 int    Tria::GetId(){ return id; }
-
+/*}}}*/
+/*FUNCTION MyRank {{{1*/
 int    Tria::MyRank(void){ 
 	extern int my_rank;
 	return my_rank; 
 }
-
-
+/*}}}*/
+/*FUNCTION Configure {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::Configure"
@@ -308,5 +324,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION CreateKMatrix {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrix"
@@ -343,6 +360,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticHoriz {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrixDiagnosticHoriz"
@@ -562,4 +579,6 @@
 
 }
+/*}}}*/
+/*FUNCTION CreateKMatrixPrognostic {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrixPrognostic"
@@ -780,8 +799,9 @@
 
 }
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreatePVectorPrognostic"
-void  Tria::CreatePVectorPrognostic(Vec pg ,void* vinputs,int analysis_type,int sub_analysis_type){
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticHorizFriction {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreateKMatrixDiagnosticHorizFriction"
+void  Tria::CreateKMatrixDiagnosticHorizFriction(Mat Kgg,void* vinputs,int analysis_type,int sub_analysis_type){
 
 
@@ -791,6 +811,5 @@
 	/* node data: */
 	const int    numgrids=3;
-	const int    NDOF1=1;
-	const int    numdof=NDOF1*numgrids;
+	const int    numdof=2*numgrids;
 	double       xyz_list[numgrids][3];
 	int          doflist[numdof];
@@ -806,9 +825,466 @@
 	double  gauss_l1l2l3[3];
 
+	/* 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]; //local element stiffness matrix 
+	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  vxvy_list[numgrids][2]={{0,0},{0,0},{0,0}};
+	int     dofs[2]={0,1};
+
+	/*friction: */
+	double alpha2_list[numgrids]={0.0,0.0,0.0};
+	double alpha2;
+
+	double MAXSLOPE=.06; // 6 %
+	double MOUNTAINKEXPONENT=10;
+
+	ParameterInputs* inputs=NULL;
+
+	/*recover pointers: */
+	inputs=(ParameterInputs*)vinputs;
+	
+	/* Get node coordinates and dof list: */
+	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
+	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;
+
+	if (shelf){
+		/*no friction, do nothing*/
+		return;
+	}
+
+	if (friction_type!=2)throw ErrorException(__FUNCT__," non-viscous friction not supported yet!");
+
+	/*recover extra inputs from users, at current convergence iteration: */
+	inputs->Recover("velocity",&vxvy_list[0][0],2,dofs,numgrids,(void**)nodes);
+
+	/*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=&k[0];
+	friction->bed=&b[0];
+	friction->thickness=&h[0];
+	friction->velocities=&vxvy_list[0][0];
+	friction->p=p;
+	friction->q=q;
+
+	/*Compute alpha2_list: */
+	FrictionGetAlpha2(&alpha2_list[0],friction);
+
+	/*Erase friction object: */
+	DeleteFriction(&friction);
+
+	#ifdef _DEBUGELEMENTS_
+	if(my_rank==RANK && id==ELID){ 
+		printf("   alpha2_list [%g %g %g ]\n",alpha2_list[0],alpha2_list[1],alpha2_list[2]);
+	}
+	#endif
+
+	/* 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);
+
+	#ifdef _DEBUGELEMENTS_
+	if(my_rank==RANK && id==ELID){ 
+		printf("   gaussian points: \n");
+		for(i=0;i<num_gauss;i++){
+			printf("    %g %g %g : %g\n",first_gauss_area_coord[i],second_gauss_area_coord[i],third_gauss_area_coord[i],gauss_weights[i]);
+		}
+	}
+	#endif
+
+	/* 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: */
+		GetParameterDerivativeValue(&slope[0], &s[0],&xyz_list[0][0], gauss_l1l2l3);
+		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 CreateKMatrixSlopeCompute {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreateKMatrixSlopeCompute"
+
+void  Tria::CreateKMatrixSlopeCompute(Mat Kgg,void* vinputs,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]; //local element stiffness matrix 
+	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
+	
+	double Jdet;
+	
+	/* Get node coordinates and dof list: */
+	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
+	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 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 CreatePVector {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreatePVector"
+void  Tria::CreatePVector(Vec pg,void* inputs,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,inputs,analysis_type,sub_analysis_type);
+	
+	}
+	else if (analysis_type==DiagnosticAnalysisEnum()){
+		if (sub_analysis_type==HorizAnalysisEnum()){
+		
+			CreatePVectorDiagnosticHoriz( pg,inputs,analysis_type,sub_analysis_type);
+		
+		}
+		else throw ErrorException(__FUNCT__,exprintf("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet"));
+	}
+	else if (analysis_type==SlopeComputeAnalysisEnum()){
+		
+		CreatePVectorSlopeCompute( pg,inputs,analysis_type,sub_analysis_type);
+	}
+	else if (analysis_type==PrognosticAnalysisEnum()){
+
+		CreatePVectorPrognostic( pg,inputs,analysis_type,sub_analysis_type);
+	}
+	else{
+		throw ErrorException(__FUNCT__,exprintf("%s%i%s"," analysis ",analysis_type," not supported yet"));
+	}
+
+}
+/*}}}*/
+/*FUNCTION CreatePVectorDiagnosticHoriz {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreatePVectorDiagnosticHoriz"
+void Tria::CreatePVectorDiagnosticHoriz( Vec pg, void* vinputs, 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];
+	double  pe_g_gaussian[numdof];
+
+	/*input parameters for structural analysis (diagnostic): */
+	double  thickness;
+
+	ParameterInputs* inputs=NULL;
+
+	/*First, if we are on water, return empty vector: */
+	if(onwater)return;
+
+	/*recover pointers: */
+	inputs=(ParameterInputs*)vinputs;
+
+	/* Get node coordinates and dof list: */
+	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
+	GetDofList(&doflist[0],&numberofdofspernode);
+
+	/* Set pe_g to 0: */
+	for(i=0;i<numdof;i++) pe_g[i]=0.0;
+
+
+	#ifdef _DEBUGELEMENTS_
+	if(my_rank==RANK && id==ELID){ 
+		printf("gravity %g\n",matpar->GetG());
+		printf("rho_ice %g\n",matpar->GetRhoIce());
+		printf("thickness [%g,%g,%g]\n",h[0],h[1],h[2]);
+		printf("surface[%g,%g,%g]\n",s[0],s[1],s[2]);
+		printf("bed[%g,%g,%g]\n",b[0],b[1],b[2]);
+		printf("drag [%g,%g,%g]\n",k[0],k[1],k[2]);
+	}
+	#endif
+
+
+	/* 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*/
+
+	#ifdef _DEBUGELEMENTS_
+	if(my_rank==RANK && id==ELID){ 
+		printf("   gaussian points: \n");
+		for(i=0;i<num_gauss;i++){
+			printf("    %g %g %g : %g\n",first_gauss_area_coord[i],second_gauss_area_coord[i],third_gauss_area_coord[i],gauss_weights[i]);
+		}
+	}
+	#endif
+
+
+
+	/* 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: */
+		GetParameterValue(&thickness, &h[0],gauss_l1l2l3);
+	
+		GetParameterDerivativeValue(&slope[0], &s[0],&xyz_list[0][0], gauss_l1l2l3);
+		
+		/*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the 
+		 * element itself: */
+		if(friction_type==1){
+			GetParameterValue(&plastic_stress, &k[0],gauss_l1l2l3);
+		}
+
+		/* 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;
+
+
+	 	#ifdef _DEBUGELEMENTS_
+		if(my_rank==RANK && id==ELID){ 
+			printf("      gaussian %i\n",ig);
+			printf("      thickness %g\n",thickness);
+			printf("      slope(%g,%g)\n",slope[0],slope[1]);
+			printf("      Jdet %g\n",Jdet);
+			printf("      gaussweigth %g\n",gauss_weight);
+			printf("      l1l2l3 (%g,%g,%g)\n",l1l2l3[0],l1l2l3[1],l1l2l3[2]);
+			if(friction_type==1)printf("      plastic_stress(%g)\n",plastic_stress);
+		}
+		#endif
+
+		/*Build pe_g_gaussian vector: */
+		if(friction_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++)
+
+	#ifdef _DEBUGELEMENTS_
+	if(my_rank==RANK && id==ELID){ 
+		printf("      pe_g->terms\n",ig);
+		for( i=0; i<pe_g->nrows; i++){
+			printf("%g ",*(pe_g->terms+i));
+		}
+		printf("\n");
+		printf("      pe_g->row_indices\n",ig);
+		for( i=0; i<pe_g->nrows; i++){
+			printf("%i ",*(pe_g->row_indices+i));
+		}
+	}
+	#endif
+
+	/*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 CreatePVectorPrognostic {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreatePVectorPrognostic"
+void  Tria::CreatePVectorPrognostic(Vec pg ,void* vinputs,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_list[numgrids]={0.0};
@@ -862,8 +1338,8 @@
 		GetParameterValue(&melting_g, &melting_list[0],gauss_l1l2l3);
 		GetParameterValue(&thickness_g, &thickness_list[0],gauss_l1l2l3);
-		
+
 		/* 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++)
 
@@ -871,5 +1347,5 @@
 	VecSetValues(pg,numdof,doflist,(const double*)pe_g,ADD_VALUES);
 
-	cleanup_and_return: 
+cleanup_and_return: 
 	xfree((void**)&first_gauss_area_coord);
 	xfree((void**)&second_gauss_area_coord);
@@ -878,17 +1354,17 @@
 
 }
-
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreateKMatrixDiagnosticHorizFriction"
-void  Tria::CreateKMatrixDiagnosticHorizFriction(Mat Kgg,void* vinputs,int analysis_type,int sub_analysis_type){
-
-
-	/* local declarations */
+/*}}}*/
+/*FUNCTION CreatePVectorSlopeCompute {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::CreatePVectorSlopeCompute"
+
+void Tria::CreatePVectorSlopeCompute( Vec pg, void* vinputs, int analysis_type,int sub_analysis_type){
+
 	int             i,j;
 
 	/* node data: */
 	const int    numgrids=3;
-	const int    numdof=2*numgrids;
+	const int    NDOF1=1;
+	const int    numdof=NDOF1*numgrids;
 	double       xyz_list[numgrids][3];
 	int          doflist[numdof];
@@ -904,92 +1380,33 @@
 	double  gauss_l1l2l3[3];
 
-	/* 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]; //local element stiffness matrix 
-	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix contribution from drag
-	
+	/* Jacobian: */
 	double Jdet;
-	
-	/*slope: */
-	double  slope[2]={0.0,0.0};
-	double  slope_magnitude;
-
-	/*input parameters for structural analysis (diagnostic): */
-	double  vxvy_list[numgrids][2]={{0,0},{0,0},{0,0}};
-	int     dofs[2]={0,1};
-
-	/*friction: */
-	double alpha2_list[numgrids]={0.0,0.0,0.0};
-	double alpha2;
-
-	double MAXSLOPE=.06; // 6 %
-	double MOUNTAINKEXPONENT=10;
-
-	ParameterInputs* inputs=NULL;
-
-	/*recover pointers: */
-	inputs=(ParameterInputs*)vinputs;
-	
+
+	/*nodal functions: */
+	double l1l2l3[3];
+
+	/*element vector at the gaussian points: */
+	double  pe_g[numdof];
+	double  pe_g_gaussian[numdof];
+	double  param[3];
+	double  slope[2];
+
 	/* Get node coordinates and dof list: */
 	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
 	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;
-
-	if (shelf){
-		/*no friction, do nothing*/
-		return;
-	}
-
-	if (friction_type!=2)throw ErrorException(__FUNCT__," non-viscous friction not supported yet!");
-
-	/*recover extra inputs from users, at current convergence iteration: */
-	inputs->Recover("velocity",&vxvy_list[0][0],2,dofs,numgrids,(void**)nodes);
-
-	/*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=&k[0];
-	friction->bed=&b[0];
-	friction->thickness=&h[0];
-	friction->velocities=&vxvy_list[0][0];
-	friction->p=p;
-	friction->q=q;
-
-	/*Compute alpha2_list: */
-	FrictionGetAlpha2(&alpha2_list[0],friction);
-
-	/*Erase friction object: */
-	DeleteFriction(&friction);
-
-	#ifdef _DEBUGELEMENTS_
-	if(my_rank==RANK && id==ELID){ 
-		printf("   alpha2_list [%g %g %g ]\n",alpha2_list[0],alpha2_list[1],alpha2_list[2]);
-	}
-	#endif
-
-	/* 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);
-
-	#ifdef _DEBUGELEMENTS_
-	if(my_rank==RANK && id==ELID){ 
-		printf("   gaussian points: \n");
-		for(i=0;i<num_gauss;i++){
-			printf("    %g %g %g : %g\n",first_gauss_area_coord[i],second_gauss_area_coord[i],third_gauss_area_coord[i],gauss_weights[i]);
-		}
-	}
-	#endif
+	/* Set pe_g to 0: */
+	for(i=0;i<numdof;i++) pe_g[i]=0.0;
+
+	if ( (sub_analysis_type==SurfaceXAnalysisEnum()) || (sub_analysis_type==SurfaceYAnalysisEnum())){
+		for(i=0;i<numdof;i++) param[i]=s[i];
+	}
+	if ( (sub_analysis_type==BedXAnalysisEnum()) || (sub_analysis_type==BedYAnalysisEnum())){
+		for(i=0;i<numdof;i++) param[i]=b[i];
+	}
+
+	/* 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: */
@@ -1001,42 +1418,27 @@
 		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: */
-		GetParameterDerivativeValue(&slope[0], &s[0],&xyz_list[0][0], gauss_l1l2l3);
-		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);
-		}
-
+		GetParameterDerivativeValue(&slope[0], &param[0],&xyz_list[0][0], gauss_l1l2l3);
+		
 		/* 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);
+		
+		 /*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: 
@@ -1046,384 +1448,7 @@
 	xfree((void**)&gauss_weights);
 
-}	
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreateKMatrixSlopeCompute"
-
-void  Tria::CreateKMatrixSlopeCompute(Mat Kgg,void* vinputs,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]; //local element stiffness matrix 
-	double Ke_gg_gaussian[numdof][numdof]; //stiffness matrix evaluated at the gaussian point.
-	
-	double Jdet;
-	
-	/* Get node coordinates and dof list: */
-	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
-	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 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);
-}
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreatePVector"
-void  Tria::CreatePVector(Vec pg,void* inputs,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,inputs,analysis_type,sub_analysis_type);
-	
-	}
-	else if (analysis_type==DiagnosticAnalysisEnum()){
-		if (sub_analysis_type==HorizAnalysisEnum()){
-		
-			CreatePVectorDiagnosticHoriz( pg,inputs,analysis_type,sub_analysis_type);
-		
-		}
-		else throw ErrorException(__FUNCT__,exprintf("%s%i%s\n","sub_analysis: ",sub_analysis_type," not supported yet"));
-	}
-	else if (analysis_type==SlopeComputeAnalysisEnum()){
-		
-		CreatePVectorSlopeCompute( pg,inputs,analysis_type,sub_analysis_type);
-	}
-	else if (analysis_type==PrognosticAnalysisEnum()){
-
-		CreatePVectorPrognostic( pg,inputs,analysis_type,sub_analysis_type);
-	}
-	else{
-		throw ErrorException(__FUNCT__,exprintf("%s%i%s"," analysis ",analysis_type," not supported yet"));
-	}
-
-}
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreatePVectorDiagnosticHoriz"
-void Tria::CreatePVectorDiagnosticHoriz( Vec pg, void* vinputs, 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];
-	double  pe_g_gaussian[numdof];
-
-	/*input parameters for structural analysis (diagnostic): */
-	double  thickness;
-
-	ParameterInputs* inputs=NULL;
-
-	/*First, if we are on water, return empty vector: */
-	if(onwater)return;
-
-	/*recover pointers: */
-	inputs=(ParameterInputs*)vinputs;
-
-	/* Get node coordinates and dof list: */
-	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
-	GetDofList(&doflist[0],&numberofdofspernode);
-
-	/* Set pe_g to 0: */
-	for(i=0;i<numdof;i++) pe_g[i]=0.0;
-
-
-	#ifdef _DEBUGELEMENTS_
-	if(my_rank==RANK && id==ELID){ 
-		printf("gravity %g\n",matpar->GetG());
-		printf("rho_ice %g\n",matpar->GetRhoIce());
-		printf("thickness [%g,%g,%g]\n",h[0],h[1],h[2]);
-		printf("surface[%g,%g,%g]\n",s[0],s[1],s[2]);
-		printf("bed[%g,%g,%g]\n",b[0],b[1],b[2]);
-		printf("drag [%g,%g,%g]\n",k[0],k[1],k[2]);
-	}
-	#endif
-
-
-	/* 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*/
-
-	#ifdef _DEBUGELEMENTS_
-	if(my_rank==RANK && id==ELID){ 
-		printf("   gaussian points: \n");
-		for(i=0;i<num_gauss;i++){
-			printf("    %g %g %g : %g\n",first_gauss_area_coord[i],second_gauss_area_coord[i],third_gauss_area_coord[i],gauss_weights[i]);
-		}
-	}
-	#endif
-
-
-
-	/* 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: */
-		GetParameterValue(&thickness, &h[0],gauss_l1l2l3);
-	
-		GetParameterDerivativeValue(&slope[0], &s[0],&xyz_list[0][0], gauss_l1l2l3);
-		
-		/*In case we have plastic basal drag, compute plastic stress at gaussian point from k1, k2 and k3 fields in the 
-		 * element itself: */
-		if(friction_type==1){
-			GetParameterValue(&plastic_stress, &k[0],gauss_l1l2l3);
-		}
-
-		/* 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;
-
-
-	 	#ifdef _DEBUGELEMENTS_
-		if(my_rank==RANK && id==ELID){ 
-			printf("      gaussian %i\n",ig);
-			printf("      thickness %g\n",thickness);
-			printf("      slope(%g,%g)\n",slope[0],slope[1]);
-			printf("      Jdet %g\n",Jdet);
-			printf("      gaussweigth %g\n",gauss_weight);
-			printf("      l1l2l3 (%g,%g,%g)\n",l1l2l3[0],l1l2l3[1],l1l2l3[2]);
-			if(friction_type==1)printf("      plastic_stress(%g)\n",plastic_stress);
-		}
-		#endif
-
-		/*Build pe_g_gaussian vector: */
-		if(friction_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++)
-
-	#ifdef _DEBUGELEMENTS_
-	if(my_rank==RANK && id==ELID){ 
-		printf("      pe_g->terms\n",ig);
-		for( i=0; i<pe_g->nrows; i++){
-			printf("%g ",*(pe_g->terms+i));
-		}
-		printf("\n");
-		printf("      pe_g->row_indices\n",ig);
-		for( i=0; i<pe_g->nrows; i++){
-			printf("%i ",*(pe_g->row_indices+i));
-		}
-	}
-	#endif
-
-	/*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);
-
-}
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::CreatePVectorSlopeCompute"
-
-void Tria::CreatePVectorSlopeCompute( Vec pg, void* vinputs, 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];
-	double  pe_g_gaussian[numdof];
-	double  param[3];
-	double  slope[2];
-
-	/* Get node coordinates and dof list: */
-	GetElementNodeData( &xyz_list[0][0], nodes, numgrids);
-	GetDofList(&doflist[0],&numberofdofspernode);
-
-	/* Set pe_g to 0: */
-	for(i=0;i<numdof;i++) pe_g[i]=0.0;
-
-	if ( (sub_analysis_type==SurfaceXAnalysisEnum()) || (sub_analysis_type==SurfaceYAnalysisEnum())){
-		for(i=0;i<numdof;i++) param[i]=s[i];
-	}
-	if ( (sub_analysis_type==BedXAnalysisEnum()) || (sub_analysis_type==BedYAnalysisEnum())){
-		for(i=0;i<numdof;i++) param[i]=b[i];
-	}
-
-	/* 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);
-
-		GetParameterDerivativeValue(&slope[0], &param[0],&xyz_list[0][0], gauss_l1l2l3);
-		
-		/* 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 UpdateFromInputs {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::UpdateFromInputs"
@@ -1463,5 +1488,6 @@
 
 }
-		
+/*}}}*/
+/*FUNCTION GetDofList {{{1*/
 void  Tria::GetDofList(int* doflist,int* pnumberofdofspernode){
 
@@ -1481,5 +1507,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GetDofList1 {{{1*/
 void  Tria::GetDofList1(int* doflist){
 
@@ -1490,6 +1517,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION GetParameterValue {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetParameterValue"
@@ -1512,6 +1539,6 @@
 	*pp=p;
 }
-
-
+/*}}}*/
+/*FUNCTION GetParameterDerivativeValue {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetParameterDerivativeValue"
@@ -1537,6 +1564,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION GetStrainRate {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetStrainRate"
@@ -1558,5 +1585,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GetJacobianDeterminant2d {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetJacobianDeterminant2d" 
@@ -1584,5 +1612,6 @@
 	
 }
-
+/*}}}*/
+/*FUNCTION GetJacobianDeterminant3d {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetJacobianDeterminant3d" 
@@ -1613,5 +1642,6 @@
 	
 }
-
+/*}}}*/
+/*FUNCTION GetB {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetB"
@@ -1656,5 +1686,6 @@
 	}
 }
-
+/*}}}*/
+/*FUNCTION GetBPrime {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetBPrime"
@@ -1694,5 +1725,6 @@
 	}
 }
-
+/*}}}*/
+/*FUNCTION GetL {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetL"
@@ -1744,5 +1776,6 @@
 	}
 }
-
+/*}}}*/
+/*FUNCTION GetB_prog {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetB_prog"
@@ -1782,5 +1815,6 @@
 	}
 }
-
+/*}}}*/
+/*FUNCTION GetBPrime_prog {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetBPrime_prog"
@@ -1815,6 +1849,6 @@
 	}
 }
-
-
+/*}}}*/
+/*FUNCTION GetNodalFunctions {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetNodalFunctions"
@@ -1833,5 +1867,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivativesBasic {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetNodalFunctionsDerivativesBasic"
@@ -1867,5 +1902,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GetNodalFunctionsDerivativesParams {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetNodalFunctionsDerivativesParams"
@@ -1893,5 +1929,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GetJacobianInvert {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetJacobianInvert"
@@ -1909,5 +1946,6 @@
 		
 }
-
+/*}}}*/
+/*FUNCTION GetJacobian {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetJacobian"
@@ -1977,6 +2015,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION Du {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::Du"
@@ -2189,4 +2227,6 @@
 
 }
+/*}}}*/
+/*FUNCTION Gradj {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::Gradj"
@@ -2204,5 +2244,6 @@
 	else throw ErrorException(__FUNCT__,exprintf("%s%s","control type not supported yet: ",control_type));
 }
-
+/*}}}*/
+/*FUNCTION GradjDrag {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GradjDrag"
@@ -2423,5 +2464,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GradjDragStokes {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GradjDragStokes"
@@ -2658,5 +2700,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION SurfaceNormal{{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::SurfaceNormal"
@@ -2686,5 +2729,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION GradjB{{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GradjB"
@@ -2861,6 +2905,6 @@
 	xfree((void**)&gauss_weights);
 }
-
-
+/*}}}*/
+/*FUNCTION Misfit {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::Misfit"
@@ -3065,5 +3109,6 @@
 	return Jelem;
 }
-
+/*}}}*/
+/*FUNCTION NodeConfiguration {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::NodeConfiguration"
@@ -3078,4 +3123,6 @@
 
 }
+/*}}}*/
+/*FUNCTION MaticeConfiguration {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::MaticeConfiguration"
@@ -3084,7 +3131,8 @@
 	matice_offset=tria_matice_offset;
 }
-
-#undef __FUNCT__ 
-#define __FUNCT__ "Tria::MaticeConfiguration"
+/*}}}*/
+/*FUNCTION MatparConfiguration {{{1*/
+#undef __FUNCT__ 
+#define __FUNCT__ "Tria::MatparConfiguration"
 void  Tria::MatparConfiguration(Matpar* tria_matpar,int tria_matpar_offset){
 
@@ -3093,5 +3141,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION NumparConfiguration {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::NumparConfiguration"
@@ -3102,5 +3151,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION CreateKMatrixDiagnosticSurfaceVert {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrixDiagnosticSurfaceVert"
@@ -3229,6 +3279,6 @@
 	xfree((void**)&gauss_weights);
 }
-		
-
+/*}}}*/
+/*FUNCTION CreatePVectorDiagnosticBaseVert {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreatePVectorDiagnosticBaseVert"
@@ -3346,5 +3396,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION ComputePressure {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::ComputePressure"
@@ -3371,5 +3422,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION CreateKMatrixThermal {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrixThermal"
@@ -3472,6 +3524,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION CreateKMatrixMelting {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreateKMatrixMelting"
@@ -3558,6 +3610,6 @@
 
 }
-
-
+/*}}}*/
+/*FUNCTION CreatePVectorThermalShelf {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreatePVectorThermalShelf"
@@ -3671,4 +3723,6 @@
 
 }
+/*}}}*/
+/*FUNCTION CreatePVectorThermalSheet {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::CreatePVectorThermalSheet"
@@ -3814,5 +3868,6 @@
 
 }
-
+/*}}}*/
+/*FUNCTION MassFlux {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::MassFlux"
@@ -3885,5 +3940,6 @@
 	return mass_flux;
 }
-
+/*}}}*/
+/*FUNCTION GetArea {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetArea"
@@ -3903,5 +3959,6 @@
 	return x2*y3 - y2*x3 + x1*y2 - y1*x2 + x3*y1 - y3*x1;
 }
-
+/*}}}*/
+/*FUNCTION GetAreaCoordinate {{{1*/
 #undef __FUNCT__ 
 #define __FUNCT__ "Tria::GetAreaCoordinate"
@@ -3936,4 +3993,3 @@
 	else throw ErrorException(__FUNCT__,exprintf("%s%i%s\n"," error message: area coordinate ",which_one," done not exist!"));
 }
-
-
+/*}}}*/
