Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/Makefile
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/Makefile	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/Makefile	(revision 20176)
@@ -0,0 +1,11 @@
+all:
+		g++ vfsa_mpi.cpp  \
+			-I$(ISSM_DIR)/externalpackages/gsl/install/include \
+			-L$(ISSM_DIR)/externalpackages/gsl/install/lib -lgsl -lgslcblas \
+		   -I$(ISSM_DIR)/externalpackages/mpich/install/include/ \
+		   -L$(ISSM_DIR)/externalpackages/mpich/install/lib/ -lmpich -lpmpich -lmpl -o forward.exe 
+
+forward:
+	   mpirun -np 4 ./forward.exe
+clean:
+		rm ./forward.exe
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/Makefile
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/Makefile	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/Makefile	(revision 20176)
@@ -0,0 +1,11 @@
+all:
+		g++ density_rock_uneven.cpp  \
+			-I$(ISSM_DIR)/externalpackages/gsl/install/include \
+			-L$(ISSM_DIR)/externalpackages/gsl/install/lib -lgsl -lgslcblas \
+		   -I$(ISSM_DIR)/externalpackages/mpich/install/include/ \
+		   -L$(ISSM_DIR)/externalpackages/mpich/install/lib/ -lmpich -lpmpich -lmpl -o forward.exe 
+
+forward:
+	   mpirun -np 4 ./forward.exe
+run -np 4 ./forward.execlean:
+		rm ./forward.exe
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock.cpp	(revision 20176)
@@ -0,0 +1,510 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include "mpi.h"
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N]();
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel);
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+/*}}}*/
+
+int main(int argc,char *argv[]){/*{{{*/
+
+	int my_rank,num_procs;
+
+	MPI_Init(&argc, &argv);
+
+	MPI_Comm_size(MPI_COMM_WORLD,&num_procs);
+	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
+
+	/* Define the variables {{{*/
+
+	int    dx     = 1000;   /* prism dimension in x-direction                           */
+	int    dy     = 1000;   /* prism dimension in y-direction                           */
+	int    mx     = 99;    /* number of prisms in x-direction                          */
+	int    my     = 99;    /* number of prisms in y-direction                          */
+	int    nx     = 99;    /* number of data points in x-direction                     */
+	int    ny     = 99;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+	// Pobs->Echo();
+
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* prisms positions */
+	makep(Pp,mx,my,dx,dy);
+	// Pp->Echo();
+
+	double  rhoi = 917;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+	// double  rhos = 2013;		      /* sediment density */
+
+	double rhoc_min=2000.;
+	double rhoc_max=3000.;
+
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc_min);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc_min);
+	rho2->SetValue(0,1,rhow-rhoc_min);
+
+	double dlevel=3134;         /* level of data acquisition */
+
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+	//	xobs->Echo();
+	//	yobs->Echo();
+
+
+	/*}}}*/     
+	/* load the data {{{*/
+
+
+	double inputnumber;
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("gravityraw.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+	//	gobs->Echo();
+
+
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("evalid1.txt");
+	Matrix * evalid= new Matrix(nx*ny,1);
+	for(int s=0;s<nx*ny; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+	//	evalid->Echo();
+
+	/* initial guess of the model */
+
+	ifstream file5("m0_102714contzach.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+			file5 >> inputnumber;
+			mesh_ini->SetValue(s,j,inputnumber);
+		}
+	}
+	file5.close();
+	//	mesh_ini->Echo();
+	/*}}}*/
+	/* Test {{{ */
+
+
+	double rhoc=rhoc_min;
+	double rhoc_opti=rhoc_min;
+	double E=misfit(mesh_ini,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my,my_rank,num_procs);
+	double E_opti=E;
+
+	for(int i=rhoc_min;i<rhoc_max+1;i++){
+		rhoc=i;
+		rho1->SetValue(0,2,rhoc);
+		rho2->SetValue(0,0,rhoi-rhoc);
+		rho2->SetValue(0,1,rhow-rhoc);
+
+		E=misfit(mesh_ini,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my,my_rank,num_procs);
+
+		if(E<E_opti){
+			E_opti=E;
+			rhoc_opti=rhoc;
+		}
+		if(my_rank==0){
+			cout<<rhoc<<"  "<<rhoc_opti<<"  "<<E<<"  "<<E_opti<<endl;
+		}
+	}
+
+
+
+
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete evalid;
+	delete gobs;
+
+	/*}}}*/
+
+	MPI_Finalize();
+
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(x);
+	gsl_vector_free(b);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+				m1->SetValue(i,j,m1->GetValue(i,j));
+				m2->SetValue(i,j,m2->GetValue(i,j));
+			}
+			else{
+				m1->SetValue(i,j,1e-10);
+			}
+		}
+	}
+	m1->AddNumber(dlevel);
+	m2->AddNumber(dlevel);
+}/*}}}*/
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs){/*{{{*/
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+
+	double *glocal=new double[n]();
+
+	for(int c=my_rank;c<n;c+=num_procs){
+		glocal[c]=0;
+		if(evalid->GetValue(c,0)==1){
+			for(int a=0;a<m;a++){
+				test=true;
+				xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+				xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+				if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+					xpp->SetValue(0,0,xp->GetValue(0,1));
+					xpp->SetValue(0,1,xp->GetValue(0,0));
+					xp->MatrixAbs(xpp);
+				}
+				yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+				yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+				if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+					ypp->SetValue(0,0,yp->GetValue(0,1));
+					ypp->SetValue(0,1,yp->GetValue(0,0));
+					yp->MatrixAbs(ypp);
+				}
+				P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+				if(P>dn){
+					test=false;
+					for(int i=0;i<l-1;i++){
+						gl->SetValue(0,i,0);
+					}
+				}
+				if(test==true){
+					si=1;
+					sj=1;
+					id=0;
+					for(int i=0;i<2;i++){
+						si*=-1;
+						for(int j=0;j<2;j++){
+							sj*=-1;
+							s=si*sj;
+							for(int k=0;k<l;k++){
+								R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+								Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+								U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+							}
+							id++;
+						}
+					}
+					for(int b=0;b<l-1;b++){
+						U->ExtractLine(U1,b);
+						U->ExtractLine(U2,b+1);
+						gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+					}
+				}
+				glocal[c]=glocal[c]+gg*gl->MatrixInternSum();
+			}
+		}
+	}
+
+	MPI_Allreduce(glocal,g->GetPointer(),n,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
+
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+	delete []glocal;
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(nx*ny,1);
+	Matrix* df=new Matrix(nx*ny,1);
+	Matrix* G=new Matrix(nx*ny,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	plouff(g1,Pobs,Pp,m1,rho1,dx,dy,dn,mx*my,nx*ny,4,evalid, my_rank, num_procs);
+	plouff(g2,Pobs,Pp,m2,rho2,dx,dy,dn,mx*my,nx*ny,3,evalid, my_rank, num_procs);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock_uneven.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock_uneven.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_densite/density_rock_uneven.cpp	(revision 20176)
@@ -0,0 +1,516 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include "mpi.h"
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N]();
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,Matrix *dlevel);
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,Matrix *dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+/*}}}*/
+
+int main(int argc,char *argv[]){/*{{{*/
+
+	int my_rank,num_procs;
+
+	MPI_Init(&argc, &argv);
+
+	MPI_Comm_size(MPI_COMM_WORLD,&num_procs);
+	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
+
+	/* Define the variables {{{*/
+
+	int    dx     = 1000;   /* prism dimension in x-direction                           */
+	int    dy     = 1000;   /* prism dimension in y-direction                           */
+	int    mx     = 99;    /* number of prisms in x-direction                          */
+	int    my     = 99;    /* number of prisms in y-direction                          */
+	int    nx     = 99;    /* number of data points in x-direction                     */
+	int    ny     = 99;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+	// Pobs->Echo();
+
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* prisms positions */
+	makep(Pp,mx,my,dx,dy);
+	// Pp->Echo();
+
+	double  rhoi = 917;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+	// double  rhos = 2013;		      /* sediment density */
+
+	double rhoc_min=2000.;
+	double rhoc_max=3000.;
+
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc_min);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc_min);
+	rho2->SetValue(0,1,rhow-rhoc_min);
+
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+	//	xobs->Echo();
+	//	yobs->Echo();
+
+
+	/*}}}*/     
+	/* load the data {{{*/
+
+
+	double inputnumber;
+
+	/* Levels of data acquisition */
+
+	ifstream file0("dataalti.txt");
+	Matrix * dlevel= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){
+		file0 >> inputnumber;
+		dlevel->SetValue(i,0,inputnumber);
+	}
+	file0.close();
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("gravityraw.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+	//	gobs->Echo();
+
+
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("evalid1.txt");
+	Matrix * evalid= new Matrix(nx*ny,1);
+	for(int s=0;s<nx*ny; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+	//	evalid->Echo();
+
+	/* initial guess of the model */
+
+	ifstream file5("m0_102714contzach.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+			file5 >> inputnumber;
+			mesh_ini->SetValue(s,j,inputnumber);
+		}
+	}
+	file5.close();
+	//	mesh_ini->Echo();
+	/*}}}*/
+	/* Test {{{ */
+
+
+	double rhoc=rhoc_min;
+	double rhoc_opti=rhoc_min;
+	double E=misfit(mesh_ini,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my,my_rank,num_procs);
+	double E_opti=E;
+
+	for(int i=rhoc_min;i<rhoc_max+1;i++){
+		rhoc=i;
+		rho1->SetValue(0,2,rhoc);
+		rho2->SetValue(0,0,rhoi-rhoc);
+		rho2->SetValue(0,1,rhow-rhoc);
+
+		E=misfit(mesh_ini,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my,my_rank,num_procs);
+
+		if(E<E_opti){
+			E_opti=E;
+			rhoc_opti=rhoc;
+		}
+		if(my_rank==0){
+			cout<<rhoc<<"  "<<rhoc_opti<<"  "<<E<<"  "<<E_opti<<endl;
+		}
+	}
+
+
+
+
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete evalid;
+	delete gobs;
+
+	/*}}}*/
+
+	MPI_Finalize();
+
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(x);
+	gsl_vector_free(b);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,Matrix* dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+				m1->SetValue(i,j,m1->GetValue(i,j)+dlevel->GetValue(i,1));
+				m2->SetValue(i,j,m2->GetValue(i,j)+dlevel->GetValue(i,1));
+			}
+			else{
+				m1->SetValue(i,j,1e-10+dlevel->GetValue(i,1));
+			}
+		}
+	}
+}/*}}}*/
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs){/*{{{*/
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+
+	double *glocal=new double[n]();
+
+	for(int c=my_rank;c<n;c+=num_procs){
+		glocal[c]=0;
+		if(evalid->GetValue(c,0)==1){
+			for(int a=0;a<m;a++){
+				test=true;
+				xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+				xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+				if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+					xpp->SetValue(0,0,xp->GetValue(0,1));
+					xpp->SetValue(0,1,xp->GetValue(0,0));
+					xp->MatrixAbs(xpp);
+				}
+				yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+				yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+				if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+					ypp->SetValue(0,0,yp->GetValue(0,1));
+					ypp->SetValue(0,1,yp->GetValue(0,0));
+					yp->MatrixAbs(ypp);
+				}
+				P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+				if(P>dn){
+					test=false;
+					for(int i=0;i<l-1;i++){
+						gl->SetValue(0,i,0);
+					}
+				}
+				if(test==true){
+					si=1;
+					sj=1;
+					id=0;
+					for(int i=0;i<2;i++){
+						si*=-1;
+						for(int j=0;j<2;j++){
+							sj*=-1;
+							s=si*sj;
+							for(int k=0;k<l;k++){
+								R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+								Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+								U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+							}
+							id++;
+						}
+					}
+					for(int b=0;b<l-1;b++){
+						U->ExtractLine(U1,b);
+						U->ExtractLine(U2,b+1);
+						gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+					}
+				}
+				glocal[c]=glocal[c]+gg*gl->MatrixInternSum();
+			}
+		}
+	}
+
+	MPI_Allreduce(glocal,g->GetPointer(),n,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
+
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+	delete []glocal;
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,Matrix *dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(nx*ny,1);
+	Matrix* df=new Matrix(nx*ny,1);
+	Matrix* G=new Matrix(nx*ny,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	plouff(g1,Pobs,Pp,m1,rho1,dx,dy,dn,mx*my,nx*ny,4,evalid, my_rank, num_procs);
+	plouff(g2,Pobs,Pp,m2,rho2,dx,dy,dn,mx*my,nx*ny,3,evalid, my_rank, num_procs);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi.cpp	(revision 20176)
@@ -0,0 +1,876 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include "mpi.h"
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N]();
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel);
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+double signe(double a);
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my);
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask);
+double coolshed(double T0,double k,double c,double D);
+/*}}}*/
+
+int main(int argc,char *argv[]){/*{{{*/
+	
+	int my_rank,num_procs;
+
+	MPI_Init(&argc, &argv);
+
+	MPI_Comm_size(MPI_COMM_WORLD,&num_procs);
+	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
+
+	/* Seed the random number generator {{{*/
+		srand (time(NULL));            /*}}}*/
+	/* Define the variables {{{*/
+
+	int    dx     = 1000;   /* prism dimension in x-direction                           */
+	int    dy     = 1000;   /* prism dimension in y-direction                           */
+	int    mx     = 99;    /* number of prisms in x-direction                          */
+	int    my     = 99;    /* number of prisms in y-direction                          */
+	int    nx     = 99;    /* number of data points in x-direction                     */
+	int    ny     = 99;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+	double ptval  = 100.;  /* max. amount to perturb model                             */
+	double ptval2 = 100.;
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+	// Pobs->Echo();
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* prisms positions */
+	makep(Pp,mx,my,dx,dy);
+	// Pp->Echo();
+
+	double  rhoi = 917;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+	// double  rhos = 2013;		      /* sediment density */
+	double  rhoc = 2670;          /* bedrock density */
+
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc);
+	rho2->SetValue(0,1,rhow-rhoc);
+
+	double dlevel=3134;         /* level of data acquisition */
+
+	double ctr=1;            /* parameter for filtering */
+	double sd=0.1;
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+	//	xobs->Echo();
+	//	yobs->Echo();
+
+
+	double mmax  = 1000;               /* max value for layer interfaces */
+	double mmax2 = 1000;
+	double mmax3 = 1000;
+
+	/* control parameter for temperature schedule  */
+
+	double ca=0.9;                    /* for acceptance */
+	double cm=0.5;                    /* for model perturbation */
+
+	double T0a          = 0.1;      /* initial temperature for acceptance           */
+	double T0m          = 0.9;      /* initial temperature for model perturbation   */
+	double D            = 2;        /* dimension of the model                       */
+	int    maxconsecrej = 1000;     /* max consecutive rejection                    */
+	int    maxsuccess   = 100;      /* max number of success within one temperature */
+	double T_min        = 1e-10;    /* stopping temp                                */
+	double Tred         = 1;
+	double E_min        = -1000000;
+	double E_exp        = 0.0291;   /* expected misfit                              */
+	int    maxiter      = 10000;
+	int    maxtotaliter = 1000000;
+	double Tol          = 1e-10;    /* tolerance on misfit                          */
+	int    sfreq        = 100;
+
+	/*}}}*/     
+	/* load the data {{{*/
+
+	/*landmask */
+
+	ifstream file("landmaskzach.txt");
+	Matrix * landmask= new Matrix(nx*ny,1);
+	double inputnumber;
+	for(int i=0;i<ny*nx; i++){ 
+		file >> inputnumber;
+		landmask->SetValue(i,0,inputnumber);
+	}
+	file.close();
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("gravityzach.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+	//	gobs->Echo();
+
+	/* load data about the ice thickness */
+
+	ifstream file2("icethickzach.txt");
+	Matrix * icethick= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file2 >> inputnumber;
+		icethick->SetValue(s,0,inputnumber);
+	}
+	file2.close();
+	//	icethick->Echo();
+
+	/* load the batimethry data */
+
+	ifstream file3("bathymetryzach.txt");
+	Matrix * bathy= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file3 >> inputnumber;
+		bathy->SetValue(s,0,inputnumber);
+	}
+	file3.close();
+	//	bathy->Echo();
+
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("evalidzach.txt");
+	Matrix * evalid= new Matrix(nx*ny,1);
+	for(int s=0;s<nx*ny; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+	//	evalid->Echo();
+
+	/* initial guess of the model */
+
+	ifstream file5("m0_102714contzach.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+			file5 >> inputnumber;
+			mesh_ini->SetValue(s,j,inputnumber);
+		}
+	}
+	file5.close();
+	//	mesh_ini->Echo();
+	/*}}}*/
+	/* VFSA {{{ */
+
+	/* name of the files to save results */
+	std::ofstream savefile1 ("r_zach.txt");
+	std::ofstream savefile2("m_zach.txt");
+
+	/* counters initialization */
+	int    success   = 0;
+	int    finished  = 0;
+	int    consec    = 0;
+	double Ta        = T0a;
+	double Tm        = T0m;
+	int    iterT     = 0;   /* iteration within a T      */
+	int    total     = 0;   /* total number of iteration */
+	int    totaliter = 0;
+	int    msave     = 0;
+	double E_new;
+	double E_final;
+	double dE;
+	double P;
+	double rn;
+	Matrix* m_old    = new Matrix(mx *my,3);
+	Matrix* m_min    = new Matrix(mx *my,3);
+	Matrix* m_new    = new Matrix(mx *my,3);
+	m_old->MatrixEqual(mesh_ini);
+
+	/* calculate initial misfit */
+	double E_old=misfit(m_old,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs);
+	/* record initial settings */
+	if(!my_rank){
+		savefile1 << "P     "<< "Ta    "<< "Tm    "<< "Eold  "<< "totaliter "<< "Tred   "<< endl;
+		savefile1 << "nan   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+		savefile2 << totaliter<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+		}
+		savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+	}
+	/* beginning of the loop */
+
+	while(finished==0){
+		iterT++;
+		totaliter++;
+
+		/* stop or reduce T */
+		if(iterT>=maxiter || success>maxsuccess){
+			if(Ta<T_min || total>maxtotaliter || fabs(E_old)<=Tol){
+				finished=1;
+				total+=iterT;
+				break;
+			}
+			else{ /* reduce T */
+				Ta=coolshed(T0a,Tred,ca,D);
+				Tm=coolshed(T0m,Tred,cm,D);
+				total+=iterT;
+				iterT=0;
+				success=1;
+				Tred++;
+				consec=0;
+			}
+		}
+
+		/* update model and calculate energy */
+
+		newmodelgen(m_old,m_new,bathy,icethick,mx,my,Tm,ptval,mmax,mmax2,ctr,sd, landmask);  /* new model */
+		E_new=misfit(m_new,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs); /* new energy */
+		dE=E_new-E_old;                                        /* energy difference */
+
+		/* acceptance probability */
+
+		P=exp(-dE/Ta);
+
+		/* stop if energy is lower than specified minimum */
+		if (E_new<E_min){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			break;
+		}
+
+		rn=rand()/double (RAND_MAX);
+
+		/* accept new model or not */
+		if(dE<=0){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			E_final=E_old;
+			success++;
+			consec=0;
+			if(!my_rank){
+				savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+			}
+			if(Ta<1e-3){
+				if(!my_rank){
+					savefile2 << totaliter<< endl;
+					for(int i=0;i<mx*my;i++){
+						savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+					}
+					savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+				}
+			}
+		}
+		else{
+			if(P>rn){
+				m_old->MatrixEqual(m_new);
+				E_old=E_new;
+				success++;
+				consec=0;
+				if(!my_rank){
+					savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+					if(Ta<1e-3){
+						savefile2 << totaliter<< endl;
+						for(int i=0;i<mx*my;i++){
+							savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+						}
+						savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+					}
+				}
+			}
+			else{
+				consec++;
+			}
+		}
+	}
+
+	m_min->MatrixEqual(m_old);
+	if(!my_rank){
+		savefile1 << "nan"<<"   "<<  "nan"<<"   "<< "nan"<<"   "<< E_final<<"     "<< "nan"<<"         "<< "nan" <<"  "<< endl;
+		savefile2 << " Mesh final"<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_min->GetValue(i,0)<<"   "<< m_min->GetValue(i,1)<<"   "<< m_min->GetValue(i,2)<<endl;
+		}
+	}
+	savefile1.close();
+	savefile2.close();
+
+	delete m_old;
+	delete m_min;
+	delete m_new;
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete bathy;
+	delete icethick;
+	delete evalid;
+	delete gobs;
+	delete landmask;
+
+	/*}}}*/
+
+   MPI_Finalize();
+
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(x);
+	gsl_vector_free(b);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+				m1->SetValue(i,j,m1->GetValue(i,j));
+				m2->SetValue(i,j,m2->GetValue(i,j));
+			}
+			else{
+				m1->SetValue(i,j,1e-10);
+			}
+		}
+	}
+	m1->AddNumber(dlevel);
+	m2->AddNumber(dlevel);
+}/*}}}*/
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix* evalid,int my_rank,int num_procs){/*{{{*/
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+
+	double *glocal=new double[n]();
+
+	for(int c=my_rank;c<n;c+=num_procs){
+		glocal[c]=0;
+		if(evalid->GetValue(i,0)==1){
+			for(int a=0;a<m;a++){
+				test=true;
+				xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+				xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+				if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+					xpp->SetValue(0,0,xp->GetValue(0,1));
+					xpp->SetValue(0,1,xp->GetValue(0,0));
+					xp->MatrixAbs(xpp);
+				}
+				yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+				yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+				if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+					ypp->SetValue(0,0,yp->GetValue(0,1));
+					ypp->SetValue(0,1,yp->GetValue(0,0));
+					yp->MatrixAbs(ypp);
+				}
+				P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+				if(P>dn){
+					test=false;
+					for(int i=0;i<l-1;i++){
+						gl->SetValue(0,i,0);
+					}
+				}
+				if(test==true){
+					si=1;
+					sj=1;
+					id=0;
+					for(int i=0;i<2;i++){
+						si*=-1;
+						for(int j=0;j<2;j++){
+							sj*=-1;
+							s=si*sj;
+							for(int k=0;k<l;k++){
+								R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+								Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+								U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+							}
+							id++;
+						}
+					}
+					for(int b=0;b<l-1;b++){
+						U->ExtractLine(U1,b);
+						U->ExtractLine(U2,b+1);
+						gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+					}
+				}
+				glocal[c]=glocal[c]+gg*gl->MatrixInternSum();
+			}
+		}
+	}
+
+	MPI_Allreduce(glocal,g->GetPointer(),n,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
+
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+	delete []glocal;
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(nx*ny,1);
+	Matrix* df=new Matrix(nx*ny,1);
+	Matrix* G=new Matrix(nx*ny,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	plouff(g1,Pobs,Pp,m1,rho1,dx,dy,dn,mx*my,nx*ny,4,evalid, my_rank, num_procs);
+	plouff(g2,Pobs,Pp,m2,rho2,dx,dy,dn,mx*my,nx*ny,3,evalid, my_rank, num_procs);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask){/*{{{*/
+	Matrix* m1gr=new Matrix(my,mx);
+	Matrix* m1grsm=new Matrix(my,mx);
+	Matrix* m1col=new Matrix(mx*my,1);
+	Matrix* m1gr2=new Matrix(my,mx);
+	Matrix* m1grsm2=new Matrix(my,mx);
+	Matrix* m1col2=new Matrix(mx*my,1);
+	Matrix* nptflag= new Matrix(mx*my,1);
+	double u=0;
+	double y=0;
+	m1->MatrixEqual(m0);
+	nptflag->MatrixSum(icethick,bathy);
+	/* first layer: ice */
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+					m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,2)>=m1->GetValue(i,0)+mmax2){
+					m1->SetValue(i,2,m1->GetValue(i,0)+mmax2);
+				}
+			}
+		}
+		else if(landmask->GetValue(i,0)==3){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+					m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+				}
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+				if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+					m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+				}
+			}
+		}
+	}
+
+	m1->ExtractColumn(m1col,1);
+	vec2gridsimple(m1col,m1gr,mx,my);
+	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+	reshape(m1grsm,m1col,mx,my);
+	m1->ExtractColumn(m1col2,2);
+	vec2gridsimple(m1col2,m1gr2,mx,my);
+	filtergrav(m1grsm2,m1gr2,ctr,sd,mx,my);
+	reshape(m1grsm2,m1col2,mx,my);
+
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,1,m1col->GetValue(i,0));
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,2)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else if(landmask->GetValue(i,0)==3){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,1,m1col->GetValue(i,0));
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else {
+			if(nptflag->GetValue(i,0)==0){
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0));
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,2))>1){
+					m1->SetValue(i,2,m1->GetValue(i,0));
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+	}
+
+				/* second layer: water */
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			u=double (rand())/ double(RAND_MAX);
+//			y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+//			m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+//			if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//			}
+//			if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+//			}
+//		}
+//	}
+//	m1->ExtractColumn(m1col,2);
+//	vec2gridsimple(m1col,m1gr,mx,my);
+//	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+//	reshape(m1grsm,m1col,mx,my);
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			m1->SetValue(i,2,m1col->GetValue(i,0));
+//		}
+//		else{
+//			m1->SetValue(i,2,m0->GetValue(i,2));
+//		}
+//		if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//			m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//		}
+//	}
+	delete m1gr;
+	delete m1grsm;
+	delete m1col;
+	delete m1gr2;
+	delete m1grsm2;
+	delete m1col2;
+	delete nptflag;
+}/*}}}*/
+double signe(double a){/*{{{*/
+	if(a<0){return -1;}
+	else{return 1;}
+}/*}}}*/
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my){/*{{{*/
+	A->MatrixEqual(Ain);
+	for (int i=1;i<my-1;i++){
+		for(int j=1;j<mx-1;j++){
+			A->SetValue(i,j,(ctr*Ain->GetValue(i,j)+sd*(Ain->GetValue(i-1,j)+Ain->GetValue(i+1,j)+Ain->GetValue(i,j-1)+Ain->GetValue(i,j+1)))/(ctr+4*sd));
+		}
+	}
+}/*}}}*/
+double coolshed(double T0,double k,double c,double D){/*{{{*/
+	double T1=T0*exp(-c*pow(k,1/D));
+	return T1;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi_uneven.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi_uneven.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/code_inversion/vfsa_mpi_uneven.cpp	(revision 20176)
@@ -0,0 +1,882 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include "mpi.h"
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N]();
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,Matrix *dlevel);
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix *evalid,int my_rank,int num_procs);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,Matrix *dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+double signe(double a);
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my);
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask);
+double coolshed(double T0,double k,double c,double D);
+/*}}}*/
+
+int main(int argc,char *argv[]){/*{{{*/
+	
+	int my_rank,num_procs;
+
+	MPI_Init(&argc, &argv);
+
+	MPI_Comm_size(MPI_COMM_WORLD,&num_procs);
+	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
+
+	/* Seed the random number generator {{{*/
+		srand (time(NULL));            /*}}}*/
+	/* Define the variables {{{*/
+
+	int    dx     = 1000;   /* prism dimension in x-direction                           */
+	int    dy     = 1000;   /* prism dimension in y-direction                           */
+	int    mx     = 99;    /* number of prisms in x-direction                          */
+	int    my     = 99;    /* number of prisms in y-direction                          */
+	int    nx     = 99;    /* number of data points in x-direction                     */
+	int    ny     = 99;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+	double ptval  = 100.;  /* max. amount to perturb model                             */
+	double ptval2 = 100.;
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+	// Pobs->Echo();
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* prisms positions */
+	makep(Pp,mx,my,dx,dy);
+	// Pp->Echo();
+
+	double  rhoi = 917;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+	// double  rhos = 2013;		      /* sediment density */
+	double  rhoc = 2670;          /* bedrock density */
+
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc);
+	rho2->SetValue(0,1,rhow-rhoc);
+
+	double ctr=1;            /* parameter for filtering */
+	double sd=0.1;
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+	//	xobs->Echo();
+	//	yobs->Echo();
+
+
+	double mmax  = 1000;               /* max value for layer interfaces */
+	double mmax2 = 1000;
+	double mmax3 = 1000;
+
+	/* control parameter for temperature schedule  */
+
+	double ca=0.9;                    /* for acceptance */
+	double cm=0.5;                    /* for model perturbation */
+
+	double T0a          = 0.1;      /* initial temperature for acceptance           */
+	double T0m          = 0.9;      /* initial temperature for model perturbation   */
+	double D            = 2;        /* dimension of the model                       */
+	int    maxconsecrej = 1000;     /* max consecutive rejection                    */
+	int    maxsuccess   = 100;      /* max number of success within one temperature */
+	double T_min        = 1e-10;    /* stopping temp                                */
+	double Tred         = 1;
+	double E_min        = -1000000;
+	double E_exp        = 0.0291;   /* expected misfit                              */
+	int    maxiter      = 10000;
+	int    maxtotaliter = 1000000;
+	double Tol          = 1e-10;    /* tolerance on misfit                          */
+	int    sfreq        = 100;
+
+	/*}}}*/     
+	/* load the data {{{*/
+
+	/*landmask */
+
+	ifstream file("landmaskzach.txt");
+	Matrix * landmask= new Matrix(nx*ny,1);
+	double inputnumber;
+	for(int i=0;i<ny*nx; i++){ 
+		file >> inputnumber;
+		landmask->SetValue(i,0,inputnumber);
+	}
+	file.close();
+
+	/* Levels of data acquisition */
+
+	ifstream file0("altizach.txt");
+	Matrix * dlevel= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){
+		file0 >> inputnumber;
+		dlevel->SetValue(i,0,inputnumber);
+	}
+	file0.close();
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("gravityzach.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+	//	gobs->Echo();
+
+	/* load data about the ice thickness */
+
+	ifstream file2("icethickzach.txt");
+	Matrix * icethick= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file2 >> inputnumber;
+		icethick->SetValue(s,0,inputnumber);
+	}
+	file2.close();
+	//	icethick->Echo();
+
+	/* load the batimethry data */
+
+	ifstream file3("bathymetryzach.txt");
+	Matrix * bathy= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file3 >> inputnumber;
+		bathy->SetValue(s,0,inputnumber);
+	}
+	file3.close();
+	//	bathy->Echo();
+
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("evalidzach.txt");
+	Matrix * evalid= new Matrix(nx*ny,1);
+	for(int s=0;s<nx*ny; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+	//	evalid->Echo();
+
+	/* initial guess of the model */
+
+	ifstream file5("m0_102714contzach.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+			file5 >> inputnumber;
+			mesh_ini->SetValue(s,j,inputnumber);
+		}
+	}
+	file5.close();
+	//	mesh_ini->Echo();
+	/*}}}*/
+	/* VFSA {{{ */
+
+	/* name of the files to save results */
+	std::ofstream savefile1 ("r_zach.txt");
+	std::ofstream savefile2("m_zach.txt");
+
+	/* counters initialization */
+	int    success   = 0;
+	int    finished  = 0;
+	int    consec    = 0;
+	double Ta        = T0a;
+	double Tm        = T0m;
+	int    iterT     = 0;   /* iteration within a T      */
+	int    total     = 0;   /* total number of iteration */
+	int    totaliter = 0;
+	int    msave     = 0;
+	double E_new;
+	double E_final;
+	double dE;
+	double P;
+	double rn;
+	Matrix* m_old    = new Matrix(mx *my,3);
+	Matrix* m_min    = new Matrix(mx *my,3);
+	Matrix* m_new    = new Matrix(mx *my,3);
+	m_old->MatrixEqual(mesh_ini);
+
+	/* calculate initial misfit */
+	double E_old=misfit(m_old,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs);
+	/* record initial settings */
+	if(!my_rank){
+		savefile1 << "P     "<< "Ta    "<< "Tm    "<< "Eold  "<< "totaliter "<< "Tred   "<< endl;
+		savefile1 << "nan   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+		savefile2 << totaliter<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+		}
+		savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+	}
+	/* beginning of the loop */
+
+	while(finished==0){
+		iterT++;
+		totaliter++;
+
+		/* stop or reduce T */
+		if(iterT>=maxiter || success>maxsuccess){
+			if(Ta<T_min || total>maxtotaliter || fabs(E_old)<=Tol){
+				finished=1;
+				total+=iterT;
+				break;
+			}
+			else{ /* reduce T */
+				Ta=coolshed(T0a,Tred,ca,D);
+				Tm=coolshed(T0m,Tred,cm,D);
+				total+=iterT;
+				iterT=0;
+				success=1;
+				Tred++;
+				consec=0;
+			}
+		}
+
+		/* update model and calculate energy */
+
+		newmodelgen(m_old,m_new,bathy,icethick,mx,my,Tm,ptval,mmax,mmax2,ctr,sd, landmask);  /* new model */
+		E_new=misfit(m_new,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs); /* new energy */
+		dE=E_new-E_old;                                        /* energy difference */
+
+		/* acceptance probability */
+
+		P=exp(-dE/Ta);
+
+		/* stop if energy is lower than specified minimum */
+		if (E_new<E_min){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			break;
+		}
+
+		rn=rand()/double (RAND_MAX);
+
+		/* accept new model or not */
+		if(dE<=0){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			E_final=E_old;
+			success++;
+			consec=0;
+			if(!my_rank){
+				savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+			}
+			if(Ta<1e-3){
+				if(!my_rank){
+					savefile2 << totaliter<< endl;
+					for(int i=0;i<mx*my;i++){
+						savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+					}
+					savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+				}
+			}
+		}
+		else{
+			if(P>rn){
+				m_old->MatrixEqual(m_new);
+				E_old=E_new;
+				success++;
+				consec=0;
+				if(!my_rank){
+					savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+					if(Ta<1e-3){
+						savefile2 << totaliter<< endl;
+						for(int i=0;i<mx*my;i++){
+							savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+						}
+						savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+					}
+				}
+			}
+			else{
+				consec++;
+			}
+		}
+	}
+
+	m_min->MatrixEqual(m_old);
+	if(!my_rank){
+		savefile1 << "nan"<<"   "<<  "nan"<<"   "<< "nan"<<"   "<< E_final<<"     "<< "nan"<<"         "<< "nan" <<"  "<< endl;
+		savefile2 << " Mesh final"<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_min->GetValue(i,0)<<"   "<< m_min->GetValue(i,1)<<"   "<< m_min->GetValue(i,2)<<endl;
+		}
+	}
+	savefile1.close();
+	savefile2.close();
+
+	delete m_old;
+	delete m_min;
+	delete m_new;
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete bathy;
+	delete icethick;
+	delete evalid;
+	delete gobs;
+	delete landmask;
+
+	/*}}}*/
+
+   MPI_Finalize();
+
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(x);
+	gsl_vector_free(b);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,Matrix* dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+				m1->SetValue(i,j,m1->GetValue(i,j)+dlevel->GetValue(i,1));
+				m2->SetValue(i,j,m2->GetValue(i,j)+dlevel->GetValue(i,1));
+			}
+			else{
+				m1->SetValue(i,j,1e-10+dlevel->GetValue(i,1));
+			}
+		}
+	}
+}/*}}}*/
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,Matrix* evalid,int my_rank,int num_procs){/*{{{*/
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+
+	double *glocal=new double[n]();
+
+	for(int c=my_rank;c<n;c+=num_procs){
+		glocal[c]=0;
+		if(evalid->GetValue(i,0)==1){
+			for(int a=0;a<m;a++){
+				test=true;
+				xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+				xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+				if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+					xpp->SetValue(0,0,xp->GetValue(0,1));
+					xpp->SetValue(0,1,xp->GetValue(0,0));
+					xp->MatrixAbs(xpp);
+				}
+				yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+				yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+				if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+					ypp->SetValue(0,0,yp->GetValue(0,1));
+					ypp->SetValue(0,1,yp->GetValue(0,0));
+					yp->MatrixAbs(ypp);
+				}
+				P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+				if(P>dn){
+					test=false;
+					for(int i=0;i<l-1;i++){
+						gl->SetValue(0,i,0);
+					}
+				}
+				if(test==true){
+					si=1;
+					sj=1;
+					id=0;
+					for(int i=0;i<2;i++){
+						si*=-1;
+						for(int j=0;j<2;j++){
+							sj*=-1;
+							s=si*sj;
+							for(int k=0;k<l;k++){
+								R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+								Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+								U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+							}
+							id++;
+						}
+					}
+					for(int b=0;b<l-1;b++){
+						U->ExtractLine(U1,b);
+						U->ExtractLine(U2,b+1);
+						gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+					}
+				}
+				glocal[c]=glocal[c]+gg*gl->MatrixInternSum();
+			}
+		}
+	}
+
+	MPI_Allreduce(glocal,g->GetPointer(),n,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
+
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+	delete []glocal;
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,Matrix *dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(nx*ny,1);
+	Matrix* df=new Matrix(nx*ny,1);
+	Matrix* G=new Matrix(nx*ny,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	plouff(g1,Pobs,Pp,m1,rho1,dx,dy,dn,mx*my,nx*ny,4,evalid, my_rank, num_procs);
+	plouff(g2,Pobs,Pp,m2,rho2,dx,dy,dn,mx*my,nx*ny,3,evalid, my_rank, num_procs);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask){/*{{{*/
+	Matrix* m1gr=new Matrix(my,mx);
+	Matrix* m1grsm=new Matrix(my,mx);
+	Matrix* m1col=new Matrix(mx*my,1);
+	Matrix* m1gr2=new Matrix(my,mx);
+	Matrix* m1grsm2=new Matrix(my,mx);
+	Matrix* m1col2=new Matrix(mx*my,1);
+	Matrix* nptflag= new Matrix(mx*my,1);
+	double u=0;
+	double y=0;
+	m1->MatrixEqual(m0);
+	nptflag->MatrixSum(icethick,bathy);
+	/* first layer: ice */
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+					m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,2)>=m1->GetValue(i,0)+mmax2){
+					m1->SetValue(i,2,m1->GetValue(i,0)+mmax2);
+				}
+			}
+		}
+		else if(landmask->GetValue(i,0)==3){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+					m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+				}
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+				if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+					m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+				}
+			}
+		}
+	}
+
+	m1->ExtractColumn(m1col,1);
+	vec2gridsimple(m1col,m1gr,mx,my);
+	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+	reshape(m1grsm,m1col,mx,my);
+	m1->ExtractColumn(m1col2,2);
+	vec2gridsimple(m1col2,m1gr2,mx,my);
+	filtergrav(m1grsm2,m1gr2,ctr,sd,mx,my);
+	reshape(m1grsm2,m1col2,mx,my);
+
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,1,m1col->GetValue(i,0));
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,2)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else if(landmask->GetValue(i,0)==3){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,1,m1col->GetValue(i,0));
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else {
+			if(nptflag->GetValue(i,0)==0){
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0));
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,2))>1){
+					m1->SetValue(i,2,m1->GetValue(i,0));
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+	}
+
+				/* second layer: water */
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			u=double (rand())/ double(RAND_MAX);
+//			y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+//			m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+//			if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//			}
+//			if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+//			}
+//		}
+//	}
+//	m1->ExtractColumn(m1col,2);
+//	vec2gridsimple(m1col,m1gr,mx,my);
+//	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+//	reshape(m1grsm,m1col,mx,my);
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			m1->SetValue(i,2,m1col->GetValue(i,0));
+//		}
+//		else{
+//			m1->SetValue(i,2,m0->GetValue(i,2));
+//		}
+//		if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//			m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//		}
+//	}
+	delete m1gr;
+	delete m1grsm;
+	delete m1col;
+	delete m1gr2;
+	delete m1grsm2;
+	delete m1col2;
+	delete nptflag;
+}/*}}}*/
+double signe(double a){/*{{{*/
+	if(a<0){return -1;}
+	else{return 1;}
+}/*}}}*/
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my){/*{{{*/
+	A->MatrixEqual(Ain);
+	for (int i=1;i<my-1;i++){
+		for(int j=1;j<mx-1;j++){
+			A->SetValue(i,j,(ctr*Ain->GetValue(i,j)+sd*(Ain->GetValue(i-1,j)+Ain->GetValue(i+1,j)+Ain->GetValue(i,j-1)+Ain->GetValue(i,j+1)))/(ctr+4*sd));
+		}
+	}
+}/*}}}*/
+double coolshed(double T0,double k,double c,double D){/*{{{*/
+	double T1=T0*exp(-c*pow(k,1/D));
+	return T1;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa.cpp	(revision 20176)
@@ -0,0 +1,823 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include <pthread.h>
+
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N];
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel);
+void* plouffT(void* vpthread_handle);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+double signe(double a);
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my);
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd);
+double coolshed(double T0,double k,double c,double D);
+void   LaunchThread(void* function(void*), void* usr,int num_threads);
+/*}}}*/
+
+/*Multithreading structures {{{*/
+typedef struct{
+	void* usr;
+	int   my_thread;
+	int   num_threads;
+} pthread_handle;
+
+typedef struct{
+	Matrix *g;
+	Matrix *Pobs;
+	Matrix *Pp;
+	Matrix *mesh;
+	Matrix *rho;
+	int dx;
+	int dy;
+	int dn;
+	int m;
+	int n;
+	int l;
+} AppStruct;
+/*}}}*/
+
+int main(){/*{{{*/
+
+	/* Seed the random number generator {{{*/
+	srand (time(NULL));               /*}}}*/
+	/* Define the variables {{{*/
+
+	int    dx     = 500;   /* prism dimension in x-direction                           */
+	int    dy     = 500;   /* prism dimension in y-direction                           */
+	int    mx     = 39;    /* number of prisms in x-direction                          */
+	int    my     = 60;    /* number of prisms in y-direction                          */
+	int    nx     = 39;    /* number of data points in x-direction                     */
+	int    ny     = 60;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+	double ptval  = 100.;  /* max. amount to perturb model                             */
+	double ptval2 = 100.;
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+// Pobs->Echo();
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* data positions */
+	makep(Pp,mx,my,dx,dy);
+// Pp->Echo();
+
+	double  rhoi = 890;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+// double  rhos = 2013;		      /* sediment density */
+	double  rhoc = 2670;          /* bedrock density */
+	
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc);
+	rho2->SetValue(0,1,rhow-rhoc);
+	
+	double ctr=1;            /* parameter for filtering */
+	double sd=0.1;
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+//	xobs->Echo();
+//	yobs->Echo();
+
+	double dlevel= 860;                /* mean level of data acquisition */
+
+	double mmax  = 1000;               /* max value for layer interfaces */
+	double mmax2 = 1000;
+	double mmax3 = 1000;
+
+	/* control parameter for temperature schedule  */
+
+	double ca=0.9;                    /* for acceptance */
+	double cm=0.5;                    /* for model perturbation */
+
+	double T0a          = 0.1;      /* initial temperature for acceptance           */
+	double T0m          = 0.9;      /* initial temperature for model perturbation   */
+	double D            = 2;        /* dimension of the model                       */
+	int    maxconsecrej = 1000;     /* max consecutive rejection                    */
+	int    maxsuccess   = 100;      /* max number of success within one temperature */
+	double T_min        = 1e-10;    /* stopping temp                                */
+	double Tred         = 1;
+	double E_min        = -1000000;
+	double E_exp        = 0.0291;   /* expected misfit                              */
+	int    maxiter      = 10000;
+	int    maxtotaliter = 1000000;
+	double Tol          = 1e-10;    /* tolerance on misfit                          */
+	int    sfreq        = 100;
+
+	                     /*}}}*/     
+	/* load the data {{{*/
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("store_fa500_36s.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	double inputnumber;
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+//	gobs->Echo();
+	
+	/* load data about the ice thickness */
+
+	ifstream file2("store_flag_icethick500.txt");
+	Matrix * icethick= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file2 >> inputnumber;
+		icethick->SetValue(s,0,inputnumber);
+	}
+	file2.close();
+//	icethick->Echo();
+
+	/* load the batimethry data */
+
+	ifstream file3("store_flag_bathy500.txt");
+	Matrix * bathy= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file3 >> inputnumber;
+		bathy->SetValue(s,0,inputnumber);
+	}
+	file3.close();
+//	bathy->Echo();
+	
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("store_flag_eval500.txt");
+	Matrix * evalid= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+//	evalid->Echo();
+	
+	/* initial guess of the model */
+
+	ifstream file5("m0_140114b.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+		file5 >> inputnumber;
+		mesh_ini->SetValue(s,j,inputnumber);
+	}
+	}
+	file5.close();
+//	mesh_ini->Echo();
+                           /*}}}*/
+		/* VFSA {{{ */
+
+	/* name of the files to save results */
+	std::ofstream savefile1 ("r_140114b.txt");
+	std::ofstream savefile2("m_140114b.txt");
+
+	/* counters initialization */
+	int    success   = 0;
+	int    finished  = 0;
+	int    consec    = 0;
+	double Ta        = T0a;
+	double Tm        = T0m;
+	int    iterT     = 0;   /* iteration within a T      */
+	int    total     = 0;   /* total number of iteration */
+	int    totaliter = 0;
+	int    msave     = 0;
+	double E_new;
+	double E_final;
+	double dE;
+	double P;
+	double rn;
+	Matrix* m_old    = new Matrix(mx *my,3);
+	Matrix* m_min    = new Matrix(mx *my,3);
+	Matrix* m_new    = new Matrix(mx *my,3);
+	m_old->MatrixEqual(mesh_ini);
+
+	/* calculate initial misfit */
+	double E_old=misfit(m_old,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my);
+
+	/* record initial settings */
+	savefile1 << "P     "<< "Ta    "<< "Tm    "<< "Eold  "<< "totaliter "<< "Tred   "<< endl;
+	savefile1 << "nan   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+	savefile2 << totaliter<< endl;
+	for(int i=0;i<mx*my;i++){
+		savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+	}
+	savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+
+	/* beginning of the loop */
+
+	while(finished==0){
+
+		iterT++;
+		totaliter++;
+
+		/* stop or reduce T */
+		if(iterT>=maxiter || success>maxsuccess){
+			if(Ta<T_min || total>maxtotaliter || fabs(E_old)<=Tol){
+				finished=1;
+				total+=iterT;
+				break;
+			}
+			else{ /* reduce T */
+				Ta=coolshed(T0a,Tred,ca,D);
+				Tm=coolshed(T0m,Tred,cm,D);
+				total+=iterT;
+				iterT=0;
+				success=1;
+				Tred++;
+				consec=0;
+			}
+		}
+
+		/* update model and calculate energy */
+
+		newmodelgen(m_old,m_new,bathy,icethick,mx,my,Tm,ptval,mmax,mmax2,ctr,sd);  /* new model */
+		E_new=misfit(m_new,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my); /* new energy */
+		dE=E_new-E_old;                                        /* energy difference */
+
+		/* acceptance probability */
+
+		P=exp(-dE/Ta);
+
+		/* stop if energy is lower than specified minimum */
+		if (E_new<E_min){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			break;
+		}
+
+		rn=rand()/double (RAND_MAX);
+
+		/* accept new model or not */
+		if(dE<=0){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			success++;
+			consec=0;
+			savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+			if(Ta<1e-3){
+				savefile2 << totaliter<< endl;
+				for(int i=0;i<mx*my;i++){
+					savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+				}
+				savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+			}
+		}
+		else{
+			if(P>rn){
+				m_old->MatrixEqual(m_new);
+				E_old=E_new;
+				success++;
+				consec=0;
+				savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+				if(Ta<1e-3){
+					savefile2 << totaliter<< endl;
+					for(int i=0;i<mx*my;i++){
+						savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+					}
+					savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+				}
+			}
+			else{
+				consec++;
+			}
+		}
+	cout<<totaliter<<endl;
+	}
+
+	m_min->MatrixEqual(m_old);
+	E_final=E_old;
+	savefile1 << "nan"<<"   "<<  "nan"<<"   "<< "nan"<<"   "<< E_final<<"     "<< "nan"<<"         "<< "nan" <<"  "<< endl;
+	savefile2 << " Mesh final"<< endl;
+	for(int i=0;i<mx*my;i++){
+		savefile2 << m_min->GetValue(i,0)<<"   "<< m_min->GetValue(i,1)<<"   "<< m_min->GetValue(i,2)<<endl;
+	}
+	savefile1.close();
+	savefile2.close();
+
+	delete m_old;
+	delete m_min;
+	delete m_new;
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete bathy;
+	delete icethick;
+	delete evalid;
+
+			/*}}}*/
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(b);
+	gsl_vector_free(x);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,j,1e-10);
+			}
+		}
+	}
+	m1->AddNumber(dlevel);
+	m2->AddNumber(dlevel);
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(mx*my,1);
+	Matrix* df=new Matrix(mx*my,1);
+	Matrix* G=new Matrix(mx*my,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	
+	/*Multithreaded core*/
+	int       num_threads = 8;
+	AppStruct usr;
+	usr.g = g1;
+	usr.Pobs = Pobs;
+	usr.Pp=Pp;
+	usr.mesh= m1;
+	usr.rho= rho1;
+	usr.dx=dx;
+	usr.dy=dy;
+	usr.dn=dn;
+	usr.m=mx*my;
+	usr.n=nx*ny;
+	usr.l=4;
+	LaunchThread(plouffT,(void*)&usr,num_threads);
+	usr.g = g2;
+	usr.mesh= m2;
+	usr.rho= rho2;
+	usr.l=3;
+	LaunchThread(plouffT,(void*)&usr,num_threads);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,mx,my);
+	for (int i=0;i<mx*my;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<my;i++){
+		for(int j=0;j<mx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,mx,my);
+	for (int i=0;i<mx*my;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd){/*{{{*/
+	Matrix* m1gr=new Matrix(my,mx);
+	Matrix* m1grsm=new Matrix(my,mx);
+	Matrix* m1col=new Matrix(mx*my,1);
+	double u=0;
+	double y=0;
+	m1->MatrixEqual(m0);
+	for (int i=0;i<mx*my;i++){
+		if(icethick->GetValue(i,0)==0){
+			u=double (rand())/ double(RAND_MAX);
+			y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+			m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+			if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+				m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+			}
+			if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+				m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+			}
+		}
+	}
+	m1->ExtractColumn(m1col,1);
+	vec2gridsimple(m1col,m1gr,mx,my);
+	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+	reshape(m1grsm,m1col,mx,my);
+	for (int i=0;i<mx*my;i++){
+		if(icethick->GetValue(i,0)==0){
+			m1->SetValue(i,1,m1col->GetValue(i,0));
+		}
+		else{
+			m1->SetValue(i,1,m0->GetValue(i,1));
+		}
+		if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+			m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+		}
+	}
+
+	for (int i=0;i<mx*my;i++){
+		if(bathy->GetValue(i,0)==0){
+			u=double (rand())/ double(RAND_MAX);
+			y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+			m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+			if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+			}
+			if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+				m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+			}
+		}
+	}
+	m1->ExtractColumn(m1col,2);
+	vec2gridsimple(m1col,m1gr,mx,my);
+	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+	reshape(m1grsm,m1col,mx,my);
+	for (int i=0;i<mx*my;i++){
+		if(bathy->GetValue(i,0)==0){
+			m1->SetValue(i,2,m1col->GetValue(i,0));
+		}
+		else{
+			m1->SetValue(i,2,m0->GetValue(i,2));
+		}
+		if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+			m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+		}
+	}
+	delete m1gr;
+	delete m1grsm;
+	delete m1col;
+}/*}}}*/
+double signe(double a){/*{{{*/
+	if(a<0){return -1;}
+	else{return 1;}
+}/*}}}*/
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my){/*{{{*/
+	A->MatrixEqual(Ain);
+	for (int i=1;i<my-1;i++){
+		for(int j=1;j<mx-1;j++){
+			A->SetValue(i,j,(ctr*Ain->GetValue(i,j)+sd*(Ain->GetValue(i-1,j)+Ain->GetValue(i+1,j)+Ain->GetValue(i,j-1)+Ain->GetValue(i,j+1)))/(ctr+4*sd));
+		}
+	}
+}/*}}}*/
+double coolshed(double T0,double k,double c,double D){/*{{{*/
+	double T1=T0*exp(-c*pow(k,1/D));
+	return T1;
+}/*}}}*/
+void* plouffT(void* vpthread_handle){/*{{{*/
+
+	/*recover this thread info*/
+	pthread_handle *handle = (pthread_handle*)vpthread_handle;
+	int my_thread   = handle->my_thread;
+	int num_threads = handle->num_threads;
+
+	/*Recover struct*/
+	AppStruct *usr = (AppStruct*)handle->usr;
+	Matrix *g = usr->g;
+	Matrix *Pobs = usr->Pobs;
+	Matrix *Pp = usr->Pp;
+	Matrix *mesh = usr->mesh;
+	Matrix *rho = usr->rho;
+	int dx =usr->dx;
+	int dy =usr->dy;
+	int dn =usr->dn;
+	int m =usr->m;
+	int n =usr->n;
+	int l =usr->l;
+
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+	for(int c=my_thread;c<n;c+=num_threads){
+		g->SetValue(c,0,0);
+		for(int a=0;a<m;a++){
+			test=true;
+			xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+			xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+			if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+				xpp->SetValue(0,0,xp->GetValue(0,1));
+				xpp->SetValue(0,1,xp->GetValue(0,0));
+				xp->MatrixAbs(xpp);
+			}
+			yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+			yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+			if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+				ypp->SetValue(0,0,yp->GetValue(0,1));
+				ypp->SetValue(0,1,yp->GetValue(0,0));
+				yp->MatrixAbs(ypp);
+			}
+			P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+			if(P>dn){
+				test=false;
+				for(int i=0;i<l-1;i++){
+					gl->SetValue(0,i,0);
+				}
+			}
+			if(test==true){
+				si=1;
+				sj=1;
+				id=0;
+				for(int i=0;i<2;i++){
+					si*=-1;
+					for(int j=0;j<2;j++){
+						si*=-1;
+						s=si*sj;
+						for(int k=0;k<l;k++){
+							R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+							Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+							U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+						}
+						id++;
+					}
+				}
+				for(int b=0;b<l-1;b++){
+					U->ExtractLine(U1,b);
+					U->ExtractLine(U2,b+1);
+					gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+				}
+			}
+			g->SetValue(c,0,g->GetValue(c,0)+gg*gl->MatrixInternSum());
+		}
+	}
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+
+	return NULL;
+}/*}}}*/
+void LaunchThread(void* function(void*), void* usr,int num_threads){/*{{{*/
+
+	int i;
+	int            *status  = NULL;
+	pthread_t      *threads = NULL;
+	pthread_handle *handles = NULL;
+
+	/*dynamically allocate: */
+	threads=(pthread_t*)malloc(num_threads*sizeof(pthread_t));
+	handles=(pthread_handle*)malloc(num_threads*sizeof(pthread_handle));
+
+	for(i=0;i<num_threads;i++){
+		handles[i].usr=usr;
+		handles[i].my_thread  =i;
+		handles[i].num_threads=num_threads;
+	}
+	for(i=0;i<num_threads;i++){
+		if(pthread_create(threads+i,NULL,function,(void*)(handles+i))){
+			std::cerr<<"pthread_create error";
+		}
+	}
+	for(i=0;i<num_threads;i++){
+		if(pthread_join(threads[i],(void**)&status)){
+			std::cerr<<"pthread_join error";
+		}
+	}
+
+	/*Free ressources:*/
+	delete threads;
+	delete handles;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa_mpi.cpp
===================================================================
--- /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa_mpi.cpp	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/buzzi/gravity/vfsa_mpi.cpp	(revision 20176)
@@ -0,0 +1,835 @@
+#include <iostream>
+#include <cmath>
+#include <fstream>
+#include <string>
+#include <cstdio>
+#include <cstdlib>
+#include <time.h>
+#include <cassert>
+#include <gsl/gsl_multifit.h>
+#include "mpi.h"
+using namespace std;
+
+class Matrix{/*{{{*/
+	private:
+		int     M;        /*Number of lines   */
+		int     N;        /*Number if Columns */
+		double *values;
+	public:
+		Matrix(int m_in,int n_in){/*{{{*/
+			this->M = m_in;
+			this->N = n_in;
+			this->values = new double[M*N]();
+		}/*}}}*/
+		~Matrix(){/*{{{*/
+			delete [] this->values;
+		}/*}}}*/
+		void Echo(void){/*{{{*/
+			for(int i=0;i<M;i++){
+				for(int j=0;j<N;j++){
+					cout << " " << this->values[i*N+j];
+				}
+				cout << endl;
+			}
+		}/*}}}*/
+		void SetValue(int i,int j,double value){/*{{{*/
+			this->values[i*N+j] = value;
+		}/*}}}*/
+		double GetValue(int i,int j){/*{{{*/
+			return this->values[i*N+j];
+		}/*}}}*/
+		void GetSize(int* pM,int* pN){/*{{{*/
+			*pM = this->M;
+			*pN = this->N;
+		}/*}}}*/
+		double* GetPointer(void){/*{{{*/
+			return this->values;
+		}/*}}}*/
+		void MatrixSum(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) + B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixDiff(Matrix* A,Matrix* B){/*{{{*/
+			/*Check that sizes are compatible*/
+			int M_B,N_B,M_A,N_A;
+			B->GetSize(&M_B,&N_B);
+			A->GetSize(&M_A,&N_A);
+			assert(this->M==M_B && this->N==N_B);
+			assert(this->M==M_A && this->N==N_A);
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j) - B->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		void MatrixAbs(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,fabs(A->GetValue(i,j)));
+				}
+			}
+		}/*}}}*/
+		void MatrixEqual(Matrix* A){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,A->GetValue(i,j));
+				}
+			}
+		}/*}}}*/
+		double MatrixInternSum(){/*{{{*/
+			double sum=0;
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					sum+=this->GetValue(i,j);
+				}
+			}
+			return sum;
+		}/*}}}*/
+		void ExtractLine(Matrix* A,int i){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(M_A==1 && this->N==N_A);
+			for(int j=0;j<this->N;j++){
+				A->SetValue(0,j,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void ExtractColumn(Matrix* A,int j){/*{{{*/
+			/* Check that the size of A is compatible */
+			int M_A,N_A;
+			A->GetSize(&M_A,&N_A);
+			assert(N_A==1 && this->M==M_A);
+			for(int i=0;i<this->M;i++){
+				A->SetValue(i,0,this->GetValue(i,j));
+			}
+		}/*}}}*/
+		void AddNumber(double a){/*{{{*/
+			for(int i=0;i<this->M;i++){
+				for(int j=0;j<this->N;j++){
+					this->SetValue(i,j,this->GetValue(i,j) + a);
+				}
+			}
+		}/*}}}*/
+};/*}}}*/
+
+/*Local prototypes{{{*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy);
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny);
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel);
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,int my_rank,int num_procs);
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny);
+void reshape(Matrix* V,Matrix* V1,int nx,int ny);
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs);
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B);
+double signe(double a);
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my);
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask);
+double coolshed(double T0,double k,double c,double D);
+/*}}}*/
+
+int main(int argc,char *argv[]){/*{{{*/
+	
+	int my_rank,num_procs;
+
+	MPI_Init(&argc, &argv);
+
+	MPI_Comm_size(MPI_COMM_WORLD,&num_procs);
+	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
+
+	/* Seed the random number generator {{{*/
+		srand (time(NULL));            /*}}}*/
+	/* Define the variables {{{*/
+
+	int    dx     = 1000;   /* prism dimension in x-direction                           */
+	int    dy     = 1000;   /* prism dimension in y-direction                           */
+	int    mx     = 99;    /* number of prisms in x-direction                          */
+	int    my     = 99;    /* number of prisms in y-direction                          */
+	int    nx     = 99;    /* number of data points in x-direction                     */
+	int    ny     = 99;    /* number of data points in y-direction                     */
+	int    dn     = 15000; /* distance for neighbouting prisms for gravity calculation */
+	double ptval  = 100.;  /* max. amount to perturb model                             */
+	double ptval2 = 100.;
+
+	Matrix *Pobs=new Matrix(nx*ny,2); /* data positions */
+	makep(Pobs,nx,ny,dx,dy);
+	// Pobs->Echo();
+
+
+	Matrix *Pp=new Matrix(mx*my,2); /* prisms positions */
+	makep(Pp,mx,my,dx,dy);
+	// Pp->Echo();
+
+	double  rhoi = 917;           /* ice density     */
+	double  rhow = 1030;          /* water density   */
+	// double  rhos = 2013;		      /* sediment density */
+	double  rhoc = 2670;          /* bedrock density */
+
+	Matrix *Rho  = new Matrix(1,2);
+	Rho->SetValue(0,0,rhoi);
+	Rho->SetValue(0,1,rhow);
+	Matrix *rho1  = new Matrix(1,3);
+	rho1->SetValue(0,0,rhoi);
+	rho1->SetValue(0,1,rhow);
+	rho1->SetValue(0,2,rhoc);
+	Matrix *rho2  = new Matrix(1,2);
+	rho2->SetValue(0,0,rhoi-rhoc);
+	rho2->SetValue(0,1,rhow-rhoc);
+
+	double dlevel=2400;         /* level of data acquisition */
+
+	double ctr=1;            /* parameter for filtering */
+	double sd=0.1;
+
+	Matrix *xobs= new Matrix(ny,nx);
+	Matrix *yobs= new Matrix(ny,nx);
+
+	vec2grid(Pobs,xobs,yobs,nx,ny);
+	//	xobs->Echo();
+	//	yobs->Echo();
+
+
+	double mmax  = 2000;               /* max value for layer interfaces */
+	double mmax2 = 2000;
+	double mmax3 = 2000;
+
+	/* control parameter for temperature schedule  */
+
+	double ca=0.9;                    /* for acceptance */
+	double cm=0.5;                    /* for model perturbation */
+
+	double T0a          = 0.1;      /* initial temperature for acceptance           */
+	double T0m          = 0.9;      /* initial temperature for model perturbation   */
+	double D            = 2;        /* dimension of the model                       */
+	int    maxconsecrej = 1000;     /* max consecutive rejection                    */
+	int    maxsuccess   = 100;      /* max number of success within one temperature */
+	double T_min        = 1e-10;    /* stopping temp                                */
+	double Tred         = 1;
+	double E_min        = -1000000;
+	double E_exp        = 0.0291;   /* expected misfit                              */
+	int    maxiter      = 10000;
+	int    maxtotaliter = 1000000;
+	double Tol          = 1e-10;    /* tolerance on misfit                          */
+	int    sfreq        = 100;
+
+	/*}}}*/     
+	/* load the data {{{*/
+
+	/*landmask */
+
+	ifstream file("landmaskzach.txt");
+	Matrix * landmask= new Matrix(nx*ny,1);
+	double inputnumber;
+	for(int i=0;i<ny*nx; i++){ 
+		file >> inputnumber;
+		landmask->SetValue(i,0,inputnumber);
+	}
+	file.close();
+
+	/* Observed gravity anomaly */
+
+	ifstream file1("gravityzach.txt");
+	Matrix * gobs= new Matrix(nx*ny,1);
+	for(int i=0;i<ny*nx; i++){ 
+		file1 >> inputnumber;
+		gobs->SetValue(i,0, inputnumber*1e-5);
+	}
+	file1.close();
+	//	gobs->Echo();
+
+	/* load data about the ice thickness */
+
+	ifstream file2("icethickzach.txt");
+	Matrix * icethick= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file2 >> inputnumber;
+		icethick->SetValue(s,0,inputnumber);
+	}
+	file2.close();
+	//	icethick->Echo();
+
+	/* load the batimethry data */
+
+	ifstream file3("bathymetryzach.txt");
+	Matrix * bathy= new Matrix(mx*my,1);
+	for(int s=0;s<mx*my; s++){ 
+		file3 >> inputnumber;
+		bathy->SetValue(s,0,inputnumber);
+	}
+	file3.close();
+	//	bathy->Echo();
+
+	/* id of grid to evaluate misfit */
+
+
+	ifstream file4("evalidzach.txt");
+	Matrix * evalid= new Matrix(nx*ny,1);
+	for(int s=0;s<nx*ny; s++){ 
+		file4 >> inputnumber;
+		evalid->SetValue(s,0,inputnumber);
+	}
+	file4.close();
+	//	evalid->Echo();
+
+	/* initial guess of the model */
+
+	ifstream file5("m0_092614zach.txt");
+	Matrix * mesh_ini= new Matrix(mx*my,3);
+	for(int s=0;s<mx*my; s++){ 
+		for(int j=0;j<3;j++){
+			file5 >> inputnumber;
+			mesh_ini->SetValue(s,j,inputnumber);
+		}
+	}
+	file5.close();
+	//	mesh_ini->Echo();
+	/*}}}*/
+	/* VFSA {{{ */
+
+	/* name of the files to save results */
+	std::ofstream savefile1 ("r_zach.txt");
+	std::ofstream savefile2("m_zach.txt");
+
+	/* counters initialization */
+	int    success   = 0;
+	int    finished  = 0;
+	int    consec    = 0;
+	double Ta        = T0a;
+	double Tm        = T0m;
+	int    iterT     = 0;   /* iteration within a T      */
+	int    total     = 0;   /* total number of iteration */
+	int    totaliter = 0;
+	int    msave     = 0;
+	double E_new;
+	double E_final;
+	double dE;
+	double P;
+	double rn;
+	Matrix* m_old    = new Matrix(mx *my,3);
+	Matrix* m_min    = new Matrix(mx *my,3);
+	Matrix* m_new    = new Matrix(mx *my,3);
+	m_old->MatrixEqual(mesh_ini);
+
+	/* calculate initial misfit */
+	double E_old=misfit(m_old,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs);
+	/* record initial settings */
+	if(!my_rank){
+		savefile1 << "P     "<< "Ta    "<< "Tm    "<< "Eold  "<< "totaliter "<< "Tred   "<< endl;
+		savefile1 << "nan   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+		savefile2 << totaliter<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+		}
+		savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+	}
+	/* beginning of the loop */
+
+	while(finished==0){
+		iterT++;
+		totaliter++;
+
+		/* stop or reduce T */
+		if(iterT>=maxiter || success>maxsuccess){
+			if(Ta<T_min || total>maxtotaliter || fabs(E_old)<=Tol){
+				finished=1;
+				total+=iterT;
+				break;
+			}
+			else{ /* reduce T */
+				Ta=coolshed(T0a,Tred,ca,D);
+				Tm=coolshed(T0m,Tred,cm,D);
+				total+=iterT;
+				iterT=0;
+				success=1;
+				Tred++;
+				consec=0;
+			}
+		}
+
+		/* update model and calculate energy */
+
+		newmodelgen(m_old,m_new,bathy,icethick,mx,my,Tm,ptval,mmax,mmax2,ctr,sd, landmask);  /* new model */
+		E_new=misfit(m_new,evalid,gobs,dlevel,Pobs,xobs,yobs,Pp,rho1,rho2,dx,dy,dn,nx,ny,mx,my, my_rank, num_procs); /* new energy */
+		dE=E_new-E_old;                                        /* energy difference */
+
+		/* acceptance probability */
+
+		P=exp(-dE/Ta);
+
+		/* stop if energy is lower than specified minimum */
+		if (E_new<E_min){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			break;
+		}
+
+		rn=rand()/double (RAND_MAX);
+
+		/* accept new model or not */
+		if(dE<=0){
+			m_old->MatrixEqual(m_new);
+			E_old=E_new;
+			success++;
+			consec=0;
+			if(!my_rank){
+				savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+			}
+			if(Ta<1e-3){
+				if(!my_rank){
+					savefile2 << totaliter<< endl;
+					for(int i=0;i<mx*my;i++){
+						savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+					}
+					savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+				}
+			}
+		}
+		else{
+			if(P>rn){
+				m_old->MatrixEqual(m_new);
+				E_old=E_new;
+				success++;
+				consec=0;
+				if(!my_rank){
+					savefile1 << P<<"   "<<  Ta<<"   "<< Tm<<"   "<< E_old<<"     "<< totaliter<<"         "<< Tred <<"  "<< endl;
+					if(Ta<1e-3){
+						savefile2 << totaliter<< endl;
+						for(int i=0;i<mx*my;i++){
+							savefile2 << m_old->GetValue(i,0)<<"   "<< m_old->GetValue(i,1)<<"   "<< m_old->GetValue(i,2)<<endl;
+						}
+						savefile2 << "111111111111111111111111111111111111111111111111111111111111111111111111111"<< endl;
+					}
+				}
+			}
+			else{
+				consec++;
+			}
+		}
+	}
+
+	m_min->MatrixEqual(m_old);
+	E_final=E_old;
+	if(!my_rank){
+		savefile1 << "nan"<<"   "<<  "nan"<<"   "<< "nan"<<"   "<< E_final<<"     "<< "nan"<<"         "<< "nan" <<"  "<< endl;
+		savefile2 << " Mesh final"<< endl;
+		for(int i=0;i<mx*my;i++){
+			savefile2 << m_min->GetValue(i,0)<<"   "<< m_min->GetValue(i,1)<<"   "<< m_min->GetValue(i,2)<<endl;
+		}
+	}
+	savefile1.close();
+	savefile2.close();
+
+	delete m_old;
+	delete m_min;
+	delete m_new;
+	delete Pobs;
+	delete Pp;
+	delete Rho;
+	delete rho1;
+	delete rho2;
+	delete xobs;
+	delete yobs;
+	delete mesh_ini;
+	delete bathy;
+	delete icethick;
+	delete evalid;
+
+	/*}}}*/
+
+   MPI_Finalize();
+
+	return 0;
+}/*}}}*/
+
+void GSLsquarefit(Matrix** pX,Matrix* A,Matrix* B){/*{{{*/
+
+	/*GSL Matrices and vectors: */
+	int    M,N;
+	double chisq;
+	/*Get system size*/
+	A->GetSize(&M,&N);
+
+	/*Initialize gsl matrices and vectors: */
+	gsl_matrix* a = gsl_matrix_alloc(M,N);
+	for(int i=0;i<M;i++){
+		for(int j=0;j<N;j++){
+			gsl_matrix_set (a,i,j,A->GetValue(i,j));
+		}
+	}
+	gsl_vector* b = gsl_vector_alloc(M);
+	for(int i=0;i<M;i++){
+		gsl_vector_set(b,i,B->GetValue(i,0));
+	}
+
+	gsl_vector* x = gsl_vector_alloc(N);
+	gsl_matrix* cov = gsl_matrix_alloc(N,N);
+
+	/*Least square fit: */
+	gsl_multifit_linear_workspace* work = gsl_multifit_linear_alloc(M,N);
+	gsl_multifit_linear (a, b, x, cov, &chisq, work);
+	gsl_multifit_linear_free (work);
+
+	/*Clean up and assign output pointer*/
+	Matrix* X = new Matrix(N,1);
+	for(int j=0;j<N;j++){
+		X->SetValue(j,0,gsl_vector_get(x,j));
+	}
+	*pX = X;
+
+	gsl_matrix_free(a);
+	gsl_vector_free(x);
+	gsl_vector_free(b);
+	gsl_matrix_free(cov);
+
+}/*}}}*/
+void makep(Matrix *Pobs,int nx,int ny, int dx, int dy){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			Pobs->SetValue(j+nx*i,0,j*dx);
+			Pobs->SetValue(j+nx*i,1,i*dy);
+		}
+	}
+}/*}}}*/
+void vec2grid(Matrix *V,Matrix *V1,Matrix *V2,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+			V2->SetValue(i,j, V->GetValue(j+nx*i,1));
+		}
+	}
+}/*}}}*/
+void msplit( Matrix *m, Matrix *m1,Matrix *m2,double dlevel){/*{{{*/
+	int sizem1,sizem2;
+	m->GetSize(&sizem1,&sizem2);
+	for(int i=0;i<sizem1;i++){
+		for(int j=0;j<sizem2+1;j++){
+			if(j<sizem2){
+				m1->SetValue(i,j,1e-10*(sizem2+1-j));
+				m2->SetValue(i,j,m->GetValue(i,j));
+				if(m->GetValue(i,j)<0){
+					m1->SetValue(i,j,m->GetValue(i,j));
+					m2->SetValue(i,j,i*1e-10);
+				}
+				m1->SetValue(i,j,m1->GetValue(i,j));
+				m2->SetValue(i,j,m2->GetValue(i,j));
+			}
+			else{
+				m1->SetValue(i,j,1e-10);
+			}
+		}
+	}
+	m1->AddNumber(dlevel);
+	m2->AddNumber(dlevel);
+}/*}}}*/
+void plouff(Matrix *g,Matrix *Pobs,Matrix *Pp,Matrix * mesh,Matrix *rho,int dx,int dy, int dn,int m,int n,int l,int my_rank,int num_procs){/*{{{*/
+	double gg=6.673e-11;
+	int si,sj,id,s;
+	double R,Q,P;
+	Matrix *xp= new Matrix(1,2);
+	Matrix *yp= new Matrix(1,2);
+	Matrix *xpp= new Matrix(1,2);
+	Matrix *ypp= new Matrix(1,2);
+	Matrix *U= new Matrix(l,4);
+	Matrix *U1=new Matrix(1,4);
+	Matrix *U2=new Matrix(1,4);
+	Matrix *gl= new Matrix(1,l-1);
+	bool test=true;
+
+	double *glocal=new double[n]();
+
+	for(int c=my_rank;c<n;c+=num_procs){
+		glocal[c]=0;
+		for(int a=0;a<m;a++){
+			test=true;
+			xp->SetValue(0,0,Pp->GetValue(a,0)-Pobs->GetValue(c,0));
+			xp->SetValue(0,1,Pp->GetValue(a,0)-Pobs->GetValue(c,0)+dx);
+			if(xp->GetValue(0,0)<0 && xp->GetValue(0,0)<xp->GetValue(0,1) && xp->GetValue(0,0)*xp->GetValue(0,1)>=0){
+				xpp->SetValue(0,0,xp->GetValue(0,1));
+				xpp->SetValue(0,1,xp->GetValue(0,0));
+				xp->MatrixAbs(xpp);
+			}
+			yp->SetValue(0,0,Pp->GetValue(a,1)-Pobs->GetValue(c,1));
+			yp->SetValue(0,1,Pp->GetValue(a,1)-Pobs->GetValue(c,1)+dy);
+			if(yp->GetValue(0,0)<0 && yp->GetValue(0,0)<yp->GetValue(0,1) && yp->GetValue(0,0)*yp->GetValue(0,1)>=0){
+				ypp->SetValue(0,0,yp->GetValue(0,1));
+				ypp->SetValue(0,1,yp->GetValue(0,0));
+				yp->MatrixAbs(ypp);
+			}
+			P=sqrt(xp->GetValue(0,0)*xp->GetValue(0,0)+yp->GetValue(0,0)*yp->GetValue(0,0));
+			if(P>dn){
+				test=false;
+				for(int i=0;i<l-1;i++){
+					gl->SetValue(0,i,0);
+				}
+			}
+			if(test==true){
+				si=1;
+				sj=1;
+				id=0;
+				for(int i=0;i<2;i++){
+					si*=-1;
+					for(int j=0;j<2;j++){
+						sj*=-1;
+						s=si*sj;
+						for(int k=0;k<l;k++){
+							R=sqrt(xp->GetValue(0,i)*xp->GetValue(0,i)+yp->GetValue(0,j)*yp->GetValue(0,j)+mesh->GetValue(a,k)*mesh->GetValue(a,k));
+							Q=atan(xp->GetValue(0,i)*yp->GetValue(0,j)/(mesh->GetValue(a,k)*R));
+							U->SetValue(k,id,s*(mesh->GetValue(a,k)*Q-xp->GetValue(0,i)*log(R+yp->GetValue(0,j))-yp->GetValue(0,j)*log(R+xp->GetValue(0,i))));
+						}
+						id++;
+					}
+				}
+				for(int b=0;b<l-1;b++){
+					U->ExtractLine(U1,b);
+					U->ExtractLine(U2,b+1);
+					gl->SetValue(0,b,rho->GetValue(0,b)*(U1->MatrixInternSum()*(-1)+U2->MatrixInternSum()));
+				}
+			}
+			glocal[c]=glocal[c]+gg*gl->MatrixInternSum();
+
+		}
+	}
+
+	MPI_Allreduce(glocal,g->GetPointer(),n,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
+
+	delete xp;
+	delete yp;
+	delete xpp;
+	delete ypp;
+	delete gl;
+	delete U;
+	delete U1;
+	delete U2;
+	delete []glocal;
+}/*}}}*/
+void vec2gridsimple(Matrix *V,Matrix *V1,int nx, int ny){/*{{{*/
+	for(int i=0;i<ny;i++){
+		for (int j=0;j<nx;j++){
+			V1->SetValue(i,j, V->GetValue(j+nx*i,0));
+		}
+	}
+}/*}}}*/
+void reshape(Matrix* V,Matrix* V1,int nx,int ny){/*{{{*/
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			V1->SetValue(j+nx*i,0,V->GetValue(i,j));
+		}
+	}
+}/*}}}*/
+double misfit(Matrix* m0,Matrix* evalid,Matrix* gobs,double dlevel,Matrix* Pobs,Matrix* xobs,Matrix* yobs,Matrix* Pp,Matrix* rho1, Matrix* rho2,int dx,int dy,int dn,int nx,int ny, int mx,int my,int my_rank,int num_procs){/*{{{*/
+	Matrix* m1=new Matrix(mx*my,4);
+	Matrix* m2=new Matrix(mx*my,3);
+	Matrix* g1=new Matrix(nx*ny,1);
+	Matrix* g2=new Matrix(nx*ny,1);
+	Matrix* g=new Matrix(nx*ny,1);
+	Matrix* gcalgr=new Matrix(ny,nx);
+	Matrix* gcalvec=new Matrix(nx*ny,1);
+	Matrix* df=new Matrix(nx*ny,1);
+	Matrix* G=new Matrix(nx*ny,3);
+	double a=0;
+	double b=0;
+	double e=0;
+	msplit(m0,m1,m2,dlevel);
+	plouff(g1,Pobs,Pp,m1,rho1,dx,dy,dn,mx*my,nx*ny,4, my_rank, num_procs);
+	plouff(g2,Pobs,Pp,m2,rho2,dx,dy,dn,mx*my,nx*ny,3, my_rank, num_procs);
+	g->MatrixSum(g1,g2);
+	vec2gridsimple(g,gcalgr,nx,ny);
+	reshape(gcalgr,gcalvec,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		df->SetValue(i,0,evalid->GetValue(i,0)*(gobs->GetValue(i,0)-gcalvec->GetValue(i,0)));
+		G->SetValue(i,0,evalid->GetValue(i,0)*Pobs->GetValue(i,0));
+		G->SetValue(i,1,evalid->GetValue(i,0)*Pobs->GetValue(i,1));
+		G->SetValue(i,2,evalid->GetValue(i,0));
+	}
+	Matrix* M = NULL;
+	GSLsquarefit(&M,G,df);
+
+	for (int i=0;i<ny;i++){
+		for(int j=0;j<nx;j++){
+			gcalgr->SetValue(i,j,gcalgr->GetValue(i,j)+xobs->GetValue(i,j)*M->GetValue(0,0)+yobs->GetValue(i,j)*M->GetValue(1,0)+M->GetValue(2,0));
+		}
+	}
+	reshape(gcalgr,g,nx,ny);
+	for (int i=0;i<nx*ny;i++){
+		a=a+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)-g->GetValue(i,0)));
+		b=b+fabs(evalid->GetValue(i,0)*(gobs->GetValue(i,0)+g->GetValue(i,0)));
+	}
+	e=2*a/(a+b);
+
+	delete m1;
+	delete m2;
+	delete g1;
+	delete g2;
+	delete g;
+	delete gcalgr;
+	delete gcalvec;
+	delete df;
+	delete G;
+	delete M;
+
+	return e;
+}/*}}}*/
+void newmodelgen(Matrix* m0,Matrix* m1,Matrix* bathy,Matrix* icethick,int mx,int my,double T,double ptval,double mmax,double mmax2,double ctr,double sd, Matrix *landmask){/*{{{*/
+	Matrix* m1gr=new Matrix(my,mx);
+	Matrix* m1grsm=new Matrix(my,mx);
+	Matrix* m1col=new Matrix(mx*my,1);
+	Matrix* m1gr2=new Matrix(my,mx);
+	Matrix* m1grsm2=new Matrix(my,mx);
+	Matrix* m1col2=new Matrix(mx*my,1);
+	Matrix* nptflag= new Matrix(mx*my,1);
+	double u=0;
+	double y=0;
+	m1->MatrixEqual(m0);
+	nptflag->MatrixSum(icethick,bathy);
+	/* first layer: ice */
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,1,m0->GetValue(i,1)+y*ptval);
+				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(m1->GetValue(i,1)>=m1->GetValue(i,0)+mmax){
+					m1->SetValue(i,1,m1->GetValue(i,0)+mmax);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				u=double(rand())/double(RAND_MAX);
+				y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+				m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(m1->GetValue(i,2)>=m1->GetValue(i,0)+mmax2){
+					m1->SetValue(i,2,m1->GetValue(i,0)+mmax2);
+				}
+			}
+		}
+	}
+
+	m1->ExtractColumn(m1col,1);
+	vec2gridsimple(m1col,m1gr,mx,my);
+	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+	reshape(m1grsm,m1col,mx,my);
+	m1->ExtractColumn(m1col2,2);
+	vec2gridsimple(m1col2,m1gr2,mx,my);
+	filtergrav(m1grsm2,m1gr2,ctr,sd,mx,my);
+	reshape(m1grsm2,m1col2,mx,my);
+
+	for (int i=0;i<mx*my;i++){
+		if(landmask->GetValue(i,0)==2){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,1,m1col->GetValue(i,0));
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,1)<=m1->GetValue(i,0)){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,2)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else if(landmask->GetValue(i,0)==0){
+			if(nptflag->GetValue(i,0)==0){
+				m1->SetValue(i,2,m1col2->GetValue(i,0));
+				if(m1->GetValue(i,2)<=m1->GetValue(i,0)){
+					m1->SetValue(i,2,m1->GetValue(i,0)+1e-10);
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0)+1e-10);
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+		else {
+			if(nptflag->GetValue(i,0)==0){
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,1))>1){
+					m1->SetValue(i,1,m1->GetValue(i,0));
+				}
+				if(fabs(m1->GetValue(i,0)-m1->GetValue(i,2))>1){
+					m1->SetValue(i,2,m1->GetValue(i,0));
+				}
+			}
+			else{
+				m1->SetValue(i,1,m0->GetValue(i,1));
+				m1->SetValue(i,2,m0->GetValue(i,2));
+			}
+		}
+	}
+
+				/* second layer: water */
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			u=double (rand())/ double(RAND_MAX);
+//			y=signe(u-0.5)*T*(pow(1+1/T,fabs(2*u-1))-1);
+//			m1->SetValue(i,2,m0->GetValue(i,2)+y*ptval);
+//			if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//			}
+//			if(m1->GetValue(i,2)>=m1->GetValue(i,1)+mmax2){
+//				m1->SetValue(i,2,m1->GetValue(i,1)+mmax2);
+//			}
+//		}
+//	}
+//	m1->ExtractColumn(m1col,2);
+//	vec2gridsimple(m1col,m1gr,mx,my);
+//	filtergrav(m1grsm,m1gr,ctr,sd,mx,my);
+//	reshape(m1grsm,m1col,mx,my);
+//	for (int i=0;i<mx*my;i++){
+//		if(bathy->GetValue(i,0)==0){
+//			m1->SetValue(i,2,m1col->GetValue(i,0));
+//		}
+//		else{
+//			m1->SetValue(i,2,m0->GetValue(i,2));
+//		}
+//		if(m1->GetValue(i,2)<=m1->GetValue(i,1)){
+//			m1->SetValue(i,2,m1->GetValue(i,1)+1e-10);
+//		}
+//	}
+	delete m1gr;
+	delete m1grsm;
+	delete m1col;
+	delete m1gr2;
+	delete m1grsm2;
+	delete m1col2;
+	delete nptflag;
+}/*}}}*/
+double signe(double a){/*{{{*/
+	if(a<0){return -1;}
+	else{return 1;}
+}/*}}}*/
+void filtergrav(Matrix* A,Matrix* Ain,double ctr,double sd,int mx,int my){/*{{{*/
+	A->MatrixEqual(Ain);
+	for (int i=1;i<my-1;i++){
+		for(int j=1;j<mx-1;j++){
+			A->SetValue(i,j,(ctr*Ain->GetValue(i,j)+sd*(Ain->GetValue(i-1,j)+Ain->GetValue(i+1,j)+Ain->GetValue(i,j-1)+Ain->GetValue(i,j+1)))/(ctr+4*sd));
+		}
+	}
+}/*}}}*/
+double coolshed(double T0,double k,double c,double D){/*{{{*/
+	double T1=T0*exp(-c*pow(k,1/D));
+	return T1;
+}/*}}}*/
Index: /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/ClassTry.py
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/ClassTry.py	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/ClassTry.py	(revision 20176)
@@ -0,0 +1,122 @@
+#module imports {{{
+from netCDF4 import Dataset
+import time
+import collections
+from os import path, remove
+#}}}
+
+				
+class truc(object):
+	#properties
+	def __init__(self,*filename):#{{{
+
+		def netCDFread(filename):
+			def walktree(data):
+				keys = data.groups.keys()
+				yield keys
+				for key in keys:
+					for children in walktree(data.groups[str(key)]):
+						yield children
+
+			if path.exists(filename):
+				print ('Opening {} for reading '.format(filename))
+				NCData=Dataset(filename, 'r')
+				class_dict={}
+				
+				for children in walktree(NCData):
+					for child in children:
+						class_dict[str(child)]=str(getattr(NCData.groups[str(child)],'classtype'))
+
+				return class_dict
+
+		if filename:		
+			classtype=netCDFread(filename[0])
+		else:
+			classtype=self.default_prop()
+			
+		module=map(__import__,dict.values(classtype))
+
+		for i,mod in enumerate(dict.keys(classtype)):
+			self.__dict__[mod] = getattr(module[i],str(classtype[str(mod)]))()
+			
+		#}}}
+	def default_prop(self):    # {{{
+		# ordered list of properties since vars(self) is random
+		return {'mesh':'mesh2d',\
+		        'mask':'mask',\
+		        'geometry':'geometry',\
+		        'constants':'constants',\
+		        'smb':'SMB',\
+		        'basalforcings':'basalforcings',\
+		        'materials':'matice',\
+		        'damage':'damage',\
+		        'friction':'friction',\
+		        'flowequation':'flowequation',\
+		        'timestepping':'timestepping',\
+		        'initialization':'initialization',\
+		        'rifts':'rifts',\
+		        'debug':'debug',\
+		        'verbose':'verbose',\
+		        'settings':'settings',\
+		        'toolkits':'toolkits',\
+		        'cluster':'generic',\
+		        'balancethickness':'balancethickness',\
+		        'stressbalance':'stressbalance',\
+		        'groundingline':'groundingline',\
+		        'hydrology':'hydrologyshreve',\
+		        'masstransport':'masstransport',\
+		        'thermal':'thermal',\
+		        'steadystate':'steadystate',\
+		        'transient':'transient',\
+		        'calving':'calving',\
+						'gia':'gia',\
+		        'autodiff':'autodiff',\
+		        'flaim':'flaim',\
+		        'inversion':'inversion',\
+		        'qmu':'qmu',\
+		        'outputdefinition':'outputdefinition',\
+		        'results':'results',\
+		        'radaroverlay':'radaroverlay',\
+		        'miscellaneous':'miscellaneous',\
+		        'private':'private'}
+	# }}}
+		
+	def __repr__(obj): #{{{
+		#print "Here %s the number: %d" % ("is", 37)
+		string="%19s: %-22s -- %s" % ("mesh","[%s,%s]" % ("1x1",obj.mesh.__class__.__name__),"mesh properties")
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("mask","[%s,%s]" % ("1x1",obj.mask.__class__.__name__),"defines grounded and floating elements"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("geometry","[%s,%s]" % ("1x1",obj.geometry.__class__.__name__),"surface elevation, bedrock topography, ice thickness,..."))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("constants","[%s,%s]" % ("1x1",obj.constants.__class__.__name__),"physical constants"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("smb","[%s,%s]" % ("1x1",obj.smb.__class__.__name__),"surface forcings"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("basalforcings","[%s,%s]" % ("1x1",obj.basalforcings.__class__.__name__),"bed forcings"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("materials","[%s,%s]" % ("1x1",obj.materials.__class__.__name__),"material properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("damage","[%s,%s]" % ("1x1",obj.damage.__class__.__name__),"damage propagation laws"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("friction","[%s,%s]" % ("1x1",obj.friction.__class__.__name__),"basal friction/drag properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("flowequation","[%s,%s]" % ("1x1",obj.flowequation.__class__.__name__),"flow equations"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("timestepping","[%s,%s]" % ("1x1",obj.timestepping.__class__.__name__),"time stepping for transient models"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("initialization","[%s,%s]" % ("1x1",obj.initialization.__class__.__name__),"initial guess/state"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("rifts","[%s,%s]" % ("1x1",obj.rifts.__class__.__name__),"rifts properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("debug","[%s,%s]" % ("1x1",obj.debug.__class__.__name__),"debugging tools (valgrind, gprof)"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("verbose","[%s,%s]" % ("1x1",obj.verbose.__class__.__name__),"verbosity level in solve"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("settings","[%s,%s]" % ("1x1",obj.settings.__class__.__name__),"settings properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("toolkits","[%s,%s]" % ("1x1",obj.toolkits.__class__.__name__),"PETSc options for each solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("cluster","[%s,%s]" % ("1x1",obj.cluster.__class__.__name__),"cluster parameters (number of cpus...)"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("balancethickness","[%s,%s]" % ("1x1",obj.balancethickness.__class__.__name__),"parameters for balancethickness solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("stressbalance","[%s,%s]" % ("1x1",obj.stressbalance.__class__.__name__),"parameters for stressbalance solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("groundingline","[%s,%s]" % ("1x1",obj.groundingline.__class__.__name__),"parameters for groundingline solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("hydrology","[%s,%s]" % ("1x1",obj.hydrology.__class__.__name__),"parameters for hydrology solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("masstransport","[%s,%s]" % ("1x1",obj.masstransport.__class__.__name__),"parameters for masstransport solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("thermal","[%s,%s]" % ("1x1",obj.thermal.__class__.__name__),"parameters for thermal solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("steadystate","[%s,%s]" % ("1x1",obj.steadystate.__class__.__name__),"parameters for steadystate solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("transient","[%s,%s]" % ("1x1",obj.transient.__class__.__name__),"parameters for transient solution"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("calving","[%s,%s]" % ("1x1",obj.calving.__class__.__name__),"parameters for calving"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("autodiff","[%s,%s]" % ("1x1",obj.autodiff.__class__.__name__),"automatic differentiation parameters"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("flaim","[%s,%s]" % ("1x1",obj.flaim.__class__.__name__),"flaim parameters"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("inversion","[%s,%s]" % ("1x1",obj.inversion.__class__.__name__),"parameters for inverse methods"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("qmu","[%s,%s]" % ("1x1",obj.qmu.__class__.__name__),"dakota properties"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("outputdefinition","[%s,%s]" % ("1x1",obj.outputdefinition.__class__.__name__),"output definition"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("results","[%s,%s]" % ("1x1",obj.results.__class__.__name__),"model results"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("radaroverlay","[%s,%s]" % ("1x1",obj.radaroverlay.__class__.__name__),"radar image for plot overlay"))
+		string="%s\n%s" % (string,"%19s: %-22s -- %s" % ("miscellaneous","[%s,%s]" % ("1x1",obj.miscellaneous.__class__.__name__),"miscellaneous fields"))
+		return string
+	# }}}
Index: /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.m	(revision 20176)
@@ -0,0 +1,247 @@
+function export_netCDF(md,filename)	
+	
+%Now going on Real treatment
+	if exist(filename),
+		disp(sprintf('File %s allready exist', filename));
+		prompt = 'Give a new name or "delete" to replace: ';
+		newname = input(prompt,'s');
+		if strcmp(newname,'delete')
+			delete(filename)
+		else
+			disp(sprintf('New file name is %s ', newname));
+			filename=newname
+	  end
+  end
+	%open file and write description
+	mode = netcdf.getConstant('NC_NETCDF4');
+	mode = bitor(mode,netcdf.getConstant('NC_NOCLOBBER'));%NOCLOBBER to avoid overwrite
+	ncid = netcdf.create(filename,mode);
+	netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Title',['Results for run ' md.miscellaneous.name]);
+	netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'Date',['Created ' datestr(now)]);
+	
+	%gather geometry and timestepping as dimensions
+	Duration=md.timestepping.final_time-md.timestepping.start_time;
+	if Duration>0 && md.timestepping.time_step*md.settings.output_frequency>0,
+		StepNum=Duration/(md.timestepping.time_step*md.settings.output_frequency);
+	else
+		StepNum=1;
+  end							
+ 
+	%define netcdf dimensions
+	DimSize(1).index=netcdf.defDim(ncid,'Dimension1',md.mesh.numberofelements);
+	DimSize(2).index=netcdf.defDim(ncid,'Dimension2',md.mesh.numberofvertices);
+	DimSize(3).index=netcdf.defDim(ncid,'Dimension3',size(md.mesh.elements,2));
+	DimSize(4).index=netcdf.defDim(ncid,'Dimension4',StepNum);
+	DimSize(5).index=netcdf.defDim(ncid,'Dimension5',40);
+	DimSize(6).index=netcdf.defDim(ncid,'Dimension6',2);
+	
+	for i=1:length(DimSize),
+		[DimSize(i).name,DimSize(i).value]=netcdf.inqDim(ncid,DimSize(i).index);
+		DimValue(i)=DimSize(i).value;% putting vallues in an array for
+                                 % further use
+  end
+ 
+	%Needs a first turn arround for var def
+ 
+	%get all model classes and create respective groups
+	groups=fieldnames(md);
+	for i=1:length(groups),
+		disp(sprintf('group name in tree %s ',groups{i}));
+		groupID=netcdf.defGrp(ncid,groups{i});
+		%In each group gather the fields of the class
+		groupfields=fields(md.(groups{i}));
+		%Special treatment for the results
+		if strcmp(groups(i),'results'),
+			for j=1:length(groupfields)%looping on the differents solutions
+				netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype','results');
+				subgroupID=netcdf.defGrp(groupID,groupfields{j});
+				netcdf.putAtt(subgroupID,netcdf.getConstant('NC_GLOBAL'),'classtype',groupfields{j});
+				%disp(sprintf('=====Field name in tree %s ',groupfields{j}));
+				if length(md.results.(groupfields{j}))>1,
+					%the solution have several timestep get last timesteps and output frequency
+					last_step = length(md.results.(groupfields{j}));
+					%grab first time step
+					subfields=fields(md.results.(groupfields{j})(1));
+					for k=1:length(subfields),
+						if ~strcmp(subfields(k),'errlog') && ~strcmp(subfields(k),'outlog') && ~strcmp(subfields(k),'SolutionType'),
+							%disp(sprintf('==========SubField name in tree %s ',subfields{k}));
+							Var=md.results.(groupfields{j})(1).(subfields{k});
+							[DimSize,DimValue]=DefCreateVar(ncid,Var,subgroupID,subfields{k},DimSize,DimValue,true,last_step,md,groupfields{j});
+			      end
+		      end
+				elseif length(md.results.(groupfields{j}))==1,
+					%only one timestep
+					subfields=fields(md.results.(groupfields{j}));
+					for k=1:length(subfields),
+						%disp(sprintf('==========SubField name in tree %s ',subfields{k}));
+						if ~strcmp(subfields(k),'errlog') && ~strcmp(subfields(k),'outlog') && ~strcmp(subfields(k),'SolutionType'),
+							Var=md.results.(groupfields{1})(1).(subfields{k});
+							[DimSize,DimValue]=DefCreateVar(ncid,Var,groupID,subfields{k},DimSize,DimValue,false);
+			      end
+		      end
+				else
+					print 'Result format not suported'
+		    end
+	    end
+		else
+			for j=1:length(groupfields),
+				disp(sprintf('=====Field name in tree %s ',groupfields{j}));
+				netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',class(md.(groups{i})));
+				Var=md.(groups{i}).(groupfields{j});
+				[DimSize,DimValue]=DefCreateVar(ncid,Var,groupID,groupfields{j},DimSize,DimValue,false);
+	    end
+	  end	
+  end
+	netcdf.close(ncid);
+end
+
+function [DimSize,DimValue]=DefCreateVar(ncid,Var,groupID,field,DimSize,DimValue,istime,last,md,midfield)
+	varclass=class(Var);
+	varsize=size(Var);
+	varlength=length(Var);
+	if isa(Var,'logical'),
+		if Var,
+			LogicString='True';
+		else,
+			LogicString='False';
+  	end
+		netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,LogicString);
+	elseif isa(Var,'char'),
+		netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,Var);
+	elseif isa(Var,'double'), %dealing with arrays
+		[dims,DimSize,DimValue]=GetDims(ncid,Var,groupID,field,DimSize,DimValue,istime);
+ 		varid = netcdf.defVar(groupID,field,'NC_DOUBLE',dims);
+		if istime,
+			VarTab=Var;
+			for i=2:last,
+				TimeVar=md.results.(midfield)(i).(field);
+				VarTab=[VarTab TimeVar];
+	    end
+			netcdf.putVar(groupID,varid,VarTab);
+		else
+			if length(Var)==0,
+				netcdf.putVar(groupID,varid,NaN);
+			else
+				netcdf.putVar(groupID,varid,Var);
+	    end
+	  end
+	elseif isa(Var,'cell'),
+		[dims,DimSize,DimValue]=GetDims(ncid,Var,groupID,field,DimSize,DimValue,istime);
+		%dirty hack to be able to pass strings
+		varid = netcdf.defVar(groupID,field,'NC_CHAR',dims);
+		if length(Var)==0,
+			netcdf.putVar(groupID,varid,0,9,'emptycell')
+		else
+			for i=1:length(Var),
+				startpoint=zeros(size(Var));
+				startpoint(:,i)=i-1;
+				if length(Var)>1,
+					endpoint=[min(length(Var{i}),40) 1];
+				else
+					endpoint=min(length(Var{i}),40);
+		    end
+				if length(Var{i})>40,
+					netcdf.putVar(groupID,varid,startpoint,endpoint,Var{i}(1:40))
+					disp(sprintf('some variable have been truncated'));
+			  else
+					netcdf.putVar(groupID,varid,startpoint,endpoint,Var{i})
+	      end
+	    end
+	  end
+	elseif isa(Var,'struct'),
+		%Start by getting the structure fields and size
+		locfields=fields(Var);
+		[dims,DimSize,DimValue]=GetDims(ncid,Var,groupID,locfields,DimSize,DimValue,istime);
+		varid = netcdf.defVar(groupID,field,'NC_CHAR',dims);
+		if length(locfields)==0,
+			netcdf.putVar(groupID,varid,[0,0],[11,1],'emptystruct')
+		else
+			for i=1:length(locfields),
+				for j=1:2,
+					if j==1,
+						startpoint=[0,0,i-1];
+						CharVar=locfields{i};
+					else
+						startpoint=[0,1,i-1];
+						if isa(Var.(locfields{i}),'char'),
+							CharVar=Var.(locfields{i});
+						else
+							CharVar=num2str(Var.(locfields{i}));
+			      end
+		      end
+					endpoint=[min(length(CharVar),40),1,1];
+					if length(CharVar)>40,
+						netcdf.putVar(groupID,varid,startpoint,endpoint,CharVar(1:40))
+						disp(sprintf('some variable have been truncated'));
+					else
+						netcdf.putVar(groupID,varid,startpoint,endpoint,CharVar)
+		      end
+		    end
+	    end
+		end
+	else
+		disp(sprintf('no support for class %s of field %s',varclass,field));
+  end
+	return
+end
+
+function [dims,DimSize,DimValue]=GetDims(ncid,Var,groupID,field,DimSize,DimValue,istime)
+	dims=[];
+	%specific treatment for structures
+	if isa(Var,'struct')
+		varsize=size(field); %we pass here the fields of the current structure
+		MatOrVec=varsize>1; %checking if we have a matrix (1 1) or vector (1 0)
+		for i=1:sum(MatOrVec), %loop on the number of (non 1) dimensions
+			currentdim=varsize(i);
+			dimexist=DimValue==currentdim;
+			if sum(dimexist)==0, %dimension is new to us, need to create it
+				dimname=strcat('Dimension',int2str(length(DimValue)+1));
+				dimindex=length(DimSize)+1;
+				DimSize(dimindex).index=netcdf.defDim(ncid,dimname,currentdim);
+				[DimSize(dimindex).name,DimSize(dimindex).value]=netcdf.inqDim(ncid,DimSize(dimindex).index);
+				dims(i)=DimSize(dimindex).index;
+				DimValue(dimindex)=currentdim;
+			else
+				dimindex=find(dimexist);
+				if DimSize(dimindex).value~=currentdim,
+					error('Indexation problem with the dimension structure')
+		    end
+	    end
+			dims(i)=DimSize(dimindex).index;
+	  end
+		dims=[DimSize(6).index dims];
+	else
+		%with a cell array need to grab the transposed size to work
+		if isa(Var,'cell'),
+			varsize=size(Var');
+		else
+			varsize=size(Var);
+    end
+		MatOrVec=varsize>1; %checking if we have a matrix (1 1) or vector (1 0)
+		for i=1:sum(MatOrVec), %loop on the number of (non 1) dimensions
+			currentdim=varsize(i);
+			dimexist=DimValue==currentdim;
+			if sum(dimexist)==0, %dimension is new to us, need to create it
+				dimname=strcat('Dimension',int2str(length(DimValue)+1));
+				dimindex=length(DimSize)+1;
+				DimSize(dimindex).index=netcdf.defDim(ncid,dimname,currentdim);
+				[DimSize(dimindex).name,DimSize(dimindex).value]=netcdf.inqDim(ncid,DimSize(dimindex).index);
+				dims(i)=DimSize(dimindex).index;
+				DimValue(dimindex)=currentdim;
+			else
+				dimindex=find(dimexist);
+				if DimSize(dimindex).value~=currentdim,
+					error('Indexation problem with the dimension structure')
+		    end
+	    end
+			dims(i)=DimSize(dimindex).index;
+    end
+  end
+	if istime,
+		dims=[dims DimSize(4).index];%adding the time dimension if necessary
+  end
+	%if we have a cell variable we need to add a stringlength dimension 
+	if isa(Var,'cell') || isa(Var,'struct'),
+		dims=[DimSize(5).index dims]
+  end
+end
Index: /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.py
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.py	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/export_netCDF.py	(revision 20176)
@@ -0,0 +1,218 @@
+from netCDF4 import Dataset, stringtochar
+import numpy
+import time
+import collections
+from mesh2d import *
+from mesh3dprisms import *
+from results import *
+from os import path, remove
+
+def export_netCDF(md,filename):
+	#Now going on Real treatment
+	if path.exists(filename):
+		print ('File {} allready exist'.format(filename))
+		newname=raw_input('Give a new name or "delete" to replace: ')
+		if newname=='delete':
+			remove(filename)
+		else:
+			print ('New file name is {}'.format(newname))
+			filename=newname
+			
+	NCData=Dataset(filename, 'w', format='NETCDF4')
+	NCData.description = 'Results for run' + md.miscellaneous.name
+	NCData.history = 'Created ' + time.ctime(time.time())
+
+	#gather geometry and timestepping as dimensions
+	Duration=md.timestepping.final_time-md.timestepping.start_time
+	if Duration>0 and md.timestepping.time_step*md.settings.output_frequency>0:
+		StepNum=Duration/(md.timestepping.time_step*md.settings.output_frequency)
+	else:
+		StepNum=1
+		
+	Dimension1=NCData.createDimension('Dimension1',md.mesh.numberofelements)
+	Dimension2=NCData.createDimension('Dimension2',md.mesh.numberofvertices)
+	Dimension3=NCData.createDimension('Dimension3',numpy.shape(md.mesh.elements)[1])
+	Dimension4=NCData.createDimension('Dimension4',StepNum)
+	Dimension5=NCData.createDimension('Dimension5',40)
+	Dimension6=NCData.createDimension('Dimension6',2) 
+
+	DimDict = {len(Dimension1):'Dimension1',
+						 len(Dimension2):'Dimension2',
+						 len(Dimension3):'Dimension3',
+						 len(Dimension4):'Dimension4',
+						 len(Dimension5):'Dimension5',
+						 len(Dimension6):'Dimension6'}
+
+	#get all model classes and create respective groups
+	groups=dict.keys(md.__dict__)
+	for group in groups:
+		NCgroup=NCData.createGroup(str(group))
+		#In each group gather the fields of the class
+		fields=dict.keys(md.__dict__[group].__dict__)
+
+		#Special treatment for the results
+		if str(group)=='results':
+			for supfield in fields:#looping on the different solutions
+				NCgroup.__setattr__('classtype', "results")
+				Subgroup=NCgroup.createGroup(str(supfield))
+				Subgroup.__setattr__('classtype',str(supfield))
+				if type(md.results.__dict__[supfield])==list:#the solution have several timestep
+					#get last timesteps and output frequency
+					last_step = numpy.size(md.results.__dict__[supfield])
+					step_freq = md.settings.output_frequency
+					#grab first time step
+					subfields=dict.keys(md.results.__dict__[supfield].__getitem__(0).__dict__)
+					for field in subfields:
+						if str(field)!='errlog' and str(field)!='outlog' and str(field)!='SolutionType':
+							Var=md.results.__dict__[supfield].__getitem__(0).__dict__[field]
+							DimDict=CreateVar(NCData,Var,field,Subgroup,DimDict,True,last_step,step_freq,md,supfield)
+					
+				elif type(md.results.__dict__[supfield])==results:#only one timestep
+					subfields=dict.keys(md.results.__dict__[supfield].__dict__)
+					for field in subfields:
+						if str(field)!='errlog' and str(field)!='outlog' and str(field)!='SolutionType':
+							print 'Treating '+str(group)+'.'+str(supfield)+'.'+str(field)
+							Var=md.results.__dict__[supfield].__dict__[field]
+							DimDict=CreateVar(NCData,Var,field,NCgroup,DimDict,False)
+				else:
+					print 'Result format not suported'
+		else:
+			
+			for field in fields:
+				print 'Treating ' +str(group)+'.'+str(field)
+				NCgroup.__setattr__('classtype', md.__dict__[group].__class__.__name__)
+				Var=md.__dict__[group].__dict__[field]
+				DimDict=CreateVar(NCData,Var,field,NCgroup,DimDict,False)
+	NCData.close()
+
+#============================================================================
+#Define the variables
+def CreateVar(NCData,var,field,Group,DimDict,istime,*step_args):
+	#grab type
+	try:
+		val_type=str(var.dtype)
+	except AttributeError:
+		val_type=type(var)
+		#grab dimension
+	try:
+		val_shape=dict.keys(var)
+	except TypeError:
+		val_shape=numpy.shape(var)
+
+
+	TypeDict = {float:'f8',
+							'float64':'f8',
+							int:'i8',
+							'int64':'i8'}
+		
+	val_dim=numpy.shape(val_shape)[0]
+	#Now define and fill up variable
+	#treating scalar string or bool as atribute
+	if val_type==str or val_type==bool:
+		Group.__setattr__(str(field), str(var))
+
+	#treating list as string table
+	#matlab does not recognise strings so we have to settle down with char arrays
+	elif val_type==list:
+		dimensions,DimDict=GetDim(NCData,var,val_shape,DimDict,val_dim,istime)
+		ncvar = Group.createVariable(str(field),'S1',dimensions,zlib=True)
+		charvar=stringtochar(numpy.array(var))
+		print charvar
+		print charvar.shape
+		for elt in range(0,val_dim):
+			try:
+				ncvar[elt] = charvar[elt]
+			except IndexError:
+				ncvar[0]= " "
+				#treating bool tables as string tables
+	elif val_type=='bool':
+		dimensions,DimDict=GetDim(NCData,var,val_shape,DimDict,val_dim,istime)
+		ncvar = Group.createVariable(str(field),'S1',dimensions,zlib=True)
+		for elt in range(0,val_shape[0]):
+			ncvar[elt] = str(var[elt])
+			#treating dictionaries as string tables of dim 2
+	elif val_type==collections.OrderedDict:
+		dimensions,DimDict=GetDim(NCData,var,val_shape,DimDict,val_dim,istime)
+		ncvar = Group.createVariable(str(field),'S1',dimensions,zlib=True)
+		for elt in range(0,val_dim):
+			ncvar[elt,0]=dict.keys(var)[elt]
+			ncvar[elt,1]=str(dict.values(var)[elt]) #converting to str to avoid potential problems
+			#Now dealing with numeric variables
+	else:
+		dimensions,DimDict=GetDim(NCData,var,val_shape,DimDict,val_dim,istime)
+		ncvar = Group.createVariable(str(field),TypeDict[val_type],dimensions,zlib=True)
+		
+		if istime:
+			last=step_args[0]
+			freq=step_args[1]
+			md=step_args[2]
+			supfield=step_args[3]
+			vartab=var
+			for time in range(freq-1,last,freq):
+				if time!=0:
+					timevar=md.results.__dict__[supfield].__getitem__(time).__dict__[field]
+					print 'Treating results.'+str(supfield)+'.'+str(field)+' for time '+str(time)
+					vartab=numpy.column_stack((vartab,timevar))
+			print numpy.shape(vartab)
+			try:
+				ncvar[:,:]=vartab[:,:]
+			except ValueError:
+				ncvar[:]=vartab.T[:]
+		else:
+			try:
+				nan_val=numpy.isnan(var)
+				if nan_val.all():
+					ncvar [:] = 'NaN'
+				else:
+					ncvar[:] = var
+			except TypeError: #type does not accept nan, get vallue of the variable
+				ncvar[:] = var
+	return DimDict
+
+#============================================================================
+#retriev the dimension tuple from a dictionnary
+def GetDim(NCData,var,shape,DimDict,i,istime):
+	output=[]
+	#grab type
+	try:
+		val_type=str(var.dtype)
+	except AttributeError:
+		val_type=type(var)
+	#grab dimension
+	for dim in range(0,i): #loop on the dimensions
+		if type(shape[0])==int: 
+			try:
+				output=output+[str(DimDict[shape[dim]])] #test if the dimension allready exist
+			except KeyError: #if not create it
+				if (shape[dim])>1:
+					index=len(DimDict)+1
+					NewDim=NCData.createDimension('Dimension'+str(index),(shape[dim]))
+					DimDict[len(NewDim)]='Dimension'+str(index)
+					output=output+[str(DimDict[shape[dim]])]
+					print 'Defining dimension ' +'Dimension'+str(index)
+		elif type(shape[0])==str:#dealling with a dictionnary
+			try:
+				output=[str(DimDict[numpy.shape(shape)[0]])]+['DictDim']
+			except KeyError:
+				index=len(DimDict)+1
+				NewDim=NCData.createDimension('Dimension'+str(index),numpy.shape(shape)[0])
+				DimDict[len(NewDim)]='Dimension'+str(index)
+				output=[str(DimDict[numpy.shape(dict.keys(var))[0]])]+['Dimension6']
+				print 'Defining dimension ' +'Dimension'+str(index)
+			break
+	if istime:
+		output=output+['Dimension4']
+	#dealing with char and not string as we should so we need to had a string length
+	if val_type=='bool' or val_type==collections.OrderedDict or val_type==list:
+		charvar=stringtochar(numpy.array(var))
+		stringlength=charvar.shape[charvar.ndim-1]
+		try:
+			output=output+[str(DimDict[stringlength])] #test if the dimension allready exist
+		except KeyError: #if not create it
+			if (shape[dim])>1:
+				index=len(DimDict)+1
+				NewDim=NCData.createDimension('Dimension'+str(index),(stringlength))
+				DimDict[len(NewDim)]='Dimension'+str(index)
+				output=output+[str(DimDict[stringlength])]
+				print 'Defining dimension ' +'Dimension'+str(index)
+	return tuple(output), DimDict
Index: /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.m	(revision 20176)
@@ -0,0 +1,134 @@
+function self=read_netCDF(filename)
+
+% Different types in the netcdf standard are:
+%   2 for char
+%   4 for integer
+%   6 for doubles	
+	
+	ncid=netcdf.open(filename,'NC_NOWRITE');
+	groupIDs=netcdf.inqGrps(ncid);%retrieve group IDs
+	self=model;
+	%loop on groups
+	for i=1:length(groupIDs)
+		whichclass = netcdf.getAtt(groupIDs(i),netcdf.getConstant('NC_GLOBAL'),'classtype');
+		groupName = netcdf.inqGrpName(groupIDs(i));		
+		%results needs a special treatment as it is a structure
+		if strcmp(whichclass,'results'),
+			subgroupIDs=netcdf.inqGrps(groupIDs(i));%retrieve group IDs
+			%define the model structure
+			self=setfield(self,groupName,struct);
+			for j=1:length(subgroupIDs)
+				subclass = netcdf.getAtt(subgroupIDs(j),netcdf.getConstant('NC_GLOBAL'),'classtype');
+				self.results=setfield(self.results,subclass,struct);
+				[ndims nvar natts]=netcdf.inq(subgroupIDs(j));
+				varIDs=netcdf.inqVarIDs(subgroupIDs(j));
+				%first loop on group atributes
+				for k=1:natts,
+					attname = netcdf.inqAttName(subgroupIDs(j),netcdf.getConstant('NC_GLOBAL'),k-1);
+					[xtype,attlen] = netcdf.inqAtt(subgroupIDs(j),netcdf.getConstant('NC_GLOBAL'),attname);
+					disp(sprintf('In %s, Treating attribute %s of type %i',subclass,attname,xtype));
+					%classtype have done is job, no need to keep it any more
+					if ~strcmp(attname,'classtype'),
+						attval=netcdf.getAtt(subgroupIDs(i),netcdf.getConstant('NC_GLOBAL'),attname);
+						if strcmp(attval,'False'),
+							self.(groupName).(subclass).(attname)=false;
+						elseif strcmp(attval,'True')
+							self.(groupName).(subclass).(attname)=true;
+						else
+							self.(groupName).(subclass).(attname)=attval;
+			      end
+		      end
+		    end
+				%now loop on variable in group
+				for k=1:length(varIDs),
+					[varname, xtype, varDimIDs, varAtts] =netcdf.inqVar(subgroupIDs(j),varIDs(k));
+					disp(sprintf('In %s, Treating variable %s of type %i',whichclass,varname,xtype));
+					%time dimension seems to be last in our construction
+					for l=1:length(varDimIDs),
+						[dimname, dimlen] = netcdf.inqDim(ncid,varDimIDs(l));
+						count(l)=[dimlen];
+		      end
+					startpoint=zeros(size(varDimIDs));
+					timestep=count(end);
+					count(end)=1;
+					for l=1:timestep,
+						data=netcdf.getVar(subgroupIDs(j),varIDs(k),startpoint,count);
+						self.(groupName).(subclass)(l).(varname)=data;
+						startpoint(end)=startpoint(end)+1;
+						self.(groupName).(subclass)(l).('errlog')='';
+						self.(groupName).(subclass)(l).('outlog')='';
+						self.(groupName).(subclass)(l).('SolutionType')=subclass;
+		     end
+				 clear count
+		    end
+	    end
+			%toolkits too require a specific treatment
+		elseif strcmp(whichclass,'toolkits'),
+			%just one variable here
+			varID=netcdf.inqVarIDs(groupIDs(i));
+			[varname, xtype, varDimIDs, varAtts] =netcdf.inqVar(groupIDs(i),varID);
+			disp(sprintf('In %s, Treating variable %s of type %i',whichclass,varname,xtype));
+			[dimname,numoffields] = netcdf.inqDim(ncid,varDimIDs(end));
+			self.(groupName)=eval(whichclass);
+			for j=1:numoffields,
+				varval=netcdf.getVar(groupIDs(i),varID,[0,1,j-1],[40,1,1])';
+				fieldname=netcdf.getVar(groupIDs(i),varID,[0,0,j-1],[40,1,1])';
+				varval=cellstr(varval);
+				fieldname=cellstr(fieldname);
+				[val, status]=str2num(varval{1});
+				if strcmp(varval{1},'false') |strcmp(varval{1},'true')  ,
+					status=0;
+		    end
+				if status==1,
+					self.(groupName).(varname).(fieldname{1})=val;
+				else
+					self.(groupName).(varname).(fieldname{1})=varval{1};
+			 end
+	   end
+			%Now for the other fields
+
+		else,
+			%define the model structure
+			self.(groupName)=eval(whichclass);
+			varIDs=netcdf.inqVarIDs(groupIDs(i));
+			[ndims nvar natts]=netcdf.inq(groupIDs(i));
+			%first loop on group atributes
+			for j=1:natts,
+				attname = netcdf.inqAttName(groupIDs(i),netcdf.getConstant('NC_GLOBAL'),j-1);
+				[xtype,attlen] = netcdf.inqAtt(groupIDs(i),netcdf.getConstant('NC_GLOBAL'),attname);
+				disp(sprintf('In %s, Treating attribute %s of type %i',whichclass,attname,xtype));
+				%classtype have done is job, no need to keep it any more
+				if ~strcmp(attname,'classtype'),
+					attval=netcdf.getAtt(groupIDs(i),netcdf.getConstant('NC_GLOBAL'),attname);
+					if strcmp(attval,'False'),
+						self.(groupName).(attname)=false;
+					elseif strcmp(attval,'True')
+						self.(groupName).(attname)=true;
+					else
+					self.(groupName).(attname)=attval;
+		    end
+		  end
+	  end
+			%now loop on variable in group
+			for j=1:length(varIDs),
+				[varname, xtype, varDimIDs, varAtts] =netcdf.inqVar(groupIDs(i),varIDs(j));
+				disp(sprintf('In %s, Treating variable %s of type %i',whichclass,varname,xtype));			
+				%if the value is a single string, we need to transpose it (cross check with python file is necessary)
+				if xtype==2
+					varval=netcdf.getVar(groupIDs(i),varIDs(j))';
+					varval=cellstr(varval)';
+					if strcmp(varval{1},'emptystruct'),
+						self.(groupName).(varname)=struct;
+					elseif strcmp(varval{1},'emptycell'),
+						self.(groupName).(varname)=cell(0,0);
+					else
+						self.(groupName).(varname)=varval;
+					end
+				else
+					self.(groupName).(varname)=netcdf.getVar(groupIDs(i),varIDs(j));
+		    end
+		  end
+	  end
+  end
+	netcdf.close(ncid)
+end
Index: /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.py
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.py	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/netCDF/read_netCDF.py	(revision 20176)
@@ -0,0 +1,25 @@
+from netCDF4 import Dataset
+import time
+import collections
+from os import path, remove
+
+def netCDFRead(filename):
+	
+	def walktree(data):
+		keys = data.groups.keys()
+		yield keys
+		for key in keys:
+			for children in walktree(data.groups[str(key)]):
+				yield children
+				
+	if path.exists(filename):
+		print ('Opening {} for reading '.format(filename))
+		NCData=Dataset(filename, 'r')
+		class_dict={}
+		
+		for children in walktree(NCData):
+			for child in children:
+				class_dict[str(child)]=str(getattr(NCData.groups[str(child)],'classtype')+'()')
+
+		print class_dict
+				
Index: /issm/trunk-jpl/src/m/contrib/defleurian/paraview/enveloppeVTK.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/paraview/enveloppeVTK.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/paraview/enveloppeVTK.m	(revision 20176)
@@ -0,0 +1,186 @@
+function enveloppeVTK(filename,model,varargin)
+% vtk export
+% function enveloppeVTK(filename,model)
+% creates a directory with the vtk files for displays in paraview
+% only export the enveloppe result (surface and base) on trias
+%
+% input: filename   destination 
+%                   (string)
+%------------------------------------------------------------------
+%        model      this is md 
+%------------------------------------------------------------------
+% By default only the results are exported, you can add whichever
+% field you need as a string:
+% add 'geometry' to export md.geometry
+%
+% Basile de Fleurian:
+
+[path,name,ext]=fileparts(filename);
+separator=filesep;
+mkdir(filename);
+IsEnveloppe=find(model.mesh.vertexonbase | model.mesh.vertexonsurface);
+
+%get the element related variables
+if dimension(model.mesh)==2,
+	points=[model.mesh.x model.mesh.y zeros(model.mesh.numberofvertices,1)];
+	[num_of_elt]=size(model.mesh.elements,1);
+	[point_per_elt]=size(model.mesh.elements,2);
+else
+	points=[model.mesh.x(IsEnveloppe) model.mesh.y(IsEnveloppe) model.mesh.z(IsEnveloppe)];
+	[num_of_elt]=size(find(isnan(model.mesh.lowerelements)),1)+size(find(isnan(model.mesh.upperelements)),1);
+	[low_elt_num]=size(find(isnan(model.mesh.lowerelements)),1);
+	[top_elt_num]=size(find(isnan(model.mesh.upperelements)),1);
+end
+
+celltype=5; %triangles
+[num_of_points,dim]=size(points);
+tot_points=model.mesh.numberofvertices;
+
+%this is the result structure
+res_struct=model.results;
+%checking for results
+if (length(fields(res_struct))>0);
+	%Getting all the solutions of the model
+	solnames=fields(res_struct);
+	num_of_sols=length(solnames);
+	num_of_timesteps=1;
+	%building solution structure 
+	for i=1:num_of_sols
+		sol_struct{i}=res_struct.(solnames{i});
+		%looking for multiple time steps
+		if(size(sol_struct{i},2)>num_of_timesteps);
+			num_of_timesteps=size(sol_struct{i},2);
+			outstep=model.timestepping.time_step*model.settings.output_frequency
+    end
+  end
+else
+	num_of_timesteps=1;
+end
+for step=1:num_of_timesteps;
+	
+	timestep=step;
+	fid = fopen(strcat(path,filesep,name,filesep,'timestep.vtk',int2str(timestep),'.vtk'),'w+');
+	fprintf(fid,'# vtk DataFile Version 2.0 \n');
+	fprintf(fid,'Data for run %s \n',model.miscellaneous.name);
+	fprintf(fid,'ASCII \n');
+	fprintf(fid,'DATASET UNSTRUCTURED_GRID \n');
+	
+	fprintf(fid,'POINTS %d float\n',num_of_points);
+	if(dim==3);
+		s='%f %f %f \n';
+	elseif(dim==2);
+		s='%f %f \n';
+  end
+	P=[points zeros(num_of_points,3-dim)];
+	fprintf(fid,s,P');
+	
+	fprintf(fid,'CELLS %d %d\n',num_of_elt,num_of_elt*(3+1));
+	s='%d';
+	for j=1:3
+		s=horzcat(s,{' %d'});
+  end
+	s=cell2mat(horzcat(s,{'\n'}));
+
+	%build the connection matrix for the top and bottom elements
+	if exist('low_elt_num')
+		triaconnect=zeros(num_of_elt,3);
+		triaconnect(1:low_elt_num,:)=model.mesh.elements(find(isnan(model.mesh.lowerelements)),1:3);
+		upshift=-min(min(model.mesh.elements(find(isnan(model.mesh.upperelements)),4:6)))+1+max(max(model.mesh.elements(find(isnan(model.mesh.lowerelements)),1:3)));
+		triaconnect(1+low_elt_num:num_of_elt,:)=model.mesh.elements(find(isnan(model.mesh.upperelements)),4:6)+upshift;
+		fprintf(fid,s,[(3)*ones(num_of_elt,1) triaconnect-1]');
+	else
+		fprintf(fid,s,[(point_per_elt)*ones(num_of_elt,1)	model.mesh.elements-1]');
+  end
+
+	fprintf(fid,'CELL_TYPES %d\n',num_of_elt);
+	s='%d\n';
+	fprintf(fid,s,celltype*ones(num_of_elt,1));
+	fprintf(fid,'POINT_DATA %s \n',num2str(num_of_points));
+
+	%loop over the different solution structures
+	if (exist('num_of_sols'));
+		for j=1:num_of_sols
+			%dealing with results on different timesteps
+			if(size(sol_struct{j},2)>timestep);
+				timestep = step;
+			else
+				timestep = size(sol_struct{j},2);
+	    end
+			%getting the number of fields in the solution
+			resfields=fields(sol_struct{j}(timestep));
+			num_of_fields=length(resfields);
+			%check which field is a real result and print
+			for k=1:num_of_fields
+				if ((numel(sol_struct{j}(timestep).(resfields{k})))==tot_points);
+					%paraview does not like NaN, replacing
+					nanval=find(isnan(sol_struct{j}(timestep).(resfields{k})));
+					sol_struct{j}(timestep).(resfields{k})(nanval)=-9999;
+					%also checking for verry small value that mess up
+					smallval=(abs(sol_struct{j}(timestep).(resfields{k}))<1.0e-20);
+					sol_struct{j}(timestep).(resfields{k})(smallval)=0.0;
+					fprintf(fid,'SCALARS %s float 1 \n',resfields{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					s='%e\n';
+					fprintf(fid,s,sol_struct{j}(timestep).(resfields{k})(IsEnveloppe));
+		    end		
+	    end 
+	  end
+  end
+	%loop on arguments, if something other than result is asked, do
+	%it now
+	for j= 1:nargin-2
+		res_struct=model.(varargin{j});
+		fieldnames=fields(res_struct);
+		num_of_fields=length(fieldnames);
+		for k=1:num_of_fields
+			if ((numel(res_struct.(fieldnames{k})))==tot_points);
+				%paraview does not like NaN, replacing
+				nanval=find(isnan(res_struct.(fieldnames{k})));
+				res_struct.(fieldnames{k})(nanval)=-9999;
+				%also checking for verry small value that mess up
+				smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20);
+				res_struct.(fieldnames{k})(smallval)=0.0;
+				fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+				fprintf(fid,'LOOKUP_TABLE default\n');
+				s='%e\n';
+				fprintf(fid,s,res_struct.(fieldnames{k})(IsEnveloppe));
+				%check for forcings	
+			elseif (size(res_struct.(fieldnames{k}),1)==tot_points+1);
+				%paraview does not like NaN, replacing
+				nanval=find(isnan(res_struct.(fieldnames{k})));
+				res_struct.(fieldnames{k})(nanval)=-9999;
+				%also checking for verry small value that mess up
+				smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20);
+				res_struct.(fieldnames{k})(smallval)=0.0;
+				if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps),
+					fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					s='%e\n';
+					fprintf(fid,s,res_struct.(fieldnames{k})(IsEnveloppe,timestep));
+				else,
+					%forcing and results not on the same timestep,need some treatment
+					fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					index=1
+					currenttime=((timestep-1)*outstep)+model.timestepping.start_time+model.timestepping.time_step
+					while (res_struct.(fieldnames{k})(end,index)<=currenttime);
+						index=index+1
+		      end
+					uptime=res_struct.(fieldnames{k})(end,index);
+					uplim=res_struct.(fieldnames{k})(IsEnveloppe,index);
+					uptime
+					while (res_struct.(fieldnames{k})(end,index)>=currenttime);
+						index=index-1
+		      end
+					lowtime=res_struct.(fieldnames{k})(end,index);
+					lowlim=res_struct.(fieldnames{k})(IsEnveloppe,index);
+					lowtime
+					interp=lowlim+(uplim-lowlim)*((currenttime-lowtime)/(uptime-lowtime))
+					s='%e\n';
+					fprintf(fid,s,interp);
+				end	
+		  end		
+		end 
+	end
+	fclose(fid);
+end
Index: /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.m	(revision 20176)
@@ -0,0 +1,197 @@
+function exportVTK(filename,model,varargin)
+% vtk export
+% function exportVTK(filename,model)
+% creates a directory with the vtk files for displays in paraview
+% (only work for triangle and wedges based on their number of nodes)
+%
+%Give only the results for nw but could be extended to geometry, mask... 
+%
+% input: filename   destination 
+%                   (string)
+%------------------------------------------------------------------
+%        model      this is md 
+%------------------------------------------------------------------
+% By default only the results are exported, you can add whichever
+% field you need as a string:
+% add 'geometry' to export md.geometry
+%
+% Basile de Fleurian:
+
+[path,name,ext]=fileparts(filename);
+separator=filesep;
+mkdir(filename);
+
+%get the element related variables
+if dimension(model.mesh)==2,
+	points=[model.mesh.x model.mesh.y zeros(model.mesh.numberofvertices,1)];
+	[num_of_points,dim]=size(points);
+	[num_of_elt]=size(model.mesh.elements,1);
+	[point_per_elt]=size(model.mesh.elements,2);
+else
+	points=[model.mesh.x model.mesh.y model.mesh.z];
+	[num_of_points,dim]=size(points);
+	[num_of_elt]=size(model.mesh.elements,1);
+	[point_per_elt]=size(model.mesh.elements,2);
+end
+
+
+%Select the type of element function of the number of nodes per elements
+if point_per_elt==3;
+	celltype=5; %triangles
+elseif point_per_elt==6;
+	celltype=13; %wedges
+else
+	error('Your Element definition is not taken into account \n');
+end
+
+%this is the result structure
+res_struct=model.results;
+%checking for results
+if (length(fields(res_struct))>0);
+	%Getting all the solutions of the model
+	solnames=fields(res_struct);
+	num_of_sols=length(solnames);
+	num_of_timesteps=1;
+	%building solution structure 
+	for i=1:num_of_sols
+		sol_struct{i}=res_struct.(solnames{i});
+		%looking for multiple time steps
+		if(size(sol_struct{i},2)>num_of_timesteps);
+			num_of_timesteps=size(sol_struct{i},2);
+	  end
+		outstep=model.timestepping.time_step*model.settings.output_frequency;
+  end
+else
+	num_of_timesteps=1;
+end
+for step=1:num_of_timesteps;
+	
+	timestep=step;
+
+	fid = fopen(strcat(path,filesep,name,filesep,'timestep.vtk',int2str(timestep),'.vtk'),'w+');
+	fprintf(fid,'# vtk DataFile Version 2.0 \n');
+	fprintf(fid,'Data for run %s \n',model.miscellaneous.name);
+	fprintf(fid,'ASCII \n');
+	fprintf(fid,'DATASET UNSTRUCTURED_GRID \n');
+	
+	fprintf(fid,'POINTS %d float\n',num_of_points);
+	if(dim==3);
+		s='%f %f %f \n';
+	elseif(dim==2);
+		s='%f %f \n';
+  end
+	P=[points zeros(num_of_points,3-dim)];
+	fprintf(fid,s,P');
+	
+	fprintf(fid,'CELLS %d %d\n',num_of_elt,num_of_elt*(point_per_elt+1));
+	s='%d';
+	for j=1:point_per_elt
+		s=horzcat(s,{' %d'});
+  end
+	s=cell2mat(horzcat(s,{'\n'}));
+		fprintf(fid,s,[(point_per_elt)*ones(num_of_elt,1)	model.mesh.elements-1]');
+	
+	fprintf(fid,'CELL_TYPES %d\n',num_of_elt);
+	s='%d\n';
+	fprintf(fid,s,celltype*ones(num_of_elt,1));
+	fprintf(fid,'POINT_DATA %s \n',num2str(num_of_points));
+
+	%loop over the different solution structures
+	if (exist('num_of_sols'));
+		for j=1:num_of_sols
+			%dealing with results on different timesteps
+			if(size(sol_struct{j},2)>timestep);
+				timestep = step;
+			else
+				timestep = size(sol_struct{j},2);
+	    end
+			
+			%getting the number of fields in the solution
+			fieldnames=fields(sol_struct{j}(timestep));
+			num_of_fields=length(fieldnames);
+			
+			%check which field is a real result and print
+			for k=1:num_of_fields
+				if ((numel(sol_struct{j}(timestep).(fieldnames{k})))==num_of_points);
+					%paraview does not like NaN, replacing
+					nanval=find(isnan(sol_struct{j}(timestep).(fieldnames{k})));
+					sol_struct{j}(timestep).(fieldnames{k})(nanval)=-9999;
+					%also checking for verry small value that mess up
+					smallval=(abs(sol_struct{j}(timestep).(fieldnames{k}))<1.0e-20);
+					sol_struct{j}(timestep).(fieldnames{k})(smallval)=0.0;
+					fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					s='%e\n';
+					fprintf(fid,s,sol_struct{j}(timestep).(fieldnames{k}));
+		    end		
+	    end 
+	  end
+  end
+	%loop on arguments, if something other than result is asked, do
+	%it now
+	for j= 1:nargin-2
+		res_struct=model.(varargin{j});
+		fieldnames=fields(res_struct);
+		num_of_fields=length(fieldnames);
+		for k=1:num_of_fields
+			if ((numel(res_struct.(fieldnames{k})))==num_of_points);
+				%paraview does not like NaN, replacing
+				nanval=find(isnan(res_struct.(fieldnames{k})));
+				res_struct.(fieldnames{k})(nanval)=-9999;
+				%also checking for verry small value that mess up
+				smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20);
+				res_struct.(fieldnames{k})(smallval)=0.0;
+				fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+				fprintf(fid,'LOOKUP_TABLE default\n');
+				s='%e\n';
+				fprintf(fid,s,res_struct.(fieldnames{k}));
+				%check for forcings	
+			elseif (size(res_struct.(fieldnames{k}),1)==num_of_points+1);
+				%paraview does not like NaN, replacing
+				nanval=find(isnan(res_struct.(fieldnames{k})));
+				res_struct.(fieldnames{k})(nanval)=-9999;
+				%also checking for verry small value that mess up
+				smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20);
+				res_struct.(fieldnames{k})(smallval)=0.0;
+				if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps),
+					fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					s='%e\n';
+					fprintf(fid,s,res_struct.(fieldnames{k})(1:end-1,timestep));
+				else,
+					%forcing and results not on the same timestep,need some treatment
+					fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k});
+					fprintf(fid,'LOOKUP_TABLE default\n');
+					index=1;
+					currenttime=((timestep-1)*outstep)+model.timestepping.start_time;
+					while (res_struct.(fieldnames{k})(end,index)<=currenttime);
+						if index==size(res_struct.(fieldnames{k}),2)
+							break
+						end	
+						index=index+1;
+		      end
+					uptime=res_struct.(fieldnames{k})(end,index);
+					uplim=res_struct.(fieldnames{k})(1:end-1,index);
+					while (res_struct.(fieldnames{k})(end,index)>=currenttime);
+						if index==1
+							break
+			      end
+						index=index-1;
+		      end
+					lowtime=res_struct.(fieldnames{k})(end,index);
+					lowlim=res_struct.(fieldnames{k})(1:end-1,index);
+					if uptime==currenttime,
+						interp=uplim;
+					elseif lowtime==currenttime,
+						interp=lowlim;
+					else
+						interp=lowlim+(uplim-lowlim)*((currenttime-lowtime)/(uptime-lowtime));
+					end
+					s='%e\n';
+					fprintf(fid,s,interp);
+				end
+		  end		
+		end 
+	end
+	fclose(fid);
+end
Index: /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.py
===================================================================
--- /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.py	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/defleurian/paraview/exportVTK.py	(revision 20176)
@@ -0,0 +1,163 @@
+import numpy
+import os
+import model
+import glob
+def exportVTK(filename,model,*args):
+	'''
+	vtk export
+	function exportVTK(filename,model)
+	creates a directory with the vtk files for displays in paraview
+	(only work for triangle and wedges based on their number of nodes)
+	
+	Give only the results for nw but could be extended to geometry, mask... 
+	
+	input: filename   destination 
+	(string)
+	------------------------------------------------------------------
+model      this is md 
+	------------------------------------------------------------------
+	By default only the results are exported, you can add whichever
+	field you need as a string:
+	add 'geometry' to export md.geometry
+
+	Basile de Fleurian:
+	'''
+	Dir=os.path.basename(filename)
+	Path=filename[:-len(Dir)]
+
+	if os.path.exists(filename):
+		print ('File {} allready exist'.format(filename))
+		newname=raw_input('Give a new name or "delete" to replace: ')
+		if newname=='delete':
+			filelist = glob.glob(filename+'/*')
+			for oldfile in filelist:
+				os.remove(oldfile)
+		else:
+			print ('New file name is {}'.format(newname))
+			filename=newname
+			os.mkdir(filename)
+	else:
+		os.mkdir(filename)
+
+	#get the element related variables
+	if 'z' in dict.keys(model.mesh.__dict__):
+		points=numpy.column_stack((model.mesh.x,model.mesh.y,model.mesh.z))
+		dim=3
+	else:
+		points=numpy.column_stack((model.mesh.x,model.mesh.y,numpy.zeros(numpy.shape(model.mesh.x))))
+		dim=2
+
+	num_of_points=numpy.size(model.mesh.x)
+	num_of_elt=numpy.shape(model.mesh.elements)[0]
+	point_per_elt=numpy.shape(model.mesh.elements)[1]
+		
+	#Select the type of element function of the number of nodes per elements
+	if point_per_elt==3:
+		celltype=5 #triangles
+	elif point_per_elt==6:
+		celltype=13 #wedges
+	else:
+		error('Your Element definition is not taken into account \n')
+
+	#this is the result structure
+	res_struct=model.results
+	if (len(res_struct.__dict__)>0):
+		#Getting all the solutions of the model
+		solnames=(dict.keys(res_struct.__dict__))
+		num_of_sols=len(solnames)
+		num_of_timesteps=1
+		out_freq=model.settings.output_frequency
+		#%building solutionstructure 
+		for solution in solnames:
+			#looking for multiple time steps
+			if (numpy.size(res_struct.__dict__[solution])>num_of_timesteps):
+				num_of_timesteps=numpy.size(res_struct.__dict__[solution])
+				num_of_timesteps=int(num_of_timesteps/out_freq)+1
+	else:
+		num_of_timesteps=1
+
+	for step in range(0,num_of_timesteps):
+		timestep=step
+		fid=open((filename +'/Timestep.vtk'+str(timestep)+'.vtk'),'w+')
+		fid.write('# vtk DataFile Version 2.0 \n')
+		fid.write('Data for run %s \n' % model.miscellaneous.name)
+		fid.write('ASCII \n')
+		fid.write('DATASET UNSTRUCTURED_GRID \n')
+		fid.write('POINTS %d float\n' % num_of_points)
+		if(dim==3):
+			for point in points:
+				fid.write('%f %f %f \n'%(point[0], point[1], point[2]))
+		elif(dim==2):
+			for point in points:
+				fid.write('%f %f %f \n'%(point[0], point[1], point[2]))
+			
+		fid.write('CELLS %d %d\n' %(num_of_elt, num_of_elt*(point_per_elt+1)))
+		
+		if point_per_elt==3:
+			for elt in range(0, num_of_elt):
+				fid.write('3 %d %d %d\n' %(model.mesh.elements[elt,0]-1,model.mesh.elements[elt,1]-1,model.mesh.elements[elt,2]-1))
+		elif point_per_elt==6:
+			for elt in range(0, num_of_elt):
+				fid.write('6 %d %d %d %d %d %d\n' %(model.mesh.elements[elt,0]-1,model.mesh.elements[elt,1]-1,model.mesh.elements[elt,2]-1,model.mesh.elements[elt,3]-1,model.mesh.elements[elt,4]-1,model.mesh.elements[elt,5]-1))
+		else:
+			print 'Number of nodes per element not supported'
+
+		fid.write('CELL_TYPES %d\n' %num_of_elt)
+		for elt in range(0, num_of_elt):
+			fid.write('%d\n' %celltype)
+
+		fid.write('POINT_DATA %s \n' %str(num_of_points))
+	
+		#loop over the different solution structures
+		if 'solnames' in locals():
+			for sol in solnames:
+				#dealing with results on different timesteps
+				if(numpy.size(res_struct.__dict__[sol])>timestep):
+					timestep = step
+				else:
+					timestep = numpy.size(res_struct.__dict__[sol])
+				
+				#getting the  fields in the solution
+				if(numpy.size(res_struct.__dict__[sol])>1):
+					fieldnames=dict.keys(res_struct.__dict__[sol].__getitem__(timestep*out_freq-1).__dict__)
+				else:
+					fieldnames=dict.keys(res_struct.__dict__[sol].__dict__)
+				#check which field is a real result and print
+				for field in fieldnames:
+					if(numpy.size(res_struct.__dict__[sol])>1):
+						fieldstruct=res_struct.__dict__[sol].__getitem__(timestep*out_freq-1).__dict__[field]
+					else:
+						fieldstruct=res_struct.__dict__[sol].__dict__[field]
+
+					if ((numpy.size(fieldstruct))==num_of_points):
+						fid.write('SCALARS %s float 1 \n' % field)
+						fid.write('LOOKUP_TABLE default\n')
+						for node in range(0,num_of_points):
+							#paraview does not like NaN, replacing
+							if numpy.isnan(fieldstruct[node]):
+								fid.write('%e\n' % -9999.9999)
+							#also checking for verry small value that mess up
+							elif (abs(fieldstruct[node])<1.0e-20):
+								fid.write('%e\n' % 0.0)
+							else:
+								fid.write('%e\n' % fieldstruct[node])
+					
+		#loop on arguments, if something other than result is asked, do
+		#it now
+		for other in args:
+			other_struct=model.__dict__[other]
+			othernames=(dict.keys(other_struct.__dict__))
+			for field in othernames:
+				if ((numpy.size(other_struct.__dict__[field]))==num_of_points):
+					fid.write('SCALARS %s float 1 \n' % field)
+					fid.write('LOOKUP_TABLE default\n')
+					for node in range(0,num_of_points):
+						#paraview does not like NaN, replacing
+						if numpy.isnan(other_struct.__dict__[field][node]):
+							fid.write('%e\n' % -9999.9999)
+						#also checking for verry small value that mess up
+						elif (abs(other_struct.__dict__[field][node])<1.0e-20):
+							fid.write('%e\n' % 0.0)
+						else:
+							fid.write('%e\n' % other_struct.__dict__[field][node])
+	fid.close();
Index: /issm/trunk-jpl/src/m/contrib/larour/ecco/MeltingGroundingLines.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/ecco/MeltingGroundingLines.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/ecco/MeltingGroundingLines.m	(revision 20176)
@@ -0,0 +1,26 @@
+function md=MeltingGroundingLines(md,distance,value)
+%MELTINGGROUNDINGLINES - set melting near grounding lines to a constant value
+%
+%   Usage:
+%      md=MeltingGroundingLines(md,distance,value)
+%
+
+%get nodes on ice sheet and on ice shelf
+pos_shelf=find(md.mask.groundedice_levelset<0.);
+pos_GL=intersect(unique(md.mesh.elements(find(md.mask.elementongroundedice),:)),unique(md.mesh.elements(find(md.mask.elementonfloatingice),:)));
+
+for i=1:length(pos_shelf)
+
+	if (mod(i,100)==0),
+		fprintf('\b\b\b\b\b\b\b%5.2f%s',i/length(pos_shelf)*100,' %');
+	end
+
+	%search the node on ice sheet the closest to i
+	[d posd]=min(sqrt((md.mesh.x(pos_shelf(i))-md.mesh.x(pos_GL)).^2+(md.mesh.y(pos_shelf(i))-md.mesh.y(pos_GL)).^2));
+
+	if d<distance,
+
+		md.melting(pos_shelf(i))=value;
+
+	end
+end
Index: /issm/trunk-jpl/src/m/contrib/larour/ecco/PropagateFlagsUntilDistance.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/ecco/PropagateFlagsUntilDistance.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/ecco/PropagateFlagsUntilDistance.m	(revision 20176)
@@ -0,0 +1,60 @@
+function new_flags=PropagateFlagsUntilDistance(md,flags,distance)
+%PROPAGATEFLAGSUNTILDISTANCE
+%
+% Usage: 
+%              flags=PropagateFlagsUntilDistance(md,flags,distance)
+%
+%
+
+new_flags=flags;
+
+%make 3d work in 2d: 
+if dimension(md.mesh)==3,
+	md.mesh.x=md.mesh.x2d;
+	md.mesh.y=md.mesh.y2d;
+	md.mesh.elements=md.mesh.elements2d;
+end
+
+%find elements that are at the border of flags: 
+flag_elements=find(flags);
+conn=md.mesh.elementconnectivity(flag_elements,:);
+pos=find(conn);conn(pos)=~flags(conn(pos));
+sum_conn=sum(conn,2);
+border_elements=flag_elements(find(sum_conn>=1));
+
+%average x and y over elements: 
+x_elem=md.mesh.x(md.mesh.elements)*[1;1;1]/3;
+y_elem=md.mesh.y(md.mesh.elements)*[1;1;1]/3;
+
+while 1,
+
+	%keep copy of new_flags for this loop: 
+	new_flags_bak=new_flags;
+
+	%extend new flags by connectivity
+	pos=find(new_flags);
+
+	connected_elements=md.mesh.elementconnectivity(pos,:);
+	connected_elements=connected_elements(find(connected_elements));
+	new_flags(connected_elements)=1;
+
+	%get new elements: 
+	new_elements=find(new_flags & ~new_flags_bak);
+	if ~length(new_elements),
+		%we are done!
+		break;
+	end
+
+	%check which of these new elements are more than distance away from the border elements
+	for i=1:length(new_elements),
+		dist=sqrt(     (x_elem(border_elements)-x_elem(new_elements(i))).^2 + (y_elem(border_elements)-y_elem(new_elements(i))).^2)-distance;
+		if ~any(dist<0)
+			%none of the border elements are within distance, this element is outside out area of interest.
+			%ensure this element never gets found again in the connectivity.
+			pos=find(md.mesh.elementconnectivity==new_elements(i));
+			md.mesh.elementconnectivity(pos)=0;
+			%exclude this new element from the new_flags!
+			new_flags(new_elements(i))=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/contrib/larour/ecco/ecco32issm.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/ecco/ecco32issm.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/ecco/ecco32issm.m	(revision 20176)
@@ -0,0 +1,8 @@
+function nodefield=ecco32issm(field,transition,xecco3,yecco3)
+
+	xecco3linear=xecco3(:); yecco3linear=yecco3(:); %linearize
+	nodefieldlinear=zeros(length(xecco3linear),1);
+	nodefieldlinear(transition(:,1))=field(transition(:,2));
+	nodefield=xecco3;
+	nodefield(:)=nodefieldlinear;
+	%nodefield=nodefield'; %not sure we need that
Index: /issm/trunk-jpl/src/m/contrib/larour/ecco/issm2ecco3.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/ecco/issm2ecco3.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/ecco/issm2ecco3.m	(revision 20176)
@@ -0,0 +1,8 @@
+function nodefield=issm2ecco3(field,transition,xecco3,yecco3)
+
+	xecco3linear=xecco3(:); yecco3linear=yecco3(:); %linearize
+	nodefieldlinear=zeros(length(xecco3linear),1);
+	nodefieldlinear(transition(:,1))=field(transition(:,2));
+	nodefield=xecco3;
+	nodefield(:)=nodefieldlinear;
+	%nodefield=nodefield'; %not sure we need that
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/aggregation.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/aggregation.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/aggregation.m	(revision 20176)
@@ -0,0 +1,64 @@
+function [mask,varargout]=aggregation(mask,windowsize,threshhold,varargin)
+%AGGREGATION - aggregation of an image to a lower sized image
+% 
+%  mask is an image of arbitrary size, format binary, with values 1 for foreground, and 0 for background
+%  mask is first convoluted with a square matrix of size windowsize (where windowsize is an even number), 
+%       it is then filtered according to the threshhold value, and finally subsampled using 1/windowsize as 
+%       sample scaling. 
+%  x,y can be provided as optional arguments, as coordinates of the center points of the mask. aggregation will 
+%       then return subsampled x,y arguments in output.
+% 
+%  Usage:   mask2=aggregation(mask,7,7^2/2);
+%           [mask2,x2,y2]=aggregation(mask,7,7^2,x,y];
+%
+%  See also CLOSING, OPENING, DILATION, EROSION
+
+%check input arguments  %{{{
+%even windowsize
+if mod(windowsize,2)==0,
+	error('windowsize should be an even number');
+end
+
+%check on presence of varargin: 
+optional=0;
+if nargin>3,
+	if nargin~=5,
+		help aggregation;
+		error('wrong number of optional arguments specified');
+	else
+		optional=1;
+		x=varargin{1};
+		y=varargin{2};
+	end
+end
+
+%check on presence of varargout: 
+if optional,
+	if nargout~=3,
+		help aggregation;
+		error('wrong number of optional output arguments specified');
+	end
+end
+%}}}
+
+%convolve mask
+matrix=ones(windowsize,windowsize); 
+mask=filter2(matrix,mask,'same');
+
+%apply threshhold
+pos=find(mask>threshhold); 
+pos2=find(mask<=threshhold); 
+mask(pos)=1;
+mask(pos2)=0;
+
+%mask has been transformed into double format from the filter2  operation. Bring back to binary. 
+mask=logical(mask);
+
+%subsample: 
+s=size(mask);
+mask=mask(1:windowsize:s(1),1:windowsize:s(2));
+
+if optional,
+	varargout{1}=x(1:windowsize:s(2));
+	varargout{2}=y(1:windowsize:s(1));
+end
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/closing.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/closing.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/closing.m	(revision 20176)
@@ -0,0 +1,5 @@
+function mask=closing(mask,neighboorhood)
+%closing algorithm using neighboorhood pixel neighboors.
+
+mask=dilation(mask,neighboorhood);
+mask=erosion(mask,neighboorhood);
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/dilation.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/dilation.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/dilation.m	(revision 20176)
@@ -0,0 +1,25 @@
+function mask=dilation(mask,neighboorhood)
+%deletion algorithm using 4 pixel neighboors.
+
+%convolve: 
+
+matrix=ones(3,3); 
+
+%4 neighboorhood: 
+%corners
+if neighboorhood==4,
+	matrix(1,1)=0;
+	matrix(1,3)=0;
+	matrix(3,1)=0;
+	matrix(3,3)=0;
+end
+%center
+matrix(2,2)=0;
+
+%convolve mask: 
+convol=filter2(matrix,mask,'same');
+
+pos=find(mask==0);
+pos2=find(convol(pos)~=0);
+
+mask(pos(pos2))=1;
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/erosion.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/erosion.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/erosion.m	(revision 20176)
@@ -0,0 +1,26 @@
+function mask=erosion(mask,neighboorhood)
+%erosion algorithm using neighboorhood pixel neighboors.
+
+%convolve: 
+
+matrix=ones(3,3); 
+
+%4 neighboorhood: 
+%corners
+if neighboorhood==4,
+	matrix(1,1)=0;
+	matrix(1,3)=0;
+	matrix(3,1)=0;
+	matrix(3,3)=0;
+end
+
+%center
+matrix(2,2)=0;
+
+%convolve mask: 
+convol=filter2(matrix,mask,'same');
+
+pos=find(mask==1);
+pos2=find(convol(pos)<neighboorhood);
+
+mask(pos(pos2))=0;
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/nunataks.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/nunataks.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/nunataks.m	(revision 20176)
@@ -0,0 +1,20 @@
+function [mask]=nunataks(mask)
+%NUNATAKS - bias mask towards increased 0 coverage
+% 
+%  mask is an image of arbitrary size, format binary, with values 1 for foreground, and 0 for background
+% 
+%  Usage:   mask=nunataks(mask)
+%           [mask]=aggregation(mask);
+%
+%  See also CLOSING, OPENING, DILATION, EROSION, AGGREGATION
+
+rocks=~mask;
+
+%matrices for convolution: 
+matrix=[0 1 0; 1 0 1; 0 1 0];
+
+%do not exist, i.e. locations that stand pretty much alone. 
+mask=filter2(matrix1,mask,'same');
+pos=find(~crocks & rocks);
+
+mask(pos)=0;
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/opening.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/opening.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/opening.m	(revision 20176)
@@ -0,0 +1,5 @@
+function mask=opening(mask,neighboorhood)
+%opening algorithm using neighboorhood pixel neighboors.
+
+mask=erosion(mask,neighboorhood);
+mask=dilation(mask,neighboorhood);
Index: /issm/trunk-jpl/src/m/contrib/larour/morphological/vectorialize.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/morphological/vectorialize.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/morphological/vectorialize.m	(revision 20176)
@@ -0,0 +1,11 @@
+function contours=vectorialize(mask,connectivity);
+
+	vec=bwboundaries(mask,connectivity);
+
+	contours=struct([]);
+	for i=1:length(vec),
+		contours(end+1).x=vec{i}(:,2);
+		contours(end).y=vec{i}(:,1);
+		contours(end).density=1;
+	end
+	contours(1).name='';
Index: /issm/trunk-jpl/src/m/contrib/larour/resultstomatrix.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/resultstomatrix.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/resultstomatrix.m	(revision 20176)
@@ -0,0 +1,64 @@
+function matrix=resultstomatrix(md,resultname,field,varargin)
+%RESULTSTOMATRIX - go grab in the model results structure the vector results for each time step (which is not empty), 
+%                  and line them up in a matrix.  If time vector is provided, resample.
+%
+%   Usage:
+%      matrix=resultstomatrix(model,solutioname,fieldname)
+%
+%   Available options:
+%      - 'time'     : vector providing new time tags used to resample time
+%
+%   Example:
+%      vel=resultstomatrix(md,'TransientSolution','Vel');
+%      vel=resultstomatrix(md,'TransientSolution','Vel','time',2008:1/12:2014);
+%
+%   See also MODEL  resample
+
+
+	options=pairoptions(varargin{:});
+
+	results=md.results.(resultname);
+
+	%first, figure out the size: 
+	count=0;
+	nods=0;
+	for i=1:length(results),
+		if ~isempty(results(i).(field)),
+			count=count+1;
+			nods=size(results(i).(field),1);
+		end
+	end
+
+	if ~count, 
+		error(['could not find any result ' field ' in ' resultname]);
+	end
+
+	%initialize: 
+	matrix=zeros(nods+1,count);
+
+	%fill it up: 
+	count=0;
+	for i=1:length(results),
+		if ~isempty(results(i).(field)),
+			count=count+1;
+			matrix(1:end-1,count)=results(i).(field);
+			matrix(end,count)=results(i).time/md.constants.yts;
+		end
+	end
+
+	newtime=getfieldvalue(options,'time',[]);
+	if ~isempty(newtime),
+		newmatrix=zeros(nods+1,length(newtime));
+		newmatrix(end,:)=newtime;
+		%we are asked to reinterpolate to this new time: 
+
+		for i=1:nods,
+			warning off;
+			ts=timeseries(matrix(i,:), matrix(end,:));
+			ts=resample(ts,newtime);
+			warning on;
+			newmatrix(i,:)=ts.Data;
+		end
+
+		matrix=newmatrix;
+	end
Index: /issm/trunk-jpl/src/m/contrib/larour/tres.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/larour/tres.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/larour/tres.m	(revision 20176)
@@ -0,0 +1,115 @@
+function md=tres(md,string)
+%TRES - transfer results results to corresponding model fields. 
+%
+%    Usage: md=tres(md,string)
+%
+%    Example: md=tres(md,'stressbalance');
+
+%check number of arguments
+
+if strcmpi(string,'stressbalance'),
+	if strcmp(domaintype(md.mesh),'2Dhorizontal'),
+		md.initialization.vx=md.results.StressbalanceSolution.Vx;
+		md.initialization.vy=md.results.StressbalanceSolution.Vy;
+	else 
+		md.initialization.vx=md.results.StressbalanceSolution.Vx;
+		md.initialization.vy=md.results.StressbalanceSolution.Vy;
+		md.initialization.vz=md.results.StressbalanceSolution.Vz;
+	end
+	md.initialization.vel=md.results.StressbalanceSolution.Vel;
+
+	if isfield(md.results.StressbalanceSolution,'Pressure'),
+		md.initialization.pressure=md.results.StressbalanceSolution.Pressure;
+	end
+	if ~isempty(md.rifts.riftstruct),
+		if isfield(md.results.StressbalanceSolution,'riftproperties'),
+			md.rifts.riftproperties=md.results.StressbalanceSolution.riftproperties;
+		end
+	end
+
+elseif strcmpi(string,'dakota'),
+	md.qmu.results=md.results.dakota;
+
+elseif strcmpi(string,'flaim'),
+	md.flaim.solution=md.results.FlaimSolution.solution;
+	md.flaim.quality =md.results.FlaimSolution.quality;
+
+elseif strcmpi(string,'transient'),
+	results=md.results.TransientSolution;
+	results2.Vel=NaN;
+	count=1;
+	for i=1:length(results),
+		if ~isempty(md.results.TransientSolution(i).Vel),
+			results2(count).Vel=md.results.TransientSolution(i).Vel;
+			results2(count).Surface=md.results.TransientSolution(i).Surface;
+			results2(count).Thickness=md.results.TransientSolution(i).Thickness;
+			results2(count).Bed=md.results.TransientSolution(i).Bed;
+			results2(count).Vx=md.results.TransientSolution(i).Vx;
+			results2(count).Vy=md.results.TransientSolution(i).Vy;
+			results2(count).time=md.results.TransientSolution(i).time;
+			results2(count).step=md.results.TransientSolution(i).step;
+			if ~strcmpi(md.groundingline.migration,'None'),
+				results2(count).ElementOnIceShelf=md.results.TransientSolution(i).ElementOnIceShelf;
+			end
+			count=count+1;
+		end
+	end
+	md.results.TransientSolution=results2;
+	clear results,results2;
+elseif strcmpi(string,'steadystate'),
+	md.initialization.vx=md.results.SteadystateSolution.Vx;
+	md.initialization.vy=md.results.SteadystateSolution.Vy;
+	if isfield(md.results.SteadystateSolution,'Vz'),
+		md.initialization.vz=md.results.SteadystateSolution.Vz;
+	end
+
+	md.initialization.vel=md.results.SteadystateSolution.Vel;
+	md.initialization.pressure=md.results.SteadystateSolution.Pressure;
+	md.initialization.temperature=md.results.SteadystateSolution.Temperature;
+	md.basalforcings.groundedice_melting_rate=md.results.SteadystateSolution.BasalforcingsGroundediceMeltingRate;
+
+	if md.inversion.iscontrol==1,
+		for control_parameters=md.inversion.control_parameters
+			md.(EnumToModelField(control_parameters))=md.results.SteadystateSolution.(EnumToString(control_parameters));
+		end
+	end
+
+elseif strcmpi(string,'thermal'),
+	md.initialization.temperature=md.results.ThermalSolution.Temperature;
+	md.basalforcings.groundedice_melting_rate=md.results.ThermalSolution.BasalGroundediceMeltingRate;
+elseif strcmpi(string,'hydrology'),
+	md.initialization.watercolumn=md.results.HydrologySolution.Watercolumn;
+
+else 
+	error(['tres error message: analysis ' string ' not supported yet!']);
+end
+end 
+function string=EnumToModelField(enum) % {{{
+	%ENUMTOMODELFIELD - output string of model field associated to enum
+	%
+	%   Usage:
+	%      string=EnumToModelField(enum)
+
+	disp('Warning: EnumToModelField is deprecated, it cannot work with new model definition. This function will be removed in the future');
+
+	switch enum,
+
+		case ThicknessEnum(), string='thickness'; return
+		case FrictionCoefficientEnum(), string='drag_coefficient'; return
+		case MaterialsRheologyBEnum(), string='rheology_B'; return
+		case MaterialsRheologyBbarEnum(), string='rheology_B'; return
+		case MaterialsRheologyZEnum(), string='rheology_Z'; return
+		case MaterialsRheologyZbarEnum(), string='rheology_Z'; return
+		case BalancethicknessThickeningRateEnum(), string='dhdt'; return
+		case VxEnum(), string='vx'; return
+		case InversionVxObsEnum(), string='vx_obs'; return
+		case VyEnum(), string='vy'; return
+		case InversionVyObsEnum(), string='vy_obs'; return
+		case BasalforcingsMeltingRateEnum(), string='basal_melting_rate'; return
+		case SmbAccumulationRateEnum(), string='surface_accumulation_rate'; return
+		case SmbAblationRateEnum(), string='surface_ablation_rate'; return
+		case SmbMassBalanceEnum(), string='surface_mass_balance'; return
+		otherwise, error(['Enum ' num2str(enum)  ' not found associated to any model field']);
+
+		end
+	end % }}}
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCall.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCall.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCall.m	(revision 20176)
@@ -0,0 +1,79 @@
+function md=BamgCall(md,field,hmin,hmax,gradation,epsilon),
+%BAMGCALL - call bam
+%
+%   build a metric using the Hessian of the given field
+%   call Bamg and the output mesh is plugged onto the model
+%   -hmin = minimum edge length (m)
+%   -hmax = maximum edge length (m)
+%   -gradation = maximum edge length gradation between 2 elements
+%   -epsilon = average error on each element (m/yr)
+%
+%   Usage:
+%      md=BamgCall(md,field,hmin,hmax,gradation,epsilon);
+%
+%   Example:
+%      md=BamgCall(md,md.inversion.vel_obs,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%Compute Hessian
+t1=clock; fprintf('%s','      computing Hessian...');
+hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node');
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%Compute metric
+t1=clock; fprintf('%s','      computing metric...');
+metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,[]);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('carre0.met','w');
+fprintf(fid,'%i %i\n',md.mesh.numberofvertices,3);
+fprintf(fid,'%i %i %i\n',metric');
+fclose(fid);
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'%s %i\n','MeshVersionFormatted',0);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements ones(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call bamg
+fprintf('%s\n','      call Bamg...');
+system(['bamg -ratio ' num2str(gradation) ' -splitpbedge -nbv 1000000 -M carre0.met -b carre0.mesh -o carre1.mesh']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+A=meshread('carre1.mesh');
+md.mesh.x=A.x;
+md.mesh.y=A.y;
+md.z=zeros(A.nods,1);
+md.mesh.elements=A.index;
+md.mesh.numberofvertices=A.nods;
+md.mesh.numberofelements=A.nels;
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.mesh carre1.mesh.gmsh');
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCallFromMetric.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCallFromMetric.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/BamgCallFromMetric.m	(revision 20176)
@@ -0,0 +1,65 @@
+function md=BamgCallFromMetric(md,metric,gradation),
+%BAMGCALL - call bam
+%
+%   call Bamg and the output mesh is plugged onto the model
+%   -gradation = maximum edge length gradation between 2 elements
+%
+%   Usage:
+%      md=BamgCallFromMetric(md,metric,gradation);
+%
+%   Example:
+%      md=BamgCall(md,metric,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('carre0.met','w');
+fprintf(fid,'%i %i\n',md.mesh.numberofvertices,3);
+fprintf(fid,'%i %i %i\n',metric');
+fclose(fid);
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'%s %i\n','MeshVersionFormatted',0);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements ones(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call bamg
+fprintf('%s\n','      call Bamg...');
+system(['bamg -ratio ' num2str(gradation) ' -splitpbedge -nbv 1000000 -M carre0.met -b carre0.mesh -o carre1.mesh']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+A=meshread('carre1.mesh');
+md.mesh.x=A.x;
+md.mesh.y=A.y;
+md.z=zeros(A.nods,1);
+md.mesh.elements=A.index;
+md.mesh.numberofvertices=A.nods;
+md.mesh.numberofelements=A.nels;
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.mesh carre1.mesh.gmsh');
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.m	(revision 20176)
@@ -0,0 +1,98 @@
+function md=YamsCall(md,field,hmin,hmax,gradation,epsilon),
+%YAMSCALL - call yams
+%
+%   build a metric using the Hessian of the given field
+%   call Yams and the output mesh is plugged onto the model
+%   -hmin = minimum edge length (m)
+%   -hmax = maximum edge length (m)
+%   -gradation = maximum edge length gradation between 2 elements
+%   -epsilon = average error on each element (m/yr)
+%
+%   Usage:
+%      md=YamsCall(md,field,hmin,hmax,gradation,epsilon);
+%
+%   Example:
+%      md=YamsCall(md,md.inversion.vel_obs,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2./9.;
+
+%Compute Hessian
+t1=clock; fprintf('%s','      computing Hessian...');
+hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node');
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%Compute metric
+t1=clock; fprintf('%s','      computing metric...');
+metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,[]);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+save -ascii carre0.met  metric
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'\n%s\n%i\n','MeshVersionFormatted',1);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y zeros(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements zeros(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+
+%Deal with rifts
+if ~isnan(md.rifts.riftstruct),
+
+	%we have the list of triangles that make up the rift. keep those triangles around during refinement.
+	triangles=[];
+	for i=1:size(md.rifts.riftstruct,1),
+		triangles=[triangles md.rifts(i).riftstruct.segments(:,3)'];
+	end
+
+	fprintf(fid,'\n\n%s\n%i\n\n','RequiredTriangles',length(triangles));
+	fprintf(fid,'%i\n',triangles);
+end
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call yams
+fprintf('%s\n','      call Yams...');
+if ispc()
+	%windows
+	system(['yams2-win -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+elseif ismac()
+	%Macosx
+	system(['yams2-osx -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+else
+	%Linux
+	system(['yams2-linux -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+end
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+Tria=load('carre1.tria');
+Coor=load('carre1.coor');
+md.mesh.x=Coor(:,1);
+md.mesh.y=Coor(:,2);
+md.mesh.elements=Tria;
+md.mesh.numberofvertices=size(Coor,1);
+md.mesh.numberofelements=size(Tria,1);
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.tria carre1.coor carre1.meshb');
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.py
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.py	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/YamsCall.py	(revision 20176)
@@ -0,0 +1,123 @@
+import numpy
+import time
+import subprocess
+import os
+from ComputeHessian import ComputeHessian
+from ComputeMetric import ComputeMetric
+
+def YamsCall(md,field,hmin,hmax,gradation,epsilon):
+	"""
+	YAMSCALL - call yams
+
+	   build a metric using the Hessian of the given field
+	   call Yams and the output mesh is plugged onto the model
+	   -hmin = minimum edge length (m)
+	   -hmax = maximum edge length (m)
+	   -gradation = maximum edge length gradation between 2 elements
+	   -epsilon = average error on each element (m/yr)
+
+	   Usage:
+	      md=YamsCall(md,field,hmin,hmax,gradation,epsilon);
+
+	   Example:
+	      md=YamsCall(md,md.inversion.vel_obs,1500,10^8,1.3,0.9);
+	"""
+
+	#2d geometric parameter (do not change)
+	scale=2./9.
+
+	#Compute Hessian
+	t1=time.time()
+	print "%s" % '      computing Hessian...'
+	hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node')
+	t2=time.time()
+	print "%s%d%s\n" % (' done (',t2-t1,' seconds)')
+
+	#Compute metric
+	t1=time.time()
+	print "%s" % '      computing metric...'
+	metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,numpy.empty(0,int))
+	t2=time.time()
+	print "%s%d%s\n" % (' done (',t2-t1,' seconds)')
+
+	#write files
+	t1=time.time()
+	print "%s" % '      writing initial mesh files...'
+	numpy.savetxt('carre0.met',metric)
+
+	f=open('carre0.mesh','w')
+
+	#initialiation
+	f.write("\n%s\n%i\n" % ('MeshVersionFormatted',1))
+
+	#dimension
+	f.write("\n%s\n%i\n" % ('Dimension',2))
+
+	#Vertices
+	f.write("\n%s\n%i\n\n" % ('Vertices',md.mesh.numberofvertices))
+	for i in xrange(0,md.mesh.numberofvertices):
+		f.write("%8g %8g %i\n" % (md.mesh.x[i],md.mesh.y[i],0))
+
+	#Triangles
+	f.write("\n\n%s\n%i\n\n" % ('Triangles',md.mesh.numberofelements))
+	for i in xrange(0,md.mesh.numberofelements):
+		f.write("%i %i %i %i\n" % (md.mesh.elements[i,0],md.mesh.elements[i,1],md.mesh.elements[i,2],0))
+	numberofelements1=md.mesh.numberofelements
+
+	#Deal with rifts
+	if numpy.any(not numpy.isnan(md.rifts.riftstruct)):
+
+		#we have the list of triangles that make up the rift. keep those triangles around during refinement.
+		triangles=numpy.empty(0,int)
+		for riftstruct in md.rifts.riftstruct:
+			triangles=numpy.concatenate((triangles,riftstruct.segments[:,2]))
+
+		f.write("\n\n%s\n%i\n\n" % ('RequiredTriangles',numpy.size(triangles)))
+		for triangle in triangles:
+			f.write("%i\n" % triangle)
+
+	#close
+	f.close()
+	t2=time.time()
+	print "%s%d%s\n" % (' done (',t2-t1,' seconds)')
+
+	#call yams
+	print "%s\n" % '      call Yams...'
+	if   m.ispc():
+		#windows
+		subprocess.call('yams2-win -O 1 -v -0 -ecp -hgrad %g carre0 carre1' % gradation,shell=True)
+	elif ismac():
+		#Macosx
+		subprocess.call('yams2-osx -O 1 -v -0 -ecp -hgrad %g carre0 carre1' % gradation,shell=True)
+	else:
+		#Linux
+		subprocess.call('yams2-linux -O 1 -v -0 -ecp -hgrad %g carre0 carre1' % gradation,shell=True)
+
+	#plug new mesh
+	t1=time.time()
+	print "\n%s" % '      reading final mesh files...'
+	Tria=numpy.loadtxt('carre1.tria',int)
+	Coor=numpy.loadtxt('carre1.coor',float)
+	md.mesh.x=Coor[:,0]
+	md.mesh.y=Coor[:,1]
+	md.mesh.z=numpy.zeros((numpy.size(Coor,axis=0),1))
+	md.mesh.elements=Tria
+	md.mesh.numberofvertices=numpy.size(Coor,axis=0)
+	md.mesh.numberofelements=numpy.size(Tria,axis=0)
+	numberofelements2=md.mesh.numberofelements
+	t2=time.time()
+	print "%s%d%s\n\n" % (' done (',t2-t1,' seconds)')
+
+	#display number of elements
+	print "\n%s %i" % ('      inital number of elements:',numberofelements1)
+	print "\n%s %i\n\n" % ('      new    number of elements:',numberofelements2)
+
+	#clean up:
+	os.remove('carre0.mesh')
+	os.remove('carre0.met')
+	os.remove('carre1.tria')
+	os.remove('carre1.coor')
+	os.remove('carre1.meshb')
+
+	return md
+
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh.m	(revision 20176)
@@ -0,0 +1,48 @@
+function md=gmsh(md,domainfile,h),
+
+%Read domain
+domain=expread(domainfile);
+x   = domain.x(1:end-1);
+y   = domain.y(1:end-1);
+nbv = numel(x);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('model.geo','w');
+fprintf(fid,['// Gmsh input file, created by ISSM on ' date '\n']);
+for i=1:nbv,
+	fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',i,x(i),y(i),0.);
+end
+for i=1:nbv-1
+	fprintf(fid,'Line(%i) = {%i, %i};\n',i,i,i+1);
+end
+fprintf(fid,'Line(%i) = {%i, %i};\n',nbv,nbv,1);
+fprintf(fid,'Line Loop(5) = {');
+for i=1:nbv-1
+	fprintf(fid,'%i,',i);
+end
+fprintf(fid,'%i};\n',nbv);
+fprintf(fid,'Plane Surface(6) = {5};\n');
+
+%Physical lines and surfaces
+fprintf(fid,'Physical Line(2) = {1};\n');
+fprintf(fid,'Physical Line(4) = {2};\n');
+fprintf(fid,'Physical Line(5) = {3};\n');
+fprintf(fid,'Physical Line(1) = {4};\n');
+fprintf(fid,'Physical Surface(7) = {6};\n');
+
+%resolution
+fprintf(fid,'Mesh.CharacteristicLengthMax = %g;',h);
+
+%fprintf(fid,'Plane Surface(7) = {6, 2};\n');
+fclose(fid);
+
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call gmsh
+fprintf('%s\n','      call gmsh...');
+system([issmdir() '/externalpackages/gmsh/install/gmsh -2 model.geo']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+md=importgmsh('model.msh',2);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh3d.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh3d.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/gmsh3d.m	(revision 20176)
@@ -0,0 +1,103 @@
+function md=gmsh3d(md,domainfile,h),
+
+%Read domain
+domain=expread(domainfile);
+x   = domain.x(1:end-1);
+y   = domain.y(1:end-1);
+nbv = numel(x);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('model.geo','w');
+fprintf(fid,['// Gmsh input file, created by ISSM on ' date '\n']);
+
+%Lower points
+for i=1:nbv,
+	fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',i,x(i),y(i),0.);
+end
+%Upper points
+for i=1:nbv,
+	fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',nbv+i,x(i),y(i),1.);
+end
+
+%Lower lines
+for i=1:nbv-1
+	fprintf(fid,'Line(%i) = {%i, %i};\n',i,i,i+1);
+end
+fprintf(fid,'Line(%i) = {%i, %i};\n',nbv,nbv,1);
+%Upper lines
+for i=nbv+1:2*nbv-1
+	fprintf(fid,'Line(%i) = {%i, %i};\n',i,i,i+1);
+end
+fprintf(fid,'Line(%i) = {%i, %i};\n',2*nbv,2*nbv,nbv+1);
+%Side lines
+for i=1:nbv
+	fprintf(fid,'Line(%i) = {%i, %i};\n',2*nbv+i,i,nbv+i);
+end
+
+counter = 3*nbv;
+ps = zeros(nbv+2,1);
+%Lower surface Loop and surface
+counter = counter+1;
+fprintf(fid,['Line Loop(' num2str(counter) ') = {']);
+for i=1:nbv-1
+	fprintf(fid,'%i,',i);
+end
+fprintf(fid,'%i};\n',nbv);
+fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']);
+ps(1)=counter+1;
+counter = counter+1;
+%Upper surface Loop and surface
+counter = counter+1;
+fprintf(fid,['Line Loop(' num2str(counter) ') = {']);
+for i=nbv+1:2*nbv-1
+	fprintf(fid,'%i,',i);
+end
+fprintf(fid,'%i};\n',2*nbv);
+ps(2)=counter+1;
+fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']);
+counter = counter+2;
+%Sides surfaces
+for i=1:nbv-1,
+	fprintf(fid,['Line Loop(' num2str(counter) ') = {' num2str(i) ',' num2str(2*nbv+i+1) ',-' num2str(nbv+i) ',-' num2str(2*nbv+i) '};\n']);
+	fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']);
+	ps(2+i)=counter+1;
+	counter=counter+2;
+end
+fprintf(fid,['Line Loop(' num2str(counter) ') = {' num2str(nbv) ',' num2str(2*nbv+1) ',-' num2str(2*nbv) ',-' num2str(3*nbv) '};\n']);
+fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']);
+ps(2+nbv)=counter+1;
+counter=counter+2;
+
+%Physical surfaces
+counter = counter+1;
+fprintf(fid,['Surface Loop(' num2str(counter) ') = {']);
+for i=1:numel(ps)-1
+	fprintf(fid,'%i,',ps(i));
+end
+fprintf(fid,'%i};\n',ps(end));
+fprintf(fid,['Physical Surface(1) = {' num2str(ps(2)) '};\n']);
+fprintf(fid,['Physical Surface(2) = {' num2str(ps(1)) '};\n']);
+fprintf(fid,['Physical Surface(3) = {']);
+for i=3:numel(ps)-1
+	fprintf(fid,'%i,',ps(i));
+end
+fprintf(fid,'%i};\n',ps(end));
+
+%Volume
+fprintf(fid,['Volume(1) = {' num2str(counter) '};\n']);
+fprintf(fid,['Physical Volume(2) = {1};\n']);
+
+%resolution
+fprintf(fid,'Mesh.CharacteristicLengthMax = %g;',h);
+fclose(fid);
+
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call gmsh
+fprintf('%s\n','      call gmsh...');
+system([issmdir() '/externalpackages/gmsh/install/gmsh -3 -v 0 model.geo']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+md=importgmsh('model.msh',3);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/meshread.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/meshread.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/meshread.m	(revision 20176)
@@ -0,0 +1,41 @@
+function Struct=meshread(filename)
+
+%some checks
+if ~exist(filename),
+	error(['meshread error message: file ' filename ' not found!']);
+end
+
+fid=fopen(filename,'r');
+
+while (~feof(fid)),
+
+	A=fscanf(fid,'%s',1);
+
+	if strcmp(A,'MeshVersionFormatted');
+		Struct.Version=fscanf(fid,'%s',1);
+
+	elseif strcmp(A,'Dimension'),
+		Struct.Dimension=fscanf(fid,'%i',1);
+
+	elseif strcmp(A,'Vertices'),
+		Struct.nods=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%f %f %f',[3 Struct.nods]);
+		Struct.x=A(1,:)';
+		Struct.y=A(2,:)';
+
+	elseif strcmp(A,'Triangles'),
+		Struct.nels=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%i %i %i',[4 Struct.nels]);
+		Struct.index=A(1:3,:)';
+
+	elseif strcmp(A,'Quadrilaterals'),
+		Struct.nels=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%i %i %i %i',[5 Struct.nels]);
+		Struct.index=A(1:4,:)';
+	else
+		%do nothing
+
+	end
+end
+
+fclose(fid);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/bamg/yams.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/bamg/yams.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/bamg/yams.m	(revision 20176)
@@ -0,0 +1,153 @@
+function md=yams(md,varargin)
+%MESHYAMS - Build model of Antarctica by refining according to observed velocity error estimator
+%
+%   Usage:
+%      md=yams(md,varargin);
+%      where varargin is a lit of paired arguments. 
+%      arguments can be: 'domainoutline': Argus file containing the outline of the domain to be meshed
+%      arguments can be: 'velocities': matlab file containing the velocities [m/yr]
+%      optional arguments: 'groundeddomain': Argus file containing the outline of the grounded ice
+%                          this option is used to minimize the metric on water (no refinement)
+%      optional arguments: 'resolution': initial mesh resolution [m]
+%      optional arguments: 'nsteps': number of steps of mesh adaptation
+%      optional arguments: 'epsilon': average interpolation error wished [m/yr]
+%      optional arguments: 'hmin': minimum edge length
+%      optional arguments: 'hmanx': maximum edge
+%      optional arguments: 'riftoutline': if rifts are present, specifies rift outline file.
+%      
+%
+%   Examples:
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat');
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat','groundeddomain','ground.exp');
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat','groundeddomain','ground.exp','nsteps',6,'epsilon',2,'hmin',500,'hmax',30000);
+
+%recover options
+options=pairoptions(varargin{:});
+options=deleteduplicates(options,1);
+
+%recover some fields
+disp('MeshYams Options:')
+domainoutline=getfieldvalue(options,'domainoutline');
+disp(sprintf('   %-15s: ''%s''','DomainOutline',domainoutline));
+riftoutline=getfieldvalue(options,'riftoutline','N/A');
+disp(sprintf('   %-15s: ''%s''','riftoutline',riftoutline));
+groundeddomain=getfieldvalue(options,'groundeddomain','N/A');
+disp(sprintf('   %-15s: ''%s''','GroundedDomain',groundeddomain));
+velocities=getfieldvalue(options,'velocities');
+disp(sprintf('   %-15s: ''%s''','Velocities',velocities));
+resolution=getfieldvalue(options,'resolution',5000);
+disp(sprintf('   %-15s: %f','Resolution',resolution));
+nsteps=getfieldvalue(options,'nsteps',6);
+disp(sprintf('   %-15s: %i','nsteps',nsteps));
+gradation=getfieldvalue(options,'gradation',2*ones(nsteps,1));
+disp(sprintf('   %-15s: %g','gradation',gradation(1)));
+epsilon=getfieldvalue(options,'epsilon',3);
+disp(sprintf('   %-15s: %f','epsilon',epsilon));
+hmin=getfieldvalue(options,'hmin',500);
+disp(sprintf('   %-15s: %f','hmin',hmin));
+hmax=getfieldvalue(options,'hmax',150*10^3);
+disp(sprintf('   %-15s: %f\n','hmax',hmax));
+
+%mesh with initial resolution
+disp('Initial mesh generation...');
+if strcmpi(riftoutline,'N/A');
+	md=setmesh(md,domainoutline,resolution);
+else
+	md=setmesh(md,domainoutline,riftoutline,resolution);
+	md=meshprocessrifts(md,domainoutline);
+end
+disp(['Initial mesh, number of elements: ' num2str(md.mesh.numberofelements)]);
+
+%load velocities 
+disp('loading velocities...');
+Names=VelFindVarNames(velocities);
+Vel=load(velocities);
+
+%start mesh adaptation
+for i=1:nsteps,
+	disp(['Iteration #' num2str(i) '/' num2str(nsteps)]);
+
+	%interpolate velocities onto mesh
+	disp('   interpolating velocities...');
+	if strcmpi(Names.interp,'node'),
+		vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+		vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+	else
+		vx_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+		vy_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+	end
+	field=sqrt(vx_obs.^2+vy_obs.^2);
+
+	%adapt according to velocities
+	disp('   adapting...');
+	md=YamsCall(md,field,hmin,hmax,gradation(i),epsilon);
+
+	%if we have rifts, we just messed them up, we need to recreate the segments that constitute those 
+	%rifts, because the segments are used in YamsCall to freeze the rifts elements during refinement.
+	if md.rifts.numrifts, 
+		md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+		md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+		md.mesh.segments=findsegments(md);
+		md=yamsrecreateriftsegments(md);
+	end
+
+end
+
+disp(['Final mesh, number of elements: ' num2str(md.mesh.numberofelements)]);
+
+%Now, build the connectivity tables for this mesh.
+md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+
+%recreate segments
+md.mesh.segments=findsegments(md);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+
+%Fill in rest of fields:
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonbase=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+if strcmpi(Names.interp,'node'),
+	md.inversion.vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+	md.inversion.vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+else
+	md.inversion.vx_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+	md.inversion.vy_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+end
+md.inversion.vel_obs=sqrt(md.inversion.vx_obs.^2+md.inversion.vy_obs.^2);
+
+%deal with rifts 
+if md.rifts.numrifts,
+	%first, recreate rift segments
+	md=meshyamsrecreateriftsegments(md);
+
+	%using the segments, recreate the penaltypairs
+	for j=1:md.rifts.numrifts,
+		rift=md.rifts.riftstruct(j);
+
+		%build normals and lengths of segments:
+		lengths=sqrt((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))).^2 + (md.mesh.y(rift.segments(:,1))-md.mesh.y(rift.segments(:,2))).^2 );
+		normalsx=cos(atan2((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))) , (md.mesh.y(rift.segments(:,2))-md.mesh.y(rift.segments(:,1)))));
+		normalsy=sin(atan2((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))) , (md.mesh.y(rift.segments(:,2))-md.mesh.y(rift.segments(:,1)))));
+
+		%ok, build penaltypairs: 
+		numpenaltypairs=length(rift.segments)/2-1;
+		rift.penaltypairs=zeros(numpenaltypairs,7);
+
+		for i=1:numpenaltypairs,
+			rift.penaltypairs(i,1)=rift.segments(i,2);
+			rift.penaltypairs(i,2)=rift.segments(end-i,2);
+			rift.penaltypairs(i,3)=rift.segments(i,3);
+			rift.penaltypairs(i,4)=rift.segments(end-i,3);
+			rift.penaltypairs(i,5)=normalsx(i)+normalsx(i+1);
+			rift.penaltypairs(i,6)=normalsy(i)+normalsy(i+1);
+			rift.penaltypairs(i,7)=(lengths(i)+lengths(i+1))/2;
+		end
+		%renormalize norms: 
+		norms=sqrt(rift.penaltypairs(:,5).^2+rift.penaltypairs(:,6).^2);
+		rift.penaltypairs(:,5)=rift.penaltypairs(:,5)./norms;
+		rift.penaltypairs(:,6)=rift.penaltypairs(:,6)./norms;
+
+		md.rifts.riftstruct(j)=rift;
+	end
+end
Index: /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/exportgmsh.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/exportgmsh.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/exportgmsh.m	(revision 20176)
@@ -0,0 +1,52 @@
+function exportgmsh(mesh,groundedice_levelset,filename),
+%EXPORTGMSH - export mesh to gmsh format
+%
+%   http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format
+%
+%   Usage:
+%      exportgmsh(mesh,groundedice_levelset,filename)
+%
+%   Example:
+%      exportgmsh(md.mesh,md.mask.groundedice_levelset,'temp.msh')
+
+fid=fopen(filename,'w');
+
+%Header
+fprintf(fid,'$MeshFormat\n');
+fprintf(fid,'2.2 0 8\n');
+fprintf(fid,'$EndMeshFormat\n');
+
+%Vertices
+nbv = mesh.numberofvertices;
+fprintf(fid,'$Nodes\n');
+fprintf(fid,'%i\n',nbv);
+fprintf(fid,'%i %8g %8g %8g\n',[[1:nbv]' mesh.x mesh.y zeros(nbv,1)]');
+fprintf(fid,'$EndNodes\n');
+
+%Boundary Elements first
+nbe     = mesh.numberofelements;
+nbs     = size(mesh.segments,1);
+segment = 1;
+tria    = 2;
+
+%Create flags
+grounded = sum(groundedice_levelset(mesh.segments(:,1:2))>0,2);
+A = zeros(nbs,2);
+pos = find(mesh.segmentmarkers==4);
+A(pos,:)=repmat([1,4],[numel(pos) 1]);
+pos = find(mesh.segmentmarkers==1 &  grounded);
+A(pos,:)=repmat([2,1],[numel(pos) 1]);
+pos = find(mesh.segmentmarkers==1 & ~grounded);
+A(pos,:)=repmat([3,5],[numel(pos) 1]);
+pos = find(mesh.segmentmarkers==2);
+A(pos,:)=repmat([4,2],[numel(pos) 1]);
+pos = find(mesh.segmentmarkers==3);
+A(pos,:)=repmat([5,3],[numel(pos) 1]);
+
+fprintf(fid,'$Elements\n');
+fprintf(fid,'%i\n',nbe+nbs);
+fprintf(fid,'%i %i %i %i %i %i %i\n',[[1    :nbs    ]' segment*ones(nbs,1) 2*ones(nbs,1) A mesh.segments(:,1:2)]');
+fprintf(fid,'%i %i %i %i %i %i %i %i\n',[[nbs+1:nbs+nbe]' tria*ones(nbe,1) 2*ones(nbe,1) 7*ones(nbe,1) 6*ones(nbe,1) mesh.elements]');
+fprintf(fid,'$EndElements\n');
+
+fclose(fid);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/importgmsh.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/importgmsh.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/dassflow/importgmsh.m	(revision 20176)
@@ -0,0 +1,155 @@
+function md = importgmsh(filename,dim)
+
+%some checks
+if ~exist(filename),
+	error(['expread error message: file ' filename ' not found!']);
+end
+
+%open file
+fid=fopen(filename,'r');
+
+%Get Mesh format
+A=fscanf(fid,'%s',1);
+if ~strcmp(A,'$MeshFormat'), 
+	error(['Expecting $MeshFormat (' A ')']);
+end
+A=fscanf(fid,'%f %i %i',[1 3]);
+A=fscanf(fid,'%s',1);
+if ~strcmp(A,'$EndMeshFormat'), 
+	error(['Expecting $EndMeshFormat (' A ')']);
+end
+
+%Nodes
+A=fscanf(fid,'%s',1);
+if ~strcmp(A,'$Nodes'), 
+	error(['Expecting $Nodes (' A ')']);
+end
+nbv=fscanf(fid,'%i',1);
+disp(['Number of nodes: ' num2str(nbv) ]);
+A=fscanf(fid,'%i %f %f %f',[4 nbv]);
+x = A(2,:)';
+y = A(3,:)';
+z = A(4,:)';
+
+A=fscanf(fid,'%s',1);
+if ~strcmp(A,'$EndNodes'), 
+	error(['Expecting $EndNodes (' A ')']);
+end
+
+%Elements
+A=fscanf(fid,'%s',1);
+if ~strcmp(A,'$Elements'), 
+	error(['Expecting $Elements (' A ')']);
+end
+nbt=fscanf(fid,'%i',1);
+disp(['Number of elements: ' num2str(nbt) ]);
+counter = 0;
+if (dim==2),
+	index   = zeros(0,3);
+	segments       = zeros(0,2);
+	segmentmarkers = zeros(0,1);
+elseif (dim==3),
+	index   = zeros(0,4);
+	segments       = zeros(0,3);
+	segmentmarkers = zeros(0,1);
+else
+	error('not supported');
+end
+
+while(counter<nbt);
+	id = fscanf(fid,'%i',1);
+	ty = fscanf(fid,'%i',1);
+	nbf = fscanf(fid,'%i',1);
+	flags = fscanf(fid,'%i',nbf);
+
+	switch(ty)
+		case 1, %segments
+			A=fscanf(fid,'%i %i',2);
+			if (dim==2),  %Actual element
+				segments(end+1,:)=A;
+				if    (flags(1)==5 & flags(2)==3), segmentmarkers(end+1)=3; 
+				elseif(flags(1)==1 & flags(2)==4), segmentmarkers(end+1)=4;
+				elseif(flags(1)==2 & flags(2)==1), segmentmarkers(end+1)=1;
+				elseif(flags(1)==4 & flags(2)==2), segmentmarkers(end+1)=2;
+				else error(['flags ' num2str(flags') ' not supported']);
+				end
+			else
+				error('not supported');
+			end
+		case 2, %tria
+			A=fscanf(fid,'%i %i %i',3);
+			if (dim==2), %Actual element
+				index(end+1,:)=A;
+			else         %Boundary element
+				segments(end+1,:)=A;
+				if    (flags(1)==1), segmentmarkers(end+1)=1; 
+				elseif(flags(1)==2), segmentmarkers(end+1)=2;
+				elseif(flags(1)==3), segmentmarkers(end+1)=3;
+				elseif(flags(1)==4), segmentmarkers(end+1)=4;
+				else error(['flags ' num2str(flags') ' not supported']);
+				end
+			end
+		case 4, %tetra
+			A=fscanf(fid,'%i %i %i %i',4);
+			if (dim==3), %Actual element
+				index(end+1,:)=A;
+			else
+				error('not supported');
+			end
+		case 15, %point
+			A=fscanf(fid,'%i',1);
+			continue;
+		otherwise,
+			error(['Type ' num2str(ty) ' not supported']);
+	end
+	counter = counter + 1;
+end
+
+%recreate segments
+if dim==2,
+	nbs = size(segments,1);
+	segments = [segments zeros(nbs,1)];
+	for i=1:nbs,
+		E = find(sum(ismember(index,segments(i,:)),2)>1);
+		segments(i,3)=E;
+	end
+else
+	nbs = size(segments,1);
+	segments = [segments zeros(nbs,1)];
+	for i=1:nbs,
+		E = find(sum(ismember(index,segments(i,:)),2)>2);
+		segments(i,4)=E;
+	end
+end
+
+%close file
+fclose(fid);
+
+%Create model
+if dim==2, %2d triangles
+	md=meshconvert(model,index,x,y);
+	md.mesh=mesh2dvertical(md.mesh);
+	md.mesh.segmentmarkers=segmentmarkers;
+	md.mesh.segments=segments;
+	md.mesh.vertexonbase=zeros(md.mesh.numberofvertices,1);
+	md.mesh.vertexonbase(find(vertexflags(md.mesh,1)))=1;
+	md.mesh.vertexonsurface=zeros(md.mesh.numberofvertices,1);
+	md.mesh.vertexonsurface(find(vertexflags(md.mesh,3)))=1;
+else
+	md=model();
+	md.mesh=mesh3dtetras();
+	md.mesh.x = x;
+	md.mesh.y = y;
+	md.mesh.z = z;
+	md.mesh.elements = index;
+	md.mesh.numberofelements=size(md.mesh.elements,1);
+	md.mesh.numberofvertices=length(md.mesh.x);
+
+	%base 2, surface 1, inflow 3, outflow 4
+	md.mesh.vertexonbase=zeros(md.mesh.numberofvertices,1);
+	md.mesh.vertexonbase(segments(find(segmentmarkers==2),1:3))=1;
+	md.mesh.vertexonsurface=zeros(md.mesh.numberofvertices,1);
+	md.mesh.vertexonsurface(segments(find(segmentmarkers==1),1:3))=1;
+	md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1);
+	md.mesh.vertexonboundary(segments(:,1:3))=1;
+end
Index: /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gamv.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gamv.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gamv.m	(revision 20176)
@@ -0,0 +1,70 @@
+function output = gamv(x,y,data,varargin)
+%GAMV - use gslib for Kriging
+%
+%   Usage:
+%      output = gamv(x,y,data,varargin)
+
+options=pairoptions(varargin{:});
+
+nlag = getfieldvalue(options,'nlag', 20);
+dlag = getfieldvalue(options,'dlag', 1000);
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+%Write parameter file
+fid=fopen('gamv.par','w');
+fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+fprintf(fid,'\t\t\t\t%s\n','*******************');
+fprintf(fid,'\n');
+fprintf(fid,'%s\n','START OF PARAMETERS:');
+fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\columns for X, Y, Z coordinates');
+fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+fprintf(fid,'%-30s %s\n','gamv.out'                   ,'\file for variogram output');
+fprintf(fid,'%-30s %s\n',num2str(nlag,'%i')           ,'\number of lags');
+fprintf(fid,'%-30s %s\n',num2str(dlag,'%g')           ,'\lag separation distance');
+fprintf(fid,'%-30s %s\n',num2str(dlag/2,'%g')         ,'\lag tolerance');
+fprintf(fid,'%-30s %s\n','3'                          ,'\number of directions');
+fprintf(fid,'%-30s %s\n','0.0 90.0 50.0 0.0 90.0 50.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','0.0 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','90. 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+fprintf(fid,'%-30s %s\n','2'                          ,'\number of variograms');
+fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail var., head vars., variogram type');
+fprintf(fid,'%-30s %s\n','1 1 3'                      ,'\tail var., head vars., variogram type');
+fclose(fid);
+
+%Call gamv
+system([issmdir() '/externalpackages/gslib/install/gamv gamv.par']);
+delete('gamv.par');
+
+%Read output
+output   = struct('Semivariogram',[],'Covariance',[]);
+counter1 = 1;
+counter2 = 1;
+fid=fopen('gamv.out','r');
+while (~feof(fid)),
+	A=fscanf(fid,'%s',1);
+	if strcmp(A,'Covariance');
+		A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction  2
+		output(counter1).Covariance=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])';
+		counter1=counter1+1;
+	elseif strcmp(A,'Semivariogram'),
+		A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction  2
+		output(counter2).Semivariogram=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])';
+		counter2=counter2+1;
+	else
+		%do nothing
+	end
+end
+fclose(fid);
+delete('gamv.out')
Index: /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gslib.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gslib.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/gslib/gslib.m	(revision 20176)
@@ -0,0 +1,107 @@
+function [B E] = gslib(x,y,data,xmin,ymin,nx,ny,deltax,deltay,varargin)
+%GSLIB - use gslib for Kriging
+%
+%   Usage:
+%      output = gslib(x,y,data,varargin)
+
+%process options
+options = pairoptions(varargin{:});
+
+%Variogram
+nugget= getfieldvalue(options,'nugget',10);
+sill  = getfieldvalue(options,'sill',164);
+range = getfieldvalue(options,'range',25763);
+
+%Kriging options
+mindata = getfieldvalue(options,'mindata',1);
+maxdata = getfieldvalue(options,'maxdata',50);
+maxsearchradius = getfieldvalue(options,'searchrange',50000);
+
+%Some intermediaries (Convert to gslib's parameters);
+c = (sill-nugget);
+a = sqrt(3)*range;
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+if 0, %GAMV
+	%Write parameter file
+	fid=fopen('gamv.par','w');
+	fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+	fprintf(fid,'\t\t\t\t%s\n','*******************');
+	fprintf(fid,'\n');
+	fprintf(fid,'%s\n','START OF PARAMETERS:');
+	fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+	fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\columns for X, Y, Z coordinates');
+	fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+	fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+	fprintf(fid,'%-30s %s\n','gamv.out'                   ,'\file for variogram output');
+	fprintf(fid,'%-30s %s\n','20'                         ,'\number of lags');
+	fprintf(fid,'%-30s %s\n','5.0'                        ,'\lag separation distance');
+	fprintf(fid,'%-30s %s\n','3.0'                        ,'\lag tolerance');
+	fprintf(fid,'%-30s %s\n','3'                          ,'\number of directions');
+	fprintf(fid,'%-30s %s\n','0.0 90.0 50.0 0.0 90.0 50.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','0.0 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','90. 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+	fprintf(fid,'%-30s %s\n','2'                          ,'\number of variograms');
+	fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail var., head vars., variogram type');
+	fprintf(fid,'%-30s %s\n','1 1 3'                      ,'\tail var., head vars., variogram type');
+	fclose(fid);
+
+	%Call gamv
+	system([issmdir() '/externalpackages/gslib/install/gamv gamv.par']);
+
+else, %Kriging KB2D
+	%Write parameter file
+	fid=fopen('kb2d.par','w');
+	fprintf(fid,'\t\t\t\t%s\n','Parameters for KB2D');
+	fprintf(fid,'\t\t\t\t%s\n','*******************');
+	fprintf(fid,'\n');
+	fprintf(fid,'%s\n','START OF PARAMETERS:');
+	fprintf(fid,'%-30s %s\n','./cluster.dat'                  ,'\file with data');
+	fprintf(fid,'%-30s %s\n','1 2 3'                          ,'\columns for X, Y and variable');
+	fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'                 ,'\trimming limits');
+	fprintf(fid,'%-30s %s\n','0'                              ,'\debugging level: 0,1,2,3');
+	fprintf(fid,'%-30s %s\n','kb2d.dbg'                       ,'\file for debuggging output');
+	fprintf(fid,'%-30s %s\n','kb2d.out'                       ,'\file for kriged output');
+	fprintf(fid,'%-30s %s\n',num2str([nx xmin deltax],'%i %10g %6g')  ,'\nx, xmn, xsiz');
+	fprintf(fid,'%-30s %s\n',num2str([ny ymin deltay],'%i %10g %6g')  ,'\nx, xmn, xsiz');
+	fprintf(fid,'%-30s %s\n','1 1'                            ,'\x and y block discretization');
+	fprintf(fid,'%-30s %s\n',num2str([mindata maxdata],'%6g') ,'\min and max data for kriging');
+	fprintf(fid,'%-30s %s\n',num2str(maxsearchradius,'%6g')   ,'\max search radius');
+	fprintf(fid,'%-30s %s\n','1 2.302'                        ,'\0=SK, 1=OK, (mean if SK)');
+	fprintf(fid,'%-30s %s\n',['1 ' num2str(nugget)]           ,'\nst, nugget effect');
+	fprintf(fid,'%-30s %s\n',['3 ' num2str([c 0.0 a a],'%10g')],'\it, c, azm, a_max, a_min');
+	fclose(fid);
+
+	tic;system([issmdir() '/externalpackages/gslib/install/kb2d kb2d.par']);toc;
+	delete('kb2d.par');
+
+	%Read output
+	fid=fopen('kb2d.out','r');
+	while (~feof(fid)),
+		A=fscanf(fid,'%s',1);
+		if strcmp(A,'KB2D');
+			A=fscanf(fid,'%s',1); %Read output
+			params=fscanf(fid,'%i %i %i %i %g %g %g %g %g %g %1',[11 1]);
+		elseif strcmp(A,' Estimate'),
+			continue;
+		elseif strcmp(A,'Estimation'),
+			A=fscanf(fid,'%s',1); %Read Variance
+			A=fscanf(fid,'%g %g',[params(1) params(2)*params(3)]);
+			B=A(1,:); B=reshape(B,[params(3),params(2)])';
+			E=A(2,:); E=reshape(E,[params(3),params(2)])';
+		else
+			%do nothing
+		end
+	end
+	fclose(fid);
+end
Index: /issm/trunk-jpl/src/m/contrib/morlighem/gslib/pkriging.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/gslib/pkriging.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/gslib/pkriging.m	(revision 20176)
@@ -0,0 +1,66 @@
+function [B E]=pkriging(x,y,observations,x_interp,y_interp,varargin)
+%PKRIGING - parallel Kriging
+%
+%   Usage:
+%      [B E]=pkriging(x,y,observations,x_interp,y_interp,varargin);
+
+options=pairoptions(varargin{:});
+cluster=getfieldvalue(options,'cluster',generic('np',1));
+options=removefield(options,'cluster',0);
+name   = ['krig' num2str(feature('GetPid'))];
+
+if 1,
+% =========================================   MARSHALL.m =================================================
+disp(['marshalling file ' name '.bin']);
+fid=fopen([name '.bin'],'wb');
+if fid==-1,
+	error(['marshall error message: could not open ' name '.bin file for binary writing']);
+end
+
+%First, write MaximumNumberOfDefinitionsEnum to make sure that the Enums are synchronized
+WriteData(fid,'enum',MaximumNumberOfDefinitionsEnum(),'data',true,'format','Boolean');
+
+%Write all data
+WriteData(fid,'enum',0,'data',x,'format','DoubleMat');
+WriteData(fid,'enum',1,'data',y,'format','DoubleMat');
+WriteData(fid,'enum',2,'data',observations,'format','DoubleMat');
+WriteData(fid,'enum',3,'data',x_interp,'format','DoubleMat');
+WriteData(fid,'enum',4,'data',y_interp,'format','DoubleMat');
+
+%Last, write MaximumNumberOfEnum+1 to make sure that the binary file is not corrupt
+WriteData(fid,'enum',MaximumNumberOfDefinitionsEnum()+1,'data',true,'format','Boolean');
+
+%Now, write number of options
+options.marshall(fid,5);
+st=fclose(fid);
+if st==-1,
+	error(['marshall error message: could not close file ' name '.bin']);
+end
+% =========================================   MARSHALL.m =================================================
+
+%Launch job on remote cluster
+BuildKrigingQueueScript(cluster,name,'',1,0,0); %gather, valgrind, gprof
+UploadQueueJob(cluster,name,name,{[name '.bin'] [name '.queue']})
+LaunchQueueJob(cluster,name,name,{[name '.bin'] [name '.queue']},'');
+
+%Call waitonlock
+md=model; md.cluster=cluster; md.settings.waitonlock=Inf; md.private.runtimename=name;md.miscellaneous.name=name;
+waitonlock(md);
+
+%Download
+end
+Download(cluster,name,{[name '.outbin']});
+structure=parseresultsfromdisk([name '.outbin'],0);
+delete([name '.outlog']);
+delete([name '.errlog']);
+delete([name '.outbin']);
+delete([name '.bin']);
+if ~ispc(),
+	delete([name '.tar.gz']);
+end
+
+%Process results
+B=structure.(EnumToString(0));
+B=reshape(B,size(x_interp,2),size(x_interp,1))';
+E=structure.(EnumToString(1));
+E=reshape(E,size(x_interp,2),size(x_interp,1))';
Index: /issm/trunk-jpl/src/m/contrib/morlighem/gslib/varmap.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/gslib/varmap.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/gslib/varmap.m	(revision 20176)
@@ -0,0 +1,55 @@
+function output = varmap(x,y,data,varargin)
+%VARMAP - use gslib for Kriging
+%
+%   Usage:
+%      output = varmap(x,y,data,varargin)
+
+options=pairoptions(varargin{:});
+
+nxlag = getfieldvalue(options,'nxlag', 20);
+nylag = getfieldvalue(options,'nylag', 20);
+dxlag = getfieldvalue(options,'dxlag', 1000);
+dylag = getfieldvalue(options,'dylag', 1000);
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+%Write parameter file
+fid=fopen('varmap.par','w');
+fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+fprintf(fid,'\t\t\t\t%s\n','*******************');
+fprintf(fid,'\n');
+fprintf(fid,'%s\n','START OF PARAMETERS:');
+fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+fprintf(fid,'%-30s %s\n','0    '                      ,'\1=regular grid, 0=scattered values');
+fprintf(fid,'%-30s %s\n','50 50 1'                    ,'\if =1: nx, ny, nz');
+fprintf(fid,'%-30s %s\n','1.0 1.0 1.0'                ,'\       xsiz, ysiz, zsiz if igrid=1');
+fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\if =0: columns for x, y and z coordinates');
+fprintf(fid,'%-30s %s\n','varmap.out'                 ,'\file for variogram output');
+fprintf(fid,'%-30s %s\n',num2str([nxlag nylag 0],'%i '),'\nxlag, nylag, nzlag');
+fprintf(fid,'%-30s %s\n',num2str([dxlag dylag 1],'%g %g %i'),'\dxlag, dylag, dzlag');
+fprintf(fid,'%-30s %s\n','5'                          ,'\minimum number of pairs');
+fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+fprintf(fid,'%-30s %s\n','1'                          ,'\number of variograms');
+fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail, head, variogram type');
+fclose(fid);
+
+%Call varmap
+system([issmdir() '/externalpackages/gslib/install/varmap varmap.par']);
+delete('varmap.par');
+
+%Read output
+fid=fopen('varmap.out','r');
+A = textscan(fid,'%f %f %f %f %f %f','headerlines',8);
+fclose(fid);
+delete('varmap.out')
+output = reshape(A{1},[2*nxlag+1 2*nylag+1]);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/contourmassbalance.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/contourmassbalance.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/contourmassbalance.m	(revision 20176)
@@ -0,0 +1,45 @@
+function dhdt=contourmassbalance(md,file)
+%CONTOURMASSBALANCE - compute the mass balance on a contour
+%
+%   Usage:
+%      dhdt=contourmassbalance(md,file)
+
+%some checks
+if nargin~=2,
+	help contourmassbalance
+	error('contourmassbalance error message: bad usage');
+end
+if ((length(md.initialization.vx)~=md.mesh.numberofvertices)|(length(md.initialization.vy)~=md.mesh.numberofvertices))
+	error(['thicknessevolution error message: vx and vy should have a length of ' num2str(md.mesh.numberofvertices)])
+end
+if ~exist(file),
+	error(['thicknessevolution error message: file ' file ' not found']);
+end
+
+%Get segments enveloping contour
+segments=contourenvelope(md.mesh,file);
+%md.stressbalance.icefront=segments; plotmodel(md,'data','pressureload','expdisp',file);
+
+%get flag list of elements and nodes inside the contour
+nodein=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,file,'node',1);
+elemin=(sum(nodein(md.mesh.elements),2)==size(md.mesh.elements,2));
+
+%conputing Mass flux
+x=md.mesh.x;
+y=md.mesh.y;
+vx=mean(md.initialization.vx(segments(:,1:end-1)),2);
+vy=mean(md.initialization.vy(segments(:,1:end-1)),2);
+H=mean(md.geometry.thickness(segments(:,1:end-1)),2);
+nx=cos(atan2((x(segments(:,1))-x(segments(:,2))) , (y(segments(:,2))-y(segments(:,1)))));
+ny=sin(atan2((x(segments(:,1))-x(segments(:,2))) , (y(segments(:,2))-y(segments(:,1)))));
+L=sqrt((x(segments(:,1))-x(segments(:,2))).^2+(y(segments(:,2))-y(segments(:,1))).^2);
+flux = - md.materials.rho_ice*sum(L.*H.*(vx.*nx+vy.*ny)); %outflux is negative!
+disp(['mass outflux on ' file ' = ' num2str(-flux/10^9) ' Gt/yr']);
+areas=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+dhdt=flux/(sum(areas(find(elemin)))*md.materials.rho_ice);
+disp(['dhdt on ' file ' (Flux  method) = ' num2str(dhdt) ' m/yr']);
+
+dhdt=thicknessevolution(md);
+in=find(elemin);
+dhdt=sum(dhdt(in).*areas(in))/sum(areas(in));
+disp(['dhdt on ' file ' (divHV method) = ' num2str(dhdt) ' m/yr']);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/divergence.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/divergence.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/divergence.m	(revision 20176)
@@ -0,0 +1,27 @@
+function div=divergence(md,a,b)
+%DIVERGENCE - divergence of [a;b] vector, using model's triangulation.
+%
+%   Usage:
+%      div=divergence(md,a,b)
+
+if (dimension(md.mesh)==2),
+	numberofelements=md.mesh.numberofelements;
+	numberofnodes=md.mesh.numberofvertices;
+	index=md.mesh.elements;
+	x=md.mesh.x; y=md.mesh.y; z=md.mesh.z;
+else
+	numberofelements=md.mesh.numberofelements2d;
+	numberofnodes=md.mesh.numberofvertices2d;
+	index=md.mesh.elements2d;
+	x=md.mesh.x2d; y=md.mesh.y2d;
+end
+
+%compute nodal functions coefficients N(x,y)=alpha x + beta y + gamma
+[alpha beta]=GetNodalFunctionsCoeff(index,x,y);
+
+summation=[1;1;1];
+dx=(a(index).*alpha)*summation;
+dy=(b(index).*beta)*summation;
+
+div=dx+dy;
+div=averaging(md,div,1);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflow.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflow.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflow.m	(revision 20176)
@@ -0,0 +1,18 @@
+function flag=outflow(md)
+%OUTFLOW - flag nodes on outflux boundary
+%
+%   Usage:
+%      flag=outflow(md);
+
+A=md.mesh.segments(:,1);
+B=md.mesh.segments(:,2);
+Nx=-(md.mesh.y(A)-md.mesh.y(B));
+Ny=  md.mesh.x(A)-md.mesh.x(B);
+Vx=(md.initialization.vx(A)+md.initialization.vx(B))/2;
+Vy=(md.initialization.vy(A)+md.initialization.vy(B))/2;
+
+%dot product
+VdotN=Vx.*Nx+Vy.*Ny;
+
+flag=zeros(md.mesh.numberofvertices,1);
+flag(A(find(VdotN>0)))=1;
Index: /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflux.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflux.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/massbalance/outflux.m	(revision 20176)
@@ -0,0 +1,48 @@
+function flux=outflux(md,varargin)
+%OUTFLUX - flag nodes on outflux boundary
+%
+%   Usage:
+%      flag=outflow(md);
+%      flag=outflow(md,step);
+
+A=md.mesh.segments(:,1);
+B=md.mesh.segments(:,2);
+
+lx=-(md.mesh.y(A)-md.mesh.y(B));
+ly=  md.mesh.x(A)-md.mesh.x(B);
+L=sqrt(lx.^2+ly.^2);
+Nx=lx./L;
+Ny=ly./L;
+
+if nargin==1,
+	if dimension(md.mesh)==3,
+		vxa=DepthAverage(md,md.initialization.vx);
+		vya=DepthAverage(md,md.initialization.vy);
+	else
+		vxa=md.initialization.vx;
+		vya=md.initialization.vy;
+	end
+	Vx=(vxa(A)+vxa(B))/2;
+	Vy=(vya(A)+vya(B))/2;
+	H=(md.geometry.thickness(A)+md.geometry.thickness(B))/2;
+else
+	step=varargin{1};
+	if dimension(md.mesh)==3,
+		vxa=DepthAverage(md,md.results.TransientSolution(step).Vx);
+		vya=DepthAverage(md,md.results.TransientSolution(step).Vy);
+	else
+		vxa=md.results.TransientSolution(step).Vx;
+		vya=md.results.TransientSolution(step).Vy;
+	end
+	Vx=(vxa(A)+vxa(B))/2;
+	Vy=(vya(A)+vya(B))/2;
+	H=(md.results.TransientSolution(step).Thickness(A)+md.results.TransientSolution(step).Thickness(B))/2;
+end
+
+%dot product
+HVdotN=H.*(Vx.*Nx+Vy.*Ny).*L;
+
+%plot_scatter(md.mesh.x(A),md.mesh.y(A),md.materials.rho_ice*HVdotN,'MarkerSize',4);
+flux=md.materials.rho_ice*sum(HVdotN)/10^12;
+
+disp(['Out flux is ' num2str(flux) ' Gt/yr'])
Index: /issm/trunk-jpl/src/m/contrib/morlighem/sia.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/sia.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/sia.m	(revision 20176)
@@ -0,0 +1,26 @@
+function [velx,vely,vel]=sia(md)
+%SIA - computation of Shallow Ice velocities
+%
+%   This routine uses the model of SIA to compute the velocities
+%   of a 2d model using the surface slope
+%
+%   Usage:
+%      [velx,vely,vel]=sia(md)
+
+if md.mesh.dimension~=2,
+	error('Only 2d meshes are allowed to compute velocity balances');
+end
+
+%Get slope
+[sx,sy,s]=slope(md);
+
+%Average thickness and B over all elements.
+summer=[1;1;1];
+hel=md.geometry.thickness(md.mesh.elements)*summer/3;
+Bel=md.materials.rheology_B(md.mesh.elements)*summer/3;
+
+Ael=Bel.^(-3);
+
+velx=-2*(md.materials.rho_ice*md.constants.g)^3*s.^2.*sx.*Ael/4.*hel.^4;
+vely=-2*(md.materials.rho_ice*md.constants.g)^3*s.^2.*sy.*Ael/4.*hel.^4;
+vel=sqrt(velx.^2+vely.^2);
Index: /issm/trunk-jpl/src/m/contrib/morlighem/thicknessevolution.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/morlighem/thicknessevolution.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/morlighem/thicknessevolution.m	(revision 20176)
@@ -0,0 +1,28 @@
+function dhdt=thicknessevolution(md)
+%THICKNESSEVOLUTION - compute the new thickness of a model after ∆t
+%
+%   This routine compute the new thickness of a model after a time step
+%   according to the following formula:
+%   dh/dt=-div(Hu)
+%
+%   Usage:
+%      dhdt=thicknessevolution(md)
+
+if (length(md.initialization.vx)~=md.mesh.numberofvertices)|(length(md.initialization.vy)~=md.mesh.numberofvertices)
+	error(['thicknessevolution error message: vx and vy should have a length of ' num2str(md.mesh.numberofvertices)])
+end
+
+%load some variables 
+H=md.geometry.thickness;
+vx=md.initialization.vx;
+vy=md.initialization.vy;
+index=md.mesh.elements;
+
+%compute nodal functions coefficients N(x,y)=alpha x + beta y + gamma
+[alpha beta]=GetNodalFunctionsCoeff(md.mesh.elements,md.mesh.x,md.mesh.y); 
+
+%compute dhdt=div(Hu)
+summation=1/3*ones(3,1);
+dhdt=(vx(index)*summation).*sum( H(index).*alpha,2) + (vy(index)*summation).*sum(H(index).*beta,2) ...
+	+ ( H(index)*summation).*sum(vx(index).*alpha,2) + ( H(index)*summation).*sum(vy(index).*beta,2);
+dhdt=-dhdt;
Index: /issm/trunk-jpl/src/m/contrib/seroussi/oasis/carter.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/seroussi/oasis/carter.m	(revision 20176)
+++ /issm/trunk-jpl/src/m/contrib/seroussi/oasis/carter.m	(revision 20176)
@@ -0,0 +1,28 @@
+function attenuation=carter(temperature)
+%CARTER - attenuation as a function of temperature
+%
+%   TWO WAY - Attenuation (in dB/m) as a function of temperature (K)
+%   From Carter at al. 2007 (Radar-based subglacial lake classification in Antarctica)
+%   Figure 4
+%
+%   Usage:
+%      attenuation=carter(temperature)
+
+if(temperature<0)
+	error('input temperature should be in Kelvin (positive)');
+end
+T=temperature-273.15;
+
+Temp=[-50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0]';
+A=[0.0015 0.002 0.003 0.0042 0.0055 0.0083 0.012 0.0175 0.026 0.038 0.055]';
+
+%Now, do a cubic fit between Temp and B: 
+[cfun,gof,output]=fit(Temp,A,'cubicspline');
+%breaks=cfun.p.breaks;
+%coeff=cfun.p.coefs;
+
+%Calculate attenuation
+attenuation=cfun(T);
+
+%Make it a 2 way attenuation
+attenuation=2*attenuation;
