Index: /issm/trunk-jpl/src/c/classes/DofIndexing.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/DofIndexing.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/DofIndexing.cpp	(revision 12821)
@@ -0,0 +1,210 @@
+/*!\file DofIndexing.c
+ * \brief: implementation of the DofIndexing object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include "./objects.h"
+#include <string.h>
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../Container/Container.h"
+#include "../include/include.h"
+
+/*DofIndexing constructors and destructor*/
+/*FUNCTION DofIndexing::DofIndexing(){{{*/
+DofIndexing::DofIndexing(){
+
+	this->gsize=UNDEF;
+	this->fsize=UNDEF;
+	this->ssize=UNDEF;
+	this->clone=0;
+	this->f_set=NULL;
+	this->s_set=NULL;
+	this->svalues=NULL;
+	this->doftype=NULL;
+	this->gdoflist=NULL;
+	this->fdoflist=NULL;
+	this->sdoflist=NULL;
+
+}
+/*}}}*/
+/*FUNCTION DofIndexing::DofIndexing(int gsize){{{*/
+DofIndexing::DofIndexing(int in_gsize){
+	this->Init(in_gsize,NULL);
+}
+/*}}}*/
+/*FUNCTION DofIndexing::DofIndexing(DofIndexing* in)  -> copy{{{*/
+DofIndexing::DofIndexing(DofIndexing* in){ //copy constructor
+
+	int i;
+	this->gsize=in->gsize;
+	this->fsize=in->fsize;
+	this->ssize=in->ssize;
+	
+	this->clone=in->clone;
+
+	if(this->gsize>0){
+		this->f_set=xNew<bool>(this->gsize);
+		this->s_set=xNew<bool>(this->gsize);
+		this->svalues=xNew<IssmDouble>(this->gsize);
+		if(in->doftype)this->doftype=xNew<int>(this->gsize); 
+		this->gdoflist=xNew<int>(this->gsize); 
+	}
+	else{
+		this->f_set=NULL;
+		this->s_set=NULL;
+		this->svalues=NULL;
+		this->doftype=NULL;
+		this->gdoflist=NULL;
+	}
+	if(this->fsize>0 && this->fsize!=UNDEF)this->fdoflist=xNew<int>(this->fsize); else this->fdoflist=NULL;
+	if(this->ssize>0 && this->ssize!=UNDEF)this->sdoflist=xNew<int>(this->ssize); else this->sdoflist=NULL;
+
+	if(this->gsize>0){
+		memcpy(this->f_set,in->f_set,this->gsize*sizeof(bool));
+		memcpy(this->s_set,in->s_set,this->gsize*sizeof(bool));
+		xMemCpy<IssmDouble>(this->svalues,in->svalues,this->gsize);
+		if(this->doftype)memcpy(this->doftype,in->doftype,this->gsize*sizeof(int));
+		memcpy(this->gdoflist,in->gdoflist,this->gsize*sizeof(int));
+	}
+	if(this->fsize>0 && this->fsize!=UNDEF)memcpy(this->fdoflist,in->fdoflist,this->fsize*sizeof(int));
+	if(this->ssize>0 && this->ssize!=UNDEF)memcpy(this->sdoflist,in->sdoflist,this->ssize*sizeof(int));
+
+}
+/*}}}*/
+/*FUNCTION DofIndexing::~DofIndexing() {{{*/
+DofIndexing::~DofIndexing(){ //destructor
+
+	xDelete<bool>(f_set); 
+	xDelete<bool>(s_set); 
+	xDelete<IssmDouble>(svalues);
+	xDelete<int>(doftype); 
+	xDelete<int>(gdoflist);
+	xDelete<int>(fdoflist);
+	xDelete<int>(sdoflist);
+
+}
+/*}}}*/
+/*FUNCTION DofIndexing::Init{{{*/
+void DofIndexing::Init(int in_gsize,int* in_doftype){
+
+	int i;
+	this->gsize=in_gsize;
+	
+	this->clone=0;
+
+	/*allocate: */
+	if(this->gsize>0){
+		this->f_set=xNew<bool>(this->gsize);
+		this->s_set=xNew<bool>(this->gsize);
+		this->svalues=xNew<IssmDouble>(this->gsize);
+		if(in_doftype)this->doftype=xNew<int>(this->gsize);
+		this->gdoflist=xNew<int>(this->gsize);
+	}
+
+	for (i=0;i<this->gsize;i++){
+		/*assume dof is free, no constraints, no rigid body constraint: */
+		this->f_set[i]=true;
+		this->s_set[i]=false;
+		if(this->doftype)this->doftype[i]=in_doftype[i];
+		this->svalues[i]=0; //0 constraint is the default value
+		this->gdoflist[i]=UNDEF;
+	}
+}
+/*}}}*/
+/*FUNCTION DofIndexing::InitSet{{{*/
+void DofIndexing::InitSet(int setenum){
+
+	int i;
+	int size=0;
+
+	/*go through sets, and figure out how many dofs belong to this set, except for g-set, 
+	 * which has already been initialized: */
+	if(setenum==FsetEnum){
+		size=0;
+		for(i=0;i<this->gsize;i++) if(f_set[i])size++;
+		this->fsize=size;
+		xDelete<int>(this->fdoflist);
+		if(this->fsize)this->fdoflist=xNew<int>(size);
+		else this->fdoflist=NULL;
+	}
+	else if(setenum==SsetEnum){
+		size=0;
+		for(i=0;i<this->gsize;i++) if(s_set[i])size++;
+		this->ssize=size;
+		xDelete<int>(this->sdoflist);
+		if(this->ssize)this->sdoflist=xNew<int>(size);
+		else this->sdoflist=NULL;
+	}
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+}
+/*}}}*/
+
+/*Some of the Object functionality: */
+/*FUNCTION DofIndexing::Echo{{{*/
+void DofIndexing::Echo(void){
+
+	int i;
+
+	_printLine_("DofIndexing:");
+	_printLine_("   gsize: " << gsize);
+	_printLine_("   clone: " << clone);
+}
+/*}}}*/
+/*FUNCTION DofIndexing::DeepEcho{{{*/
+void DofIndexing::DeepEcho(void){
+
+	int i;
+
+	_printLine_("DofIndexing:");
+	_printLine_("   gsize: " << gsize);
+	_printLine_("   fsize: " << fsize);
+	_printLine_("   ssize: " << ssize);
+	_printLine_("   clone: " << clone);
+	
+	_printLine_("   set membership: f,s sets ");
+	for(i=0;i<gsize;i++){
+		_printLine_("      dof " << i << ": " <<(f_set[i]?"true":"false")<< " " <<(s_set[i]?"true":"false"));
+	}
+
+	_printString_("   svalues (" << this->ssize << "): |");
+	for(i=0;i<this->gsize;i++){
+		if(this->s_set[i])_printString_(" " << svalues[i] << " |");
+	}
+	_printLine_("");
+
+	if(doftype){
+		_printString_("   doftype: |");
+		for(i=0;i<gsize;i++){
+			_printString_(" " << doftype[i] << " |");
+		}
+		_printLine_("");
+	}
+	else _printLine_("   doftype: NULL");
+
+	_printString_("   g_doflist (" << this->gsize << "): |");
+	for(i=0;i<this->gsize;i++){
+		_printString_(" " << gdoflist[i] << " |");
+	}
+	_printLine_("");
+
+	_printString_("   f_doflist (" << this->fsize << "): |");
+	for(i=0;i<this->fsize;i++){
+		_printString_(" " << fdoflist[i] << " |");
+	}
+	_printLine_("");
+
+	_printString_("   s_doflist (" << this->ssize << "): |");
+	for(i=0;i<this->ssize;i++){
+		_printString_(" " << sdoflist[i] << " |");
+	}
+	_printLine_("");
+}		
+/*}}}*/
+
Index: /issm/trunk-jpl/src/c/classes/DofIndexing.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/DofIndexing.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/DofIndexing.h	(revision 12821)
@@ -0,0 +1,54 @@
+/*!\file: DofIndexing.h
+ * \brief prototype for DofIndexing.h
+ */ 
+
+#ifndef _DOFINDEXING_H_
+#define  _DOFINDEXING_H_
+
+#include "../include/include.h"
+
+class DofIndexing{
+	
+	public:
+
+		/*sizes: */
+		int gsize; //number of dofs for a node
+		int fsize; //number of dofs solver for
+		int ssize; //number of constrained dofs
+
+		/*partitioning: */
+		int     clone;   //this node is replicated from another one 
+
+		/*boundary conditions sets: */
+		bool*     f_set; //is dof on f-set (on which we solve)
+		bool*     s_set; //is dof on s-set (on which boundary conditions -dirichlet- are applied)
+		IssmDouble*   svalues; //list of constraint values. size g_size, for ease of use.
+
+		/*types of dofs: */
+		int*     doftype; //approximation type of the dofs (used only for coupling), size g_size
+		
+		/*list of degrees of freedom: */
+		int*     gdoflist; //dof list in g_set
+		int*     fdoflist; //dof list in f_set
+		int*     sdoflist; //dof list in s_set
+
+
+		/*DofIndexing constructors, destructors {{{*/
+		DofIndexing();
+		DofIndexing(int g_size);
+		void Init(int g_size,int* doftype);
+		void InitSet(int setenum);
+		DofIndexing(DofIndexing* properties);
+		~DofIndexing();
+		/*}}}*/
+		/*Object like functionality: {{{*/
+		void  Echo(void); 
+		void  DeepEcho(void); 
+		void  copy(DofIndexing* properties);
+		/*}}}*/
+		/*DofIndexing management: {{{*/
+		DofIndexing* Spawn(int* indices, int numindices);
+		/*}}}*/
+
+};
+#endif //ifndef _DOFINDEXING_H_
Index: /issm/trunk-jpl/src/c/classes/FemModel.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/FemModel.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/FemModel.cpp	(revision 12821)
@@ -0,0 +1,159 @@
+/*!\file FemModel.c
+ * \brief: implementation of the FemModel object
+ */
+
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include "../Container/Container.h"
+#include "../modules/ModelProcessorx/ModelProcessorx.h"
+#include "../io/io.h"
+#include "./objects.h"
+#include "../include/include.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../modules/modules.h"
+
+/*Object constructors and destructor*/
+/*FUNCTION FemModel::constructor {{{*/
+FemModel::FemModel(char* inputfilename, char* outputfilename, const int in_solution_type,const int* analyses,const int nummodels){
+
+	/*intermediary*/
+	int         i;
+	int         analysis_type;
+	FILE       *IOMODEL = NULL;
+	extern int  my_rank;
+
+	/*Open input file on cpu 0: */
+	if(my_rank==0) IOMODEL = pfopen(inputfilename ,"rb");
+
+	/*Initialize internal data: */
+	this->nummodels=nummodels;
+	this->solution_type=in_solution_type;
+	this->analysis_counter=nummodels-1; //point to last analysis_type carried out.
+	this->results=new Results(); //not initialized by CreateDataSets
+	
+	/*Dynamically allocate whatever is a list of length nummodels: */
+	analysis_type_list=xNew<int>(nummodels);
+
+	/*Initialize: */
+	for(i=0;i<nummodels;i++)analysis_type_list[i]=analyses[i];
+
+	/*create datasets for all analyses*/
+	ModelProcessorx(&this->elements,&this->nodes,&this->vertices,&this->materials,&this->constraints,&this->loads,&this->parameters,IOMODEL,this->solution_type,nummodels,analyses);
+
+	/*do the post-processing of the datasets to get an FemModel that can actually run analyses: */
+	for(i=0;i<nummodels;i++){
+
+		if(VerboseMProcessor()) _pprintLine_("   Processing finite element model of analysis " << EnumToStringx(analysis_type_list[i]) << ":");
+		analysis_type=analysis_type_list[i];
+		this->SetCurrentConfiguration(analysis_type);
+	
+		if(i==0){
+			if(VerboseMProcessor()) _pprintLine_("      creating vertex degrees of freedom");
+			VerticesDofx(vertices,parameters); //only call once, we only have one set of vertices
+		}
+
+		if(VerboseMProcessor()) _pprintLine_("      resolving node constraints");
+		SpcNodesx(nodes,constraints,parameters,analysis_type); 
+
+		if(VerboseMProcessor()) _pprintLine_("      creating nodal degrees of freedom");
+		NodesDofx(nodes,parameters,analysis_type);
+	
+		if(VerboseMProcessor()) _pprintLine_("      configuring element and loads");
+		ConfigureObjectsx(elements, loads, nodes, vertices, materials,parameters);
+	}
+	
+	/*Close input file descriptors: */
+	if(my_rank==0) pfclose(IOMODEL,inputfilename);
+
+	/*Add output file name to parameters: */
+	this->parameters->AddObject(new StringParam(OutputfilenameEnum,outputfilename));
+
+}
+
+/*}}}*/
+/*FUNCTION FemModel::destructor {{{*/
+FemModel::~FemModel(){
+
+	/*Intermediary*/
+	int i;
+
+	/*Delete all the datasets: */
+	xDelete<int>(analysis_type_list);
+	delete elements;
+	delete nodes;
+	delete vertices;
+	delete constraints;
+	delete loads;
+	delete materials;
+	delete parameters;
+	delete results;
+
+}
+/*}}}*/
+
+/*Object management*/
+/*FUNCTION FemModel::Echo {{{*/
+void FemModel::Echo(void){
+
+	_printLine_("FemModel echo: ");
+	_printLine_("   number of fem models: " << nummodels);
+	_printLine_("   analysis_type_list: ");
+	for(int i=0;i<nummodels;i++)_printLine_("     " << i << ": " << EnumToStringx(analysis_type_list[i]));
+	_printLine_("   current analysis_type: ");
+	_printLine_("     " << analysis_counter << ": " << EnumToStringx(analysis_type_list[analysis_counter]));
+
+}
+/*}}}*/
+
+/*Numerics: */
+/*FUNCTION FemModel::SetCurrentConfiguration(int configuration_type,int analysis_type){{{*/
+void FemModel::SetCurrentConfiguration(int configuration_type,int analysis_type){
+
+	/*Use configuration_type to setup the analysis counter, the configurations of objects etc ... but use 
+	 * analysis_type to drive the element numerics. This allows for use of 1 configuration_type for several 
+	 * analyses. For example: do a SurfaceSlopeX, SurfaceSlopeY, BedSlopeX and BedSlopeY analysis using the 
+	 * Slope configuration.*/
+
+	int found=-1;
+	for(int i=0;i<nummodels;i++){
+		if (analysis_type_list[i]==configuration_type){
+			found=i;
+			break;
+		}
+	}
+	if(found!=-1) analysis_counter=found;
+	else _error2_("Could not find alias for analysis_type " << EnumToStringx(configuration_type) << " in list of FemModel analyses");
+
+	/*Now, plug analysis_counter and analysis_type inside the parameters: */
+	this->parameters->SetParam(analysis_counter,AnalysisCounterEnum);
+	this->parameters->SetParam(analysis_type,AnalysisTypeEnum);
+	this->parameters->SetParam(configuration_type,ConfigurationTypeEnum);
+
+	/*configure elements, loads and nodes, for this new analysis: */
+	this->elements->SetCurrentConfiguration(elements,loads, nodes,vertices, materials,parameters);
+	this->nodes->SetCurrentConfiguration(elements,loads, nodes,vertices, materials,parameters);
+	this->loads->SetCurrentConfiguration(elements, loads, nodes,vertices, materials,parameters);
+
+	#ifdef _HAVE_PETSC_
+	/*take care of petsc options, that depend on this analysis type (present only after model processor)*/
+	if(this->parameters->Exist(PetscOptionsStringsEnum)){
+		PetscOptionsFromAnalysis(this->parameters,analysis_type);
+		if(VerboseSolver()) _pprintLine_("      petsc Options set for analysis type: " << EnumToStringx(analysis_type));
+	}
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION FemModel::SetCurrentConfiguration(int configuration_type){{{*/
+void FemModel::SetCurrentConfiguration(int configuration_type){
+
+	/*overload: analysis_type = configuration_type: */
+	this->SetCurrentConfiguration(configuration_type,configuration_type);
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/FemModel.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/FemModel.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/FemModel.h	(revision 12821)
@@ -0,0 +1,51 @@
+/*
+ * FemModel.h: 
+ */
+
+#ifndef _FEMMODEL_H_
+#define _FEMMODEL_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+#include "../toolkits/toolkits.h"
+class DataSet;
+class Parameters;
+class NodeSets;
+/*}}}*/
+
+
+class FemModel {
+
+	/*no private members, as we need access to these datasets quite often!:*/
+
+	public:
+
+		int                 nummodels;
+		int                 solution_type;
+		int*                analysis_type_list; //list of analyses this femmodel is going to carry out
+		int                 analysis_counter; //counter into analysis_type_list
+		
+		Elements*           elements; //elements (one set for all analyses)
+		Nodes*              nodes; //one set of nodes
+		Vertices*           vertices; //one set of vertices
+		Constraints*        constraints; //one set of constraints. each constraint knows which analysis_type it handles
+		Loads*              loads;  //one set of constraints. each constraint knows which analysis_type it handles
+		Materials*          materials;  //one set of materials, for each element
+		Parameters*         parameters; //one set of parameters, independent of the analysis_type
+		Results*            results; //results that cannot be fit into the elements (such as one time constants, arrays, strings, etc ...)
+
+		/*constructors, destructors: */
+		FemModel(char* inputfilename, char* outputfilename, const int solution_type,const int* analyses,const int nummodels);
+		~FemModel();
+
+		/*Methods: */
+		void Echo();
+
+		/*Fem: */
+		void  SetCurrentConfiguration(int configuration_type);
+		void  SetCurrentConfiguration(int configuration_type,int analysis_type);
+
+};
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/Hook.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Hook.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/Hook.cpp	(revision 12821)
@@ -0,0 +1,266 @@
+/*!\file Hook.cpp
+ * \brief: implementation of the Hook object: see Hook.h for more explanations.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "./objects.h"
+#include "../Container/Container.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../include/include.h"
+
+
+/*Constructor/Destructors*/
+/*FUNCTION Hook::Hook(){{{*/
+Hook::Hook(){
+	this->num=0;
+	this->objects=NULL;
+	this->ids=NULL;
+	this->offsets=NULL;
+	return;
+}
+/*}}}*/
+/*FUNCTION Hook::Hook(int* ids, int num){{{*/
+Hook::Hook(int* in_ids, int in_num){
+
+	/*Intermediaries*/
+	int i;
+
+	/*Get number of objects to hook*/
+	this->num=in_num;
+
+	/*Get out if num=0*/
+	if (num==0){
+		/*Empty hook*/
+		this->ids=NULL;
+		this->objects=NULL;
+		this->offsets=NULL;
+	}
+	else{
+		/*Allocate: */
+		this->objects=xNew<Object*>(this->num);
+		this->ids=xNew<int>(this->num);
+		this->offsets=xNew<int>(this->num);
+
+		/*Copy ids: */
+		for (i=0;i<this->num;i++){
+			this->ids[i]=in_ids[i];
+			this->objects[i]=NULL;
+			this->offsets[i]=0;
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Hook::~Hook(){{{*/
+Hook::~Hook(){
+	/*deallocate: */
+	xDelete<Object*>(this->objects);
+	xDelete<int>(this->ids);
+	xDelete<int>(this->offsets);
+	return;
+}
+/*}}}*/
+
+/*Some of the Object functionality: */
+/*FUNCTION Hook::Echo{{{*/
+void Hook::Echo(void){
+
+	int i;
+	if (num){
+		_printLine_("   Hook: ");
+		_printLine_("      num=" << this->num);
+		_printString_("      ids: ");
+		for (i=0;i<this->num;i++) _printString_(this->ids[i] << " ");
+		_printLine_("");
+		_printString_("      offsets: ");
+		for (i=0;i<this->num;i++) _printString_(this->offsets[i] << " ");
+		_printLine_("");
+	}
+	else{
+		_printLine_("   Hook: num=0 ");
+	}
+}
+/*}}}*/
+/*FUNCTION Hook::DeepEcho{{{*/
+void Hook::DeepEcho(void){
+
+	int i;
+	if (num){
+		_printLine_("   Hook: ");
+		_printLine_("      num=" << this->num);
+		_printString_("      ids: ");
+		for (i=0;i<this->num;i++) _printString_(this->ids[i] << " ");
+		_printLine_("");
+		_printString_("      offsets: ");
+		for (i=0;i<this->num;i++) _printString_(this->offsets[i] << " ");
+		_printLine_("");
+		if (!objects) _printLine_("      warning: object not hooked yet");
+		else{
+			_printString_("      objects:\n   ");
+			for (i=0;i<this->num;i++){
+				_printLine_("         object " << i);
+				if(objects[i]) objects[i]->DeepEcho();
+				else           _printLine_("            no object hooked yet (not configured)");
+			}
+		}
+	}
+	else{
+		_printLine_("   Hook: num=0 ");
+	}
+}
+/*}}}*/
+/*FUNCTION Hook::copy {{{*/
+Object* Hook::copy(void){
+
+	int i;
+
+	/*output: */
+	Hook* output=NULL;
+
+	/*initalize output: */
+	output=new Hook();
+
+	/*copy in the fields: */
+	output->num=this->num;
+	if(output->num){
+		output->objects=xNew<Object*>(output->num);
+		output->ids=xNew<int>(output->num);
+		output->offsets=xNew<int>(output->num);
+	}
+	
+	for(i=0;i<output->num;i++){
+		output->objects[i]=this->objects[i];
+		output->offsets[i]=this->offsets[i];
+		output->ids[i]=this->ids[i];
+	}
+
+	return (Object*)output;
+}
+/*}}}*/
+
+/*Hook management: */
+/*FUNCTION Hook::configure{{{*/
+void Hook::configure(DataSet* dataset){
+
+	/*intermediary: */
+	Object* object=NULL;
+	int i;
+
+	/*Checks if debugging mode*/
+	_assert_(this->num==0 || this->ids!=NULL);
+
+	for(i=0;i<this->num;i++){
+
+		/*is this object id -1? If so, drop this search, it was not requested: */
+		if (this->ids[i]==-1) continue;
+
+		/*Check whether existing this->objects are correct: */
+		if(this->objects[i]){
+			if(this->objects[i]->Id()==this->ids[i]) continue; //this node is good.
+			else this->objects[i]=NULL; //this node was incorrect, reset it.
+		}
+
+		/*May be the object this->offsets into this->objects are valid?: */
+		if(this->offsets[i]!=UNDEF){
+			/* Look at the this->offsets[i]'th node in the nodes dataset. If it has the correct id, 
+			 * we are good: */
+			object=(Object*)dataset->GetObjectByOffset(this->offsets[i]);
+			if (object->Id()==this->ids[i]){
+				this->objects[i]=object;
+				continue;
+			}
+			else this->offsets[i]=UNDEF; //object offset was wrong, reset it.
+		}
+
+		/*Now, for this->objects that did not get resolved, and for which we have no offset, chase them in the dataset, by id: */
+		if(this->objects[i]==NULL){
+			this->objects[i]=(Object*)dataset->GetObjectById(this->offsets+i,this->ids[i]); //remember the offset for later on.
+			/*check the id is correct!: */
+			if (this->objects[i]->Id()!=this->ids[i]) _error2_("wrong id: " << this->objects[i]->Id() << " vs " << this->ids[i] << "  in resolved pointer!");
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Hook::delivers{{{*/
+Object* Hook::delivers(void){
+	
+	/*first, check that we only have one T object in our object list: */
+	if (this->num!=1) _error2_("trying to delivery a single hook object when hook holds " << this->num << " objects" << "\n");
+
+	/*check NULL: */
+	if (this->objects==NULL) _error2_("hook is not pointing to any object, objects pointer is NULL");
+
+	return *objects;
+}
+
+/*}}}*/
+/*FUNCTION Hook::deliverp{{{*/
+Object** Hook::deliverp(void){
+	return objects;
+}
+/*}}}*/
+/*FUNCTION Hook::Ids{{{*/
+int* Hook::Ids(void){
+	return this->ids;
+}
+/*}}}*/
+/*FUNCTION Hook::GetNum{{{*/
+int Hook::GetNum(void){
+	return this->num;
+}
+/*}}}*/
+/*FUNCTION Hook::GetObjects{{{*/
+Object** Hook::GetObjects(void){
+	return this->objects;
+}
+/*}}}*/
+/*FUNCTION Hook::GetOffsets{{{*/
+int* Hook::GetOffsets(void){
+	return this->offsets;
+}
+/*}}}*/
+/*FUNCTION Hook::Spawn{{{*/
+Hook* Hook::Spawn(int* indices, int numindices){
+
+	int i;
+
+	/*output: */
+	Hook* output=NULL;
+
+	/*allocate: */
+	output=new Hook();
+
+	/*If this Hook is empty, simply return*/
+	if(this->num==0){
+		output->num=0;
+		return output;
+	}
+
+	/*Else, check that we are requesting a half of num*/
+	if (numindices>this->num) _error2_("Cannot spawn hook with " << numindices << " objects from a Hook of " << this->num << " objects");
+
+	/*go pickup the correct objects, ids and offsets :*/
+	output->num=numindices;
+	if(output->num<1) _error2_("Trying to spawn an empty ElementProperties!");
+
+	output->objects=xNew<Object*>(output->num);
+	output->ids=xNew<int>(output->num);
+	output->offsets=xNew<int>(output->num);
+
+	for(i=0;i<output->num;i++){
+		output->objects[i]=this->objects[indices[i]];
+		output->ids[i]=this->ids[indices[i]];
+		output->offsets[i]=this->offsets[indices[i]];
+	}
+
+	return output;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/Hook.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Hook.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/Hook.h	(revision 12821)
@@ -0,0 +1,50 @@
+/*!\file Hook.h
+ * \brief: header file for hook object.
+ * A hook is a class  that can store the id, offset, and object corresponding to this id and offset into a dataset.
+ * For example, an element has a hook to its nodes. A node has a hook to its vertex.  The hook abstracts the need for having
+ * ids and offsets (necesarry for proper configuration of an object) in our objects. 
+ */
+
+#ifndef _HOOK_H_
+#define _HOOK_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+class DataSet;
+/*}}}*/
+
+class Hook{
+
+	private: 
+
+		int	   num; //number of objects being hooked onto
+		Object**	   objects; //list of object pointers. we do not allocate objects, just a list a pointers, that will get to point to the real objects from a dataset.
+		int*   ids;     //list of object ids, to go look for them in datasets.
+		int*   offsets;  //list of object offsets into datasets, to speed up lookup.
+
+	public:
+
+		/*Hook constructors, destructors: {{{*/
+		Hook();
+		Hook(int* ids, int num);
+		~Hook();
+		/*}}}*/
+		/*Object like functionality:{{{*/
+		void       Echo(void);
+		void       DeepEcho(void);
+		Object*    copy(void);
+		/*}}}*/
+		/*Hook management: {{{*/
+		Object*    delivers(void); //single object deliver
+		Object**   deliverp(void); //deliver all objects
+		void       configure(DataSet* dataset);
+		Hook*      Spawn(int* indices, int numindices);
+		Object**   GetObjects(void);
+		int*       Ids(void);
+		int*       GetOffsets(void);
+		int        GetNum(void);
+		/*}}}*/
+};
+
+#endif  /* _HOOK_H_ */
Index: /issm/trunk-jpl/src/c/classes/Patch.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/Patch.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/Patch.cpp	(revision 12821)
@@ -0,0 +1,175 @@
+/*!\file Patch.c
+ * \brief: implementation of the Patch object
+ */
+
+/*Include files: {{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "./objects.h"
+#include "../Container/Container.h"
+#include "../io/io.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../include/include.h"
+/*}}}*/
+
+/*Object constructors and destructors:*/
+/*FUNCTION Patch::Patch() default constructor {{{*/
+Patch::Patch(){
+	this->numrows=0;
+	this->numcols=0;
+	this->maxvertices=0;
+	this->maxnodes=0;
+	this->values=NULL;
+}
+/*}}}*/
+/*FUNCTION Patch::Patch(int numrows, int maxvertices, int maxnodes){{{*/
+Patch::Patch(int in_numrows, int in_maxvertices, int in_maxnodes){
+
+	int i,j;
+	this->numrows=in_numrows;
+	this->maxvertices=in_maxvertices;
+	this->maxnodes=in_maxnodes;
+    
+	this->numcols=1  //enum_type
+		+1           //step
+		+1           //time 
+		+1           //element id
+		+1           //interpolation type
+		+maxvertices //vertices
+		+maxnodes;   //nodes
+
+	//Allocate values and fill with NaN:
+	if (this->numcols*this->numrows==0){
+		this->values=NULL;
+	}
+	else{
+	        this->values=xNew<IssmDouble>(this->numcols*this->numrows);
+		for(i=0;i<this->numrows;i++){
+			for(j=0;j<this->numcols;j++){
+				this->values[i*this->numcols+j]=NAN;
+			}
+		}
+	}
+
+}
+/*}}}*/
+/*FUNCTION Patch::~Patch(){{{*/
+Patch::~Patch(){
+	xDelete<IssmDouble>(values);
+}
+/*}}}*/
+
+/*Object methods*/
+/*FUNCTION Patch::fillelementinfo{{{*/
+void Patch::fillelementinfo(int count, int element_id, int* vertices_ids, int num_vertices){
+
+	int i;
+	IssmDouble* row=NULL;
+
+	/*point to the start of the row: */
+	row=this->values+count*this->numcols;
+
+	/*Let's remember what is on a row: 
+	 enum_type step time element_id interpolation vertices_ids nodal_values
+	 */
+	row[3]=element_id;
+	for(i=0;i<num_vertices;i++){
+		row[5+i]=vertices_ids[i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION Patch::fillresultinfo{{{*/
+void Patch::fillresultinfo(int count,int enum_type,int step, IssmDouble time, int interpolation, IssmDouble* nodal_values, int num_nodes){
+
+	int i;
+	IssmDouble* row=NULL;
+
+	/*point to the start of the row: */
+	row=this->values+count*this->numcols;
+
+	/*Let's remember what is on a row: 
+	 enum_type step time element_id interpolation vertices_ids nodal_values
+	 */
+	row[0]=enum_type;
+	row[1]=(IssmDouble)step;
+	row[2]=time;
+	row[4]=interpolation;
+	for(i=0;i<num_nodes;i++){
+		row[5+this->maxvertices+i]=nodal_values[i];
+	}
+
+}
+/*}}}*/
+/*FUNCTION Patch::Gather{{{*/
+void Patch::Gather(void){
+
+	int         i;
+	int         count;
+	extern int  my_rank;
+	extern int  num_procs;
+	int         total_numrows;
+	int         node_numrows;
+	IssmDouble     *total_values  = NULL;
+	#ifdef _HAVE_MPI_
+	MPI_Status  status;
+	#endif
+
+	/*First, figure out total number of rows combining all the cpus: */
+	#ifdef _HAVE_MPI_
+	MPI_Reduce(&this->numrows,&total_numrows,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD );
+	MPI_Bcast(&total_numrows,1,MPI_INT,0,MPI_COMM_WORLD);
+	#else
+	total_numrows=this->numrows;
+	#endif
+
+	/*return if patch empty*/
+	if(total_numrows==0) return;
+
+	/*Now, allocate buffer to holds all the values, on node 0: */
+	if(my_rank==0)total_values=xNew<IssmDouble>(this->numcols*total_numrows);
+
+	/*Start by copying node 0 values onto total_values: */
+	if(my_rank==0){
+		count=0;
+		xMemCpy<IssmDouble>(total_values+count,this->values,this->numcols*this->numrows);
+		count+=this->numrows*this->numcols;
+	}
+
+	/*Now, ask other nodes to send their values: */
+	#ifdef _HAVE_MPI_
+	for (i=1;i<num_procs;i++){
+		if (my_rank==i){ 
+			MPI_Send(&this->numrows,1,MPI_INT,0,1,MPI_COMM_WORLD);   
+			if (this->numrows)MPI_Send(this->values,this->numrows*this->numcols,MPI_DOUBLE,0,1,MPI_COMM_WORLD); 
+		}
+		if (my_rank==0){
+			MPI_Recv(&node_numrows,1,MPI_INT,i,1,MPI_COMM_WORLD,&status); 
+			if (node_numrows)MPI_Recv(total_values+count,node_numrows*this->numcols,MPI_DOUBLE,i,1,MPI_COMM_WORLD,&status);
+			count+=node_numrows*this->numcols;
+		}
+	}	
+	#endif
+
+	/*Now, node 0 has total_values, of size total_numrows*this->numcols. Update the fields in the patch, to reflect this new 
+	 * reality. For other cpus, no point in keeping their data anymore: */
+	if(my_rank==0){
+		this->numrows=total_numrows;
+		xDelete<IssmDouble>(this->values);
+		this->values=total_values;
+	}
+	#ifdef _HAVE_MPI_
+	else{
+		this->numrows=0;
+		xDelete<IssmDouble>(this->values);
+	}
+	#endif
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/Patch.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Patch.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/Patch.h	(revision 12821)
@@ -0,0 +1,46 @@
+/*!\file: Patch.h
+ * \brief prototypes for Patch.h
+ */ 
+
+/*A Patch object is used to store all results held in elements, in a serial way, and to dump them to disk. 
+	
+	Each row of the Patch object is made of the following information: 
+	- the result enum_type, 
+	- the step and time, 
+	- the id of the element, 
+	- the interpolation type, 
+	- the vertices ids, 
+	- and the values at the nodes (could be different from the vertices).
+	
+	For ex: 
+	1. on a Beam element, Vx, at step 1, time .5, element id 1, interpolation type P0 (constant), vertices ids 1 and 2, one constant value 4.5
+	   VxEnum 1  .5  1 P0  1 2       4.5 NaN  NaN
+	2. on a Tria element, Vz, at step 2, time .8, element id 2, interpolation type P1 (linear), vertices ids 1 3 and 4, with values at 3 nodes 4.5, 3.2, 2.5
+	   VzEnum 2  .8  2 P1  1 3 4     4.5 3.2  2.5
+*/
+
+
+#ifndef _PATCH_H_
+#define  _PATCH_H_
+
+/*Headers:*/
+class Patch{
+
+	public:
+
+		int     numrows; //number of results held in Patch object
+		int     numcols; //number of columns
+		int     maxvertices; //maxvertices corresponds to largest amount of vertices on a given element, determined by the geometry.
+		int     maxnodes;    // maxnodes corresponds to the largest amout of nodes on a given element, determined by the interpolation type.
+		
+		IssmDouble* values;  //result values
+
+		Patch();
+		Patch(int numrows, int maxvertices, int maxnodes);
+		~Patch();
+		void fillelementinfo(int row, int element_id, int* vertices_ids, int num_vertices);
+		void fillresultinfo(int row,int enum_type,int step, IssmDouble time, int interpolation, IssmDouble* nodal_values, int num_nodes);
+		void Gather(void);
+
+};
+#endif //ifndef _PATCH_H_
Index: /issm/trunk-jpl/src/c/classes/Update.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/Update.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/Update.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*!\file: Update.h: abstract class used by some objects to update their properties
+ * \brief prototypes for Update.h
+ */ 
+
+#ifndef _UPDATE_H_
+#define  _UPDATE_H_
+
+/*Headers:*/
+/*{{{*/
+#include "../shared/shared.h"
+/*}}}*/
+
+class Update{
+
+	public:
+
+		virtual void  InputUpdateFromVector(IssmDouble* vector, int name, int type)=0;
+		virtual void  InputUpdateFromVector(int* vector, int name, int type)=0;
+		virtual void  InputUpdateFromVector(bool* vector, int name, int type)=0; 
+		#ifdef _HAVE_DAKOTA_
+		virtual void  InputUpdateFromMatrixDakota(IssmDouble* matrix, int rows, int ncols, int name, int type)=0;
+		virtual void  InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type)=0;
+		virtual void  InputUpdateFromVectorDakota(int* vector, int name, int type)=0;
+		virtual void  InputUpdateFromVectorDakota(bool* vector, int name, int type)=0;
+		#endif
+		virtual void  InputUpdateFromConstant(IssmDouble constant, int name)=0;
+		virtual void  InputUpdateFromConstant(int constant, int name)=0;
+		virtual void  InputUpdateFromConstant(bool constant, int name)=0;
+		virtual void  InputUpdateFromSolution(IssmDouble* solution)=0;
+		virtual void  InputUpdateFromIoModel(int index, IoModel* iomodel)=0;
+
+};
+
+#endif //ifndef _UPDATE_H_
+
Index: /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.cpp	(revision 12821)
@@ -0,0 +1,76 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "AdjacentTriangle.h"
+#include "Mesh.h"
+
+namespace bamg {
+
+
+	/*Constructors/Destructors*/
+	//See header file
+
+	/*Methods*/
+	/*FUNCTION AdjacentTriangle::Locked {{{*/
+	int  AdjacentTriangle::Locked() const {
+		return t->AdjEdgeIndex[a] & 4;
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::MarkUnSwap {{{*/
+	int  AdjacentTriangle::MarkUnSwap() const {
+		return t->AdjEdgeIndex[a] & 8;
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::GetAllFlag_UnSwap {{{*/
+	int  AdjacentTriangle::GetAllFlag_UnSwap() const {
+		// take all flag except MarkUnSwap
+		return t->AdjEdgeIndex[a] & 1012;
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::SetLock {{{*/
+	void AdjacentTriangle::SetLock(){
+		t->SetLocked(a);
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::Adj {{{*/
+	AdjacentTriangle AdjacentTriangle::Adj() const {
+		return  t->Adj(a);
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::EdgeVertex {{{*/
+	BamgVertex* AdjacentTriangle::EdgeVertex(const int & i) const {
+		return t->vertices[VerticesOfTriangularEdge[a][i]];
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::OppositeVertex {{{*/
+	BamgVertex* AdjacentTriangle::OppositeVertex() const {
+		return t->vertices[bamg::OppositeVertex[a]]; 
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::det {{{*/
+	Icoor2 & AdjacentTriangle::det() const {
+		return t->det;
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::swap {{{*/
+	int AdjacentTriangle::swap(){
+		return  t->swap(a);
+	}
+	/*}}}*/
+	/*FUNCTION AdjacentTriangle::SetAdj2 {{{*/
+	void AdjacentTriangle::SetAdj2(const AdjacentTriangle & ta, int l  ){
+		//set Adjacent Triangle of a triangle
+		if(t) {
+			t->adj[a]=ta.t;
+			t->AdjEdgeIndex[a]=ta.a|l;
+		}
+		if(ta.t) {
+			ta.t->adj[ta.a] = t ;
+			ta.t->AdjEdgeIndex[ta.a] = a| l ;
+		}
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/AdjacentTriangle.h	(revision 12821)
@@ -0,0 +1,46 @@
+#ifndef _TRIANGLEADJACENT_H_
+#define _TRIANGLEADJACENT_H_
+
+#include "./include.h"
+#include "./BamgVertex.h"
+
+namespace bamg {
+
+	//classes
+	class Triangle;
+	class Triangle;
+
+	class AdjacentTriangle {
+
+		public:
+			Triangle* t; //pointer toward the triangle
+			int  a;      //Edge number
+
+			//Constructors
+			AdjacentTriangle():a(0),t(NULL) {};
+			AdjacentTriangle(Triangle* tt,int  aa): t(tt),a(aa &3) {};
+
+			//Operators
+			operator Triangle * () const {return t;}
+			operator Triangle & () const {return *t;}
+			operator int() const {return a;}
+			AdjacentTriangle & operator++(){ a= NextEdge[a]; return *this; }
+			AdjacentTriangle operator--(){ a= PreviousEdge[a]; return *this; }
+
+			//Methods
+
+			//Methods
+			int  Locked() const;
+			int  MarkUnSwap() const;
+			int  GetAllFlag_UnSwap() const;
+			void SetLock();
+			void SetAdj2(const AdjacentTriangle &ta, int l=0);
+			int  swap();
+			AdjacentTriangle Adj() const;
+			BamgVertex* EdgeVertex(const int & i) const;
+			BamgVertex* OppositeVertex() const;
+			Icoor2& det() const;
+	};
+}
+#endif
+
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.cpp	(revision 12821)
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include "../objects.h"
+#include "../../io/io.h"
+#include "../../shared/shared.h"
+
+/*Constructors/Destructors*/
+/*FUNCTION BamgGeom::BamgGeom(){{{*/
+BamgGeom::BamgGeom(){
+
+	this->VerticesSize[0]=0,          this->VerticesSize[1]=0;          this->Vertices=NULL;
+	this->EdgesSize[0]=0,             this->EdgesSize[1]=0;             this->Edges=NULL;
+	this->TangentAtEdgesSize[0]=0,    this->TangentAtEdgesSize[1]=0;    this->TangentAtEdges=NULL;
+	this->CornersSize[0]=0,           this->CornersSize[1]=0;           this->Corners=NULL;
+	this->RequiredVerticesSize[0]=0,  this->RequiredVerticesSize[1]=0;  this->RequiredVertices=NULL;
+	this->RequiredEdgesSize[0]=0,     this->RequiredEdgesSize[1]=0;     this->RequiredEdges=NULL;
+	this->CrackedEdgesSize[0]=0,      this->CrackedEdgesSize[1]=0;      this->CrackedEdges=NULL;
+	this->SubDomainsSize[0]=0,        this->SubDomainsSize[1]=0;        this->SubDomains=NULL;
+
+}
+/*}}}*/
+/*FUNCTION BamgGeom::~BamgGeom(){{{*/
+BamgGeom::~BamgGeom(){
+
+	xDelete<double>(this->Vertices);
+	xDelete<double>(this->Edges);
+	xDelete<double>(this->TangentAtEdges);
+	xDelete<double>(this->Corners);
+	xDelete<double>(this->RequiredVertices);
+	xDelete<double>(this->RequiredEdges);
+	xDelete<double>(this->CrackedEdges);
+	xDelete<double>(this->SubDomains);
+
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgGeom.h	(revision 12821)
@@ -0,0 +1,31 @@
+/*!\file:  BamgGeom.h
+ */ 
+
+#ifndef _BAMGGEOM_H_
+#define _BAMGGEOM_H_
+
+class BamgGeom{
+
+	public:
+		int     VerticesSize[2];
+		double* Vertices;
+		int     EdgesSize[2];
+		double* Edges;
+		int     TangentAtEdgesSize[2];
+		double* TangentAtEdges;
+		int     CornersSize[2];
+		double* Corners;
+		int     RequiredVerticesSize[2];
+		double* RequiredVertices;
+		int     RequiredEdgesSize[2];
+		double* RequiredEdges;
+		int     CrackedEdgesSize[2];
+		double* CrackedEdges;
+		int     SubDomainsSize[2];
+		double* SubDomains;
+
+		BamgGeom();
+		~BamgGeom();
+};
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.cpp	(revision 12821)
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include "../objects.h"
+#include "../../io/io.h"
+#include "../../shared/shared.h"
+
+/*Constructors/Destructors*/
+/*FUNCTION BamgMesh::BamgMesh(){{{*/
+BamgMesh::BamgMesh(){
+
+	this->VerticesSize[0]=0,                  this->VerticesSize[1]=0;                 this->Vertices=NULL;
+	this->EdgesSize[0]=0,                     this->EdgesSize[1]=0;                    this->Edges=NULL;
+	this->TrianglesSize[0]=0,                 this->TrianglesSize[1]=0;                this->Triangles=NULL;
+	this->QuadrilateralsSize[0]=0,            this->QuadrilateralsSize[1]=0;           this->Quadrilaterals=NULL;
+
+	this->SubDomainsSize[0]=0,                this->SubDomainsSize[1]=0;               this->SubDomains=NULL;
+	this->SubDomainsFromGeomSize[0]=0,        this->SubDomainsFromGeomSize[1]=0;       this->SubDomainsFromGeom=NULL;
+	this->CrackedVerticesSize[0]=0,           this->CrackedVerticesSize[1]=0;          this->CrackedVertices=NULL;
+	this->CrackedEdgesSize[0]=0,              this->CrackedEdgesSize[1]=0;             this->CrackedEdges=NULL;
+
+	this->VerticesOnGeomVertexSize[0]=0,      this->VerticesOnGeomVertexSize[1]=0;     this->VerticesOnGeomVertex=NULL;
+	this->VerticesOnGeomEdgeSize[0]=0,        this->VerticesOnGeomEdgeSize[1]=0;       this->VerticesOnGeomEdge=NULL;
+	this->EdgesOnGeomEdgeSize[0]=0,           this->EdgesOnGeomEdgeSize[1]=0;          this->EdgesOnGeomEdge=NULL;
+
+	this->IssmEdgesSize[0]=0,                 this->IssmEdgesSize[1]=0;                this->IssmEdges=NULL;
+	this->IssmSegmentsSize[0]=0,              this->IssmSegmentsSize[1]=0;             this->IssmSegments=NULL;
+
+	this->ElementConnectivitySize[0]=0,       this->ElementConnectivitySize[1]=0;      this->ElementConnectivity=NULL;
+	this->NodalConnectivitySize[0]=0,         this->NodalConnectivitySize[1]=0;        this->NodalConnectivity=NULL;
+	this->NodalElementConnectivitySize[0]=0,  this->NodalElementConnectivitySize[1]=0; this->NodalElementConnectivity=NULL;
+}
+/*}}}*/
+/*FUNCTION BamgMesh::~BamgMesh(){{{*/
+BamgMesh::~BamgMesh(){
+
+	xDelete<double>(this->Vertices);
+	xDelete<double>(this->Edges);
+	xDelete<double>(this->Triangles);
+	xDelete<double>(this->Quadrilaterals);
+
+	xDelete<double>(this->SubDomains);
+	xDelete<double>(this->SubDomainsFromGeom);
+	xDelete<double>(this->CrackedVertices);
+	xDelete<double>(this->CrackedEdges);
+
+	xDelete<double>(this->VerticesOnGeomVertex);
+	xDelete<double>(this->VerticesOnGeomEdge);
+	xDelete<double>(this->EdgesOnGeomEdge);
+
+	xDelete<double>(this->IssmEdges);
+	xDelete<double>(this->IssmSegments);
+
+	xDelete<double>(this->ElementConnectivity);
+	xDelete<double>(this->NodalConnectivity);
+	xDelete<double>(this->NodalElementConnectivity);
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgMesh.h	(revision 12821)
@@ -0,0 +1,52 @@
+/*!\file:  BamgMesh.h
+ */ 
+
+#ifndef _BAMGMESH_H_
+#define _BAMGMESH_H_
+
+class BamgMesh{
+
+	public:
+
+		int     VerticesSize[2];
+		double* Vertices;
+		int     EdgesSize[2];
+		double* Edges;
+		int     TrianglesSize[2];
+		double* Triangles;
+		int     QuadrilateralsSize[2];
+		double* Quadrilaterals;
+
+		int     VerticesOnGeomVertexSize[2];
+		double* VerticesOnGeomVertex;
+		int     VerticesOnGeomEdgeSize[2];
+		double* VerticesOnGeomEdge;
+		int     EdgesOnGeomEdgeSize[2];
+		double* EdgesOnGeomEdge;
+
+		int     SubDomainsSize[2];
+		double* SubDomains;
+		int     SubDomainsFromGeomSize[2];
+		double* SubDomainsFromGeom;
+		int     CrackedVerticesSize[2];
+		double* CrackedVertices;
+		int     CrackedEdgesSize[2];
+		double* CrackedEdges;
+
+		/*Output for ISSM*/
+		int     IssmEdgesSize[2];
+		double* IssmEdges;
+		int     IssmSegmentsSize[2];
+		double* IssmSegments;
+		int     ElementConnectivitySize[2];
+		double* ElementConnectivity;
+		int     NodalConnectivitySize[2];
+		double* NodalConnectivity;
+		int     NodalElementConnectivitySize[2];
+		double* NodalElementConnectivity;
+
+		BamgMesh();
+		~BamgMesh();
+};
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.cpp	(revision 12821)
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include "../../shared/shared.h"
+#include "../../include/include.h"
+#include "../objects.h"
+#include "../../io/io.h"
+
+/*Constructors/Destructors*/
+/*FUNCTION BamgOpts::BamgOpts() {{{*/
+BamgOpts::BamgOpts(){
+
+	this->anisomax=0;
+	this->cutoff=0;
+	this->coeff=0;
+	this->errg=0;
+	this->gradation=0;
+	this->Hessiantype=0;
+	this->MaxCornerAngle=0;
+	this->maxnbv=0;
+	this->maxsubdiv=0;
+	this->Metrictype=0;
+	this->nbjacobi=0;
+	this->nbsmooth=0;
+	this->omega=0;
+	this->power=0;
+	this->verbose=0;
+
+	this->Crack=0;
+	this->geometricalmetric=0;
+	this->KeepVertices=0;
+	this->splitcorners=0;
+
+	this->hmin=0;
+	this->hmax=0;
+	this->hminVertices=NULL; this->hminVerticesSize[0]=this->hminVerticesSize[1]=0;
+	this->hmaxVertices=NULL; this->hmaxVerticesSize[0]=this->hmaxVerticesSize[1]=0;
+	this->hVertices=NULL;    this->hVerticesSize[0]=this->hVerticesSize[1]=0;
+	this->metric=NULL;       this->metricSize[0]=this->metricSize[1]=0;
+	this->field=NULL;        this->fieldSize[0]=this->fieldSize[1]=0;
+	this->err=NULL;          this->errSize[0]=this->errSize[1]=0;
+
+}
+/*}}}*/
+/*FUNCTION BamgOpts::~BamgOpts() {{{*/
+BamgOpts::~BamgOpts(){
+
+	xDelete<double>(this->hminVertices);
+	xDelete<double>(this->hmaxVertices);
+	xDelete<double>(this->hVertices);
+	xDelete<double>(this->metric);
+	xDelete<double>(this->field);
+	xDelete<double>(this->err);
+
+}
+/*}}}*/
+
+/*Methods*/
+/*FUNCTION BamgOpts::Check{{{*/
+void BamgOpts::Check(void){
+
+	int i;
+
+	if (this->anisomax<1) _error2_("'anisomax' option should be >=1");
+	if (this->coeff==0) _error2_("'coeff' should be positive");
+	if (this->errg<0) _error2_("'errg' option should be >0");
+	if (this->gradation<1) _error2_("'gradation' option should be >=1");
+	if (this->Hessiantype!=0  && this->Hessiantype!=1) _error2_("'Hessiantype' supported options are 0 and 1");
+	if (this->maxnbv<3) _error2_("'maxnbv' option should be >3");
+	if (this->maxsubdiv<=1) _error2_("'maxsubdiv' should be >1");
+	if (this->Metrictype!=0   && this->Metrictype!=1 && this->Metrictype!=2) _error2_("'Metrictype' supported options are 0, 1 and 2");
+	if (this->nbjacobi<=0) _error2_("'nbjacobi' option should be >0");
+	if (this->nbsmooth<=0) _error2_("'nbsmooth' option should be >0");
+
+	if (this->Crack!=0  && this->Crack!=1) _error2_("'Crack' supported options are 0 and 1");
+	if (this->KeepVertices!=0 && this->KeepVertices!=1) _error2_("'KeepVertices' supported options are 0 and 1");
+	if (this->geometricalmetric!=0  && this->geometricalmetric!=1) _error2_("'geometricalmetric' supported options are 0 and 1");
+
+	if (this->hmin<=0) _error2_("'hmin' option should be >0");
+	if (this->hmax<=0 || this->hmax<this->hmin) _error2_("'hmax' option should be between 0 and hmin=" << this->hmin);
+	if (this->hminVertices && this->hminVerticesSize[1]!=1) _error2_("'hminVertices' should be a column");
+	if (this->hmaxVertices && this->hmaxVerticesSize[1]!=1) _error2_("'hmaxVertices' should be a column");
+	if (this->hVertices && this->hVerticesSize[1]!=1) _error2_("'hVertices' should be a column");
+	if (this->metric && (this->metricSize[1]!=1 && this->metricSize[1]!=3)) _error2_("'metric' should have either 1 (iso) or 3 (aniso) columns.");
+	if (this->field){
+		if (this->errSize[0]!=1 || this->errSize[1]!=this->fieldSize[1]) _error2_("'err' should be of size " << 1 << " x " << this->fieldSize[1]);
+		for (i=0;i<this->fieldSize[1];i++) {if (this->err[i]<=0) _error2_("'err' option should be >0");};
+	}
+
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgOpts.h	(revision 12821)
@@ -0,0 +1,57 @@
+/*!\file:  BamgOpts.h
+ * \brief place holder for optimization function arguments
+ */ 
+
+#ifndef _BAMGOPTS_H_
+#define _BAMGOPTS_H_
+
+class BamgOpts{
+
+	public:
+
+		/*Parameters*/
+		double  anisomax;
+		double  cutoff;
+		double  coeff;
+		double  errg;
+		double  gradation;
+		int     Hessiantype;
+		double  MaxCornerAngle;
+		int     maxnbv;
+		double  maxsubdiv;
+		int     Metrictype;
+		int     nbjacobi;
+		int     nbsmooth;
+		double  omega;
+		double  power;
+		int     verbose;
+
+		/*Flags*/
+		int     Crack;
+		int     geometricalmetric;
+		int     KeepVertices;
+		int     splitcorners;
+
+		/*Metric related*/
+		double  hmin;
+		double  hmax;
+		int     hminVerticesSize[2];
+		double* hminVertices;
+		int     hmaxVerticesSize[2];
+		double* hmaxVertices;
+		int     hVerticesSize[2];
+		double* hVertices;
+		int     metricSize[2];
+		double* metric;
+		int     fieldSize[2];
+		double* field;
+		int     errSize[2];
+		double* err;
+
+		BamgOpts();
+		~BamgOpts();
+
+		void Check(void);
+
+};
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.cpp	(revision 12821)
@@ -0,0 +1,598 @@
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "../objects.h"
+
+namespace bamg {
+
+	/*MACROS {{{*/
+	/* 
+	 * 
+	 *    J    j
+	 *    ^    ^
+	 *    |    | +--------+--------+
+	 *    |    | |        |        |
+	 * 1X |    | |   2    |   3    |
+	 *    |    | |        |        |
+	 *    |    | +--------+--------+
+	 *    |    | |        |        |
+	 * 0X |    | |   0    |   1    |
+	 *    |    | |        |        |
+	 *    |    | +--------+--------+
+	 *    |    +-----------------------> i
+	 *    |         
+	 *    |----------------------------> I
+	 *              X0        X1  
+	 *
+	 * box 0 -> I=0 J=0 IJ=00  = 0
+	 * box 1 -> I=1 J=0 IJ=01  = 1
+	 * box 2 -> I=0 J=1 IJ=10  = 2
+	 * box 3 -> I=1 J=1 IJ=11  = 3
+	 */
+#define INTER_SEG(a,b,x,y) (((y) > (a)) && ((x) <(b)))
+#define ABS(i) ((i)<0 ?-(i) :(i))
+#define MAX1(i,j) ((i)>(j) ?(i) :(j))
+#define NORM(i1,j1,i2,j2) MAX1(ABS((i1)-(j1)),ABS((i2)-(j2)))
+
+	//IJ(i,j,l) returns the box number of i and j with respect to l
+	//if !j&l and !i&l -> 0 (box zero: lower left )
+	//if !j&l and  i&l -> 1 (box one:  lower right)
+	//if  j&l and !i&l -> 2 (box two:  upper left )
+	//if  j&l and  i&l -> 3 (box three:upper right)
+#define IJ(i,j,l)  ((j&l) ? ((i&l) ? 3:2 ) :((i&l) ? 1:0 ))
+
+	//I_IJ(k,l) returns l if first  bit of k is 1, else 0
+#define I_IJ(k,l)  ((k&1) ? l:0)
+	//J_IJ(k,l) returns l if second bit of k is 1, else 0
+#define J_IJ(k,l)  ((k&2) ? l:0)
+	/*}}}*/
+	/*DOCUMENTATION What is a BamgQuadtree? {{{
+	 * A Quadtree is a very simple way to group vertices according
+	 * to their locations. A square that holds all the points of the mesh
+	 * (or the geometry) is divided into 4 boxes. As soon as one box
+	 * hold more than 4 vertices, it is divided into 4 new boxes, etc...
+	 * There cannot be more than MAXDEEP (=30) subdivision.
+	 * This process is like a Dichotomy in dimension 2
+	 *
+	 *  + - -  -    - -    -    - - + -   - + - + - + - -     - - +
+	 *  |                           |       |   | X |             |
+	 *                                      + - + - +
+	 *  |                           |       |   |   |             |
+	 *                              + -   - + - + - +             +
+	 *  |                           |       |       |             |
+	 *                         
+	 *  |                           |       |       |             |
+	 *  + - -  -    - -    -    - - + -   - + -   - + - -     - - +
+	 *  |                           |               |             |
+	 *                         
+	 *  |                           |               |             |
+	 *                         
+	 *  |                           |               |             |
+	 *  |                           |               |             |
+	 *  + - -  -    - -    -    - - + -   -   -   - + - -     - - +
+	 *  |                           |                             |
+	 *                         
+	 *  |                           |                             |
+	 *                         
+	 *  |                           |                             |
+	 *                         
+	 *  |                           |                             |
+	 *  |                           |                             |
+	 *  |                           |                             |
+	 *  |                           |                             |
+	 *  |                           |                             |
+	 *  + - -  -    - -    -    - - + -   -   -   -   - -     - - +
+	 *
+	 * The coordinate system used in a quadtree are integers to avoid
+	 * round-off errors. The vertex in the lower left box has the coordinates
+	 * (0 0) 
+	 * The upper right vertex has the follwing coordinates:
+	 * 2^30 -1           2^30 -1        in decimal
+	 * 0 1 1 1 .... 1    0 1 1 1 .... 1 in binary
+	 *  \--   29  --/     \--   29  --/
+	 * Using binaries is therefore very easy to locate a vertex in a box:
+	 * we just need to look at the bits from the left to the right (See ::Add)
+	 }}}*/
+
+	/*Constructors/Destructors*/
+	/*FUNCTION BamgQuadtree::BamgQuadtree(){{{*/
+	BamgQuadtree::BamgQuadtree(){
+
+		/*Number of boxes and vertices*/
+		NbBamgQuadtreeBox=0;
+		NbVertices=0;
+
+		/*Create container*/
+		boxcontainer=new DataSet();
+
+		/*Create Root, pointer toward the main box*/
+		root=NewBamgQuadtreeBox();
+
+		}
+	/*}}}*/
+	/*FUNCTION BamgQuadtree::BamgQuadtree(Mesh * t,long nbv){{{*/
+	BamgQuadtree::BamgQuadtree(Mesh * t,long nbv){ 
+
+		/*Number of boxes and vertices*/
+		NbBamgQuadtreeBox=0;
+		NbVertices=0;
+
+		/*Create container*/
+		boxcontainer=new DataSet();
+
+		/*Create Root, pointer toward the main box*/
+		root=NewBamgQuadtreeBox();
+
+		/*Check Sizes*/
+		_assert_(MaxISize>MaxICoor);
+
+		/*Add all vertices of the mesh*/
+		if (nbv==-1) nbv=t->nbv;
+		for (int i=0;i<nbv;i++) Add(t->vertices[i]);
+
+	}
+	/*}}}*/
+	/*FUNCTION BamgQuadtree::~BamgQuadtree(){{{*/
+	BamgQuadtree::~BamgQuadtree() {
+		delete boxcontainer;
+		root=NULL;
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION BamgQuadtree::Add{{{*/
+	void  BamgQuadtree::Add(BamgVertex &w){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, BamgQuadtree.cpp/Add)*/
+		BamgQuadtreeBox** pb=NULL;
+		BamgQuadtreeBox*  b=NULL;
+
+		/*Get integer coodinate of current point w*/
+		register long i=w.i.x, j=w.i.y;
+
+		/*Initialize level*/
+		register long level=MaxISize;
+
+		/*Get inital box (the largest)*/
+		pb = &root;
+
+		/*Find the smallest box where w is located*/
+		while((b=*pb) && (b->nbitems<0)){ 
+
+			//shift b->nbitems by -1
+			b->nbitems--;
+
+			//shifted righ by one bit: level=00000010 -> 00000001
+			level >>= 1;
+
+			//Get next subbox according to the bit value (level)
+			pb = &b->b[IJ(i,j,level)];
+		}
+
+		/*OK, we have found b, a Subbox holding vertices (might be full)
+		  check that the vertex is not already in the box*/
+		if (b){      
+			if (b->nbitems > 3 &&  b->v[3] == &w) return;
+			if (b->nbitems > 2 &&  b->v[2] == &w) return;
+			if (b->nbitems > 1 &&  b->v[1] == &w) return;
+			if (b->nbitems > 0 &&  b->v[0] == &w) return;
+		}
+
+		/*check that l is not 0 (this should not happen as MaxDepth = 30)*/
+		_assert_(level>0);
+
+		/*Now, try to add the vertex, if the subbox is full (nbitems=4), we have to divide it
+		  in 4 new subboxes*/
+		while ((b= *pb) && (b->nbitems == 4)){ // the BamgQuadtreeBox is full
+
+			/*Copy the 4 vertices in the current BamgQuadtreebox*/
+			BamgVertex* v4[4];
+			v4[0]= b->v[0];
+			v4[1]= b->v[1];
+			v4[2]= b->v[2];
+			v4[3]= b->v[3];
+
+			/*set nbitems as negative 
+			 * (box full -> holds 4 pointers toward subboxes and not 4 vertices)*/
+			b->nbitems = -b->nbitems;
+
+			/*Initialize the 4 pointers toward the 4 subboxes*/
+			b->b[0]=b->b[1]=b->b[2]=b->b[3]=NULL;
+
+			/*level = 0010000 -> 0001000*/
+			level >>= 1;
+
+			/*Put the four vertices in the new boxes*/
+			for (int k=0;k<4;k++){
+
+				int          ij;
+				/*bb is the new "sub"box of b where v4[k] is located*/
+				BamgQuadtreeBox *bb = b->b[ij=IJ(v4[k]->i.x,v4[k]->i.y,level)];
+
+				// alloc the BamgQuadtreeBox
+				if (!bb) bb=b->b[ij]=NewBamgQuadtreeBox(); 
+
+				/*Copy the current vertex*/
+				bb->v[bb->nbitems++] = v4[k];
+			}
+
+			/*Get the subbox where w (i,j) is located*/
+			pb = &b->b[IJ(i,j,level)];
+		}
+
+		/*alloc the BamgQuadtreeBox if necessary*/
+		if (!(b=*pb)) b=*pb= NewBamgQuadtreeBox();
+
+		/*Add w*/
+		b->v[b->nbitems++]=&w;
+
+		//Increase NbVertices by one (we have one new vertex)
+		NbVertices++;
+	}
+	/*}}}*/
+	/*FUNCTION BamgQuadtree::NearestVertex{{{*/
+	BamgVertex*  BamgQuadtree::NearestVertex(Icoor1 i,Icoor1 j) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, BamgQuadtree.cpp/NearestVertex)*/
+
+		/*Intermediaries*/
+		BamgQuadtreeBox *pb[MaxDepth];
+		int          pi[MaxDepth];
+		Icoor1       ii[MaxDepth];
+		Icoor1       jj[MaxDepth];
+		int          level;
+		long         n0;
+		BamgQuadtreeBox *b;
+		long         h0;
+		long         h = MaxISize;
+		long         hb= MaxISize;
+		Icoor1       i0=0,j0=0;
+
+		/*initial output as NULL (no vertex found)*/
+		BamgVertex*  nearest_v=NULL;
+
+		/*Project w coordinates (i,j) onto [0,MaxISize-1] x [0,MaxISize-1] -> (iplus,jplus)*/
+		Icoor1 iplus( i<MaxISize ? (i<0?0:i) : MaxISize-1);
+		Icoor1 jplus( j<MaxISize ? (j<0?0:j) : MaxISize-1);
+
+		/*Get initial Quadtree box (largest)*/
+		b = root;
+
+		/*if the tree is empty, return NULL pointer*/
+		if (!root->nbitems) return nearest_v; 
+
+		/*else, find the smallest non-empty BamgQuadtreeBox containing  the point (i,j)*/
+		while((n0=b->nbitems)<0){
+
+			Icoor1       hb2 = hb >> 1;             //size of the current box
+			int          k   = IJ(iplus,jplus,hb2); //box number (0,1,2 or 3)
+			BamgQuadtreeBox *b0  = b->b[k];             //pointer toward current box
+
+			/* break if NULL box or empty (Keep previous box b)*/
+			if (( b0 == NULL) || (b0->nbitems == 0)) break;
+
+			/*Get next Quadtree box*/
+			b=b0;	
+			i0 += I_IJ(k,hb2); // i orign of BamgQuadtreeBox (macro)
+			j0 += J_IJ(k,hb2); // j orign of BamgQuadtreeBox 
+			hb = hb2;          // size of the box (in Int)
+		}
+
+		/*The box b, is the smallest box containing the point (i,j) and
+		 * has the following properties:
+		 * - n0: number of items (>0 if vertices, else boxes)
+		 * - hb: box size (int)
+		 * - i0: x coordinate of the lower left corner
+		 * - j0: y coordinate of the lower left corner*/
+
+		/* if the current subbox is holding vertices, we are almost done*/
+		if (n0>0){  
+			//loop over the vertices of the box and find the closest vertex
+			for(int k=0;k<n0;k++){
+
+				/*get integer coordinates of current vertex*/
+				I2 i2=b->v[k]->i;
+
+				/*Compute norm with w*/
+				h0=NORM(iplus,i2.x,jplus,i2.y);
+
+				/*is it smaller than previous value*/
+				if (h0<h){
+					h = h0;
+					nearest_v = b->v[k];
+				}
+			}
+			/*return closest vertex*/
+			return nearest_v;
+		}
+
+		/* general case: the current box is empty, we have to go backwards
+			and find the closest not-empty box and find the closest vertex*/
+
+		/*Initialize search variables*/
+		pb[0]=b;                             //pointer toward the box b
+		pi[0]=b->nbitems>0?(int)b->nbitems:4;//number of boxes in b
+		ii[0]=i0;                            //i coordinate of the box lowest left corner
+		jj[0]=j0;                            //j coordinate of the box lowest left corner
+
+		/*initialize h: smallest box size, containing a vertex close to w*/
+		h=hb;
+
+		/*Main loop*/
+		level=0;
+		do {
+
+			/*get current box*/
+			b= pb[level];
+
+			/*Loop over the items in current box (if not empty!)*/
+			while (pi[level]){
+
+				/*We are looping now over the items of b. k is the current index (in [0 3])*/
+				pi[level]--;
+				int k=pi[level];
+
+				/*if the current subbox is holding vertices (b->nbitems<0 is subboxes)*/
+				if (b->nbitems>0){
+					I2 i2=b->v[k]->i;
+					h0 = NORM(iplus,i2.x,jplus,i2.y);
+					if (h0<h){
+						h=h0;
+						nearest_v=b->v[k];
+					}
+				}
+				/*else: current box b is pointing toward 4 boxes
+				 * test sub-box k and go deeper into the tree if it is non empty
+				 * and contains the point w modulo a size h that is either the size of the smallest
+				 * non empty box containing w, or the closest point to w (so far) */
+				else{
+					BamgQuadtreeBox* b0=b;
+
+					/*if the next box exists:*/
+					if (b=b->b[k]){
+
+						/*Get size (hb) and coordinates of the current sub-box lowest left corner*/
+						hb>>=1;
+						Icoor1 iii = ii[level]+I_IJ(k,hb);
+						Icoor1 jjj = jj[level]+J_IJ(k,hb);
+
+						/*if the current point (iplus,jplus) is in b (modulo h), this box is good:
+						 * it is holding vertices that are close to w */
+						if (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)){
+							level++;
+							pb[level]= b;
+							pi[level]= b->nbitems>0 ?(int)  b->nbitems : 4  ;
+							ii[level]= iii;
+							jj[level]= jjj;
+						}
+
+						//else go backwards
+						else{
+							//shifted righ by one bit: hb=001000000 -> 01000000
+							b=b0;
+							hb<<=1;
+						}
+					}
+					else{
+						/*Current box is NULL, go to next subbox of b (k=k-1)*/
+						b=b0;
+					}
+				}
+			}
+
+			/*We have found a vertex, now, let's try the other boxes of the previous level
+			 * in case there is a vertex closest to w that has not yet been tested*/
+			hb <<= 1;
+		} while (level--);
+
+		/*return nearest_v, nearest vertex*/
+		return nearest_v;
+
+	}
+	/*}}}*/
+	/*FUNCTION BamgQuadtree::NearestVertexWithNormal{{{*/
+	BamgVertex*  BamgQuadtree::NearestVertexWithNormal(Icoor1 i,Icoor1 j) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, BamgQuadtree.cpp/NearestVertexWithNormal)*/
+
+		BamgQuadtreeBox * pb[ MaxDepth ];
+		int  pi[ MaxDepth  ];
+		Icoor1 ii[  MaxDepth ], jj [ MaxDepth];
+		int l; // level
+		BamgQuadtreeBox * b;
+		long     h =MaxISize,h0;
+		long     hb=MaxISize;
+		Icoor1  i0=0,j0=0;
+		Icoor1  iplus( i<MaxISize?(i<0?0:i):MaxISize-1);
+		Icoor1  jplus( j<MaxISize?(j<0?0:j):MaxISize-1);
+
+		BamgVertex *vn=0;
+
+		// init for optimisation ---
+		b = root;
+		register long  n0;
+		if (!root->nbitems)
+		 return vn; // empty tree 
+
+		while( (n0 = b->nbitems) < 0) 
+		  {
+			// search the non empty 
+			// BamgQuadtreeBox containing  the point (i,j)
+			register Icoor1 hb2 = hb >> 1 ;
+			register  int k = IJ(iplus,jplus,hb2);// BamgQuadtreeBox number of size hb2 contening i;j
+			register BamgQuadtreeBox * b0= b->b[k];
+			if ( ( b0 == 0) || (b0->nbitems == 0) ) 
+			 break; // null box or empty   => break 	    
+			b=b0;	
+			i0 += I_IJ(k,hb2); // i orign of BamgQuadtreeBox
+			j0 += J_IJ(k,hb2); // j orign of BamgQuadtreeBox 
+			hb = hb2; 
+		  }
+
+
+		if ( n0 > 0) 
+		  {  
+			for(register int k=0;k<n0;k++)
+			  {
+				I2 i2 =  b->v[k]->i;
+				//   try if is in the right direction -- 
+				h0 = NORM(iplus,i2.x,jplus,i2.y);
+				if (h0 <h) {
+					h = h0;
+					vn = b->v[k];}
+			  }
+			if (vn) return vn; 
+		  }
+		// general case -----
+		// INITIALISATION OF THE HEAP 
+		l =0; // level 
+		pb[0]= b;
+		pi[0]=b->nbitems>0 ?(int)  b->nbitems : 4  ;
+		ii[0]=i0;
+		jj[0]=j0;
+		h=hb;
+		do {   // walk on the tree  
+			b= pb[l];
+			while (pi[l]--) // loop on 4 element of the box
+			  { 	      
+				int k = pi[l];
+
+				if (b->nbitems>0) // BamgVertex BamgQuadtreeBox none empty
+				  { 
+					I2 i2 =  b->v[k]->i;
+					// if good direction when try -- 
+
+					h0 = NORM(iplus,i2.x,jplus,i2.y);
+					if (h0 <h) 
+					  {
+						h = h0;
+						vn = b->v[k];
+					  }
+				  }
+				else // Pointer BamgQuadtreeBox 
+				  { 
+					register BamgQuadtreeBox *b0=b;
+					if ((b=b->b[k])) 
+					  {
+						hb >>=1 ; // div by 2
+						register Icoor1 iii = ii[l]+I_IJ(k,hb);
+						register Icoor1 jjj = jj[l]+J_IJ(k,hb);
+
+						if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+						  {
+							pb[++l]=  b;
+							pi[l]= b->nbitems>0 ?(int)  b->nbitems : 4  ;
+							ii[l]= iii;
+							jj[l]= jjj;
+
+						  }
+						else
+						 b=b0, hb <<=1 ;
+					  }
+					else
+					 b=b0;
+				  }
+			  }
+			hb <<= 1; // mul by 2 
+		} while (l--);
+
+		return vn;
+	}
+	/*}}}*/
+	/*FUNCTION BamgQuadtree::NewBamgQuadtreeBox {{{*/
+	BamgQuadtree::BamgQuadtreeBox* BamgQuadtree::NewBamgQuadtreeBox(void){
+
+		/*Output*/
+		BamgQuadtreeBox* newbox=NULL;
+
+		/*Create and initialize a new box*/
+		newbox=new BamgQuadtreeBox;
+		newbox->nbitems=0;
+		newbox->b[0]=NULL;
+		newbox->b[1]=NULL;
+		newbox->b[2]=NULL;
+		newbox->b[3]=NULL;
+
+		/*Add root to the container*/
+		boxcontainer->AddObject(newbox);
+
+		/*Increase counter*/
+		NbBamgQuadtreeBox++;
+
+		/*currentbox now points toward next quadtree box*/
+		return newbox;
+	}/*}}}*/
+	/*FUNCTION BamgQuadtree::ToClose {{{*/
+	BamgVertex*   BamgQuadtree::ToClose(BamgVertex & v,double seuil,Icoor1 hx,Icoor1 hy){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, BamgQuadtree.cpp/ToClose)*/
+
+		const Icoor1 i=v.i.x;
+		const Icoor1 j=v.i.y;
+		const R2 X(v.r);
+		const Metric  Mx(v.m);
+
+		BamgQuadtreeBox * pb[ MaxDepth ];
+		int  pi[ MaxDepth  ];
+		Icoor1 ii[  MaxDepth ], jj [ MaxDepth];
+		register int l=0; // level
+		register BamgQuadtreeBox * b;
+		Icoor1 h=MaxISize;
+		Icoor1 hb =  MaxISize;
+		Icoor1 i0=0,j0=0;
+
+		//  BamgVertex *vn=0;
+
+		if (!root->nbitems)
+		 return 0; // empty tree 
+
+		// general case -----
+		pb[0]=root;
+		pi[0]=root->nbitems>0 ?(int)  root->nbitems : 4  ;
+		ii[0]=i0;
+		jj[0]=j0;
+		h=hb;
+		do {    
+			b= pb[l];
+			while (pi[l]--){ 	      
+				register int k = pi[l];
+
+				if (b->nbitems>0){ // BamgVertex BamgQuadtreeBox none empty
+					I2 i2 =  b->v[k]->i;
+					if ( ABS(i-i2.x) <hx && ABS(j-i2.y) <hy )
+					  {
+						R2 XY(X,b->v[k]->r);
+						double dd;
+						if( (dd= LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil ){
+							return b->v[k]; 
+						}
+					  }
+				}
+				else{ // Pointer BamgQuadtreeBox 
+					register BamgQuadtreeBox *b0=b;
+					if ((b=b->b[k])){
+						hb >>=1 ; // div by 2
+						register long iii = ii[l]+I_IJ(k,hb);
+						register long jjj = jj[l]+J_IJ(k,hb);
+
+						if  (INTER_SEG(iii,iii+hb,i-hx,i+hx) && INTER_SEG(jjj,jjj+hb,j-hy,j+hy)){
+							pb[++l]=  b;
+							pi[l]= b->nbitems>0 ?(int)  b->nbitems : 4  ;
+							ii[l]= iii;
+							jj[l]= jjj;
+
+						}
+						else{
+							b=b0;
+							hb <<=1 ;
+						}
+					}
+					else{
+						b=b0;
+					}
+				}
+			}
+			hb <<= 1; // mul by 2 
+		} while (l--);
+
+		return 0;
+	}
+	/*}}}*/
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgQuadtree.h	(revision 12821)
@@ -0,0 +1,60 @@
+/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, BamgQuadtree.h)*/
+#ifndef _BAMGQUADTREE_H
+#define _BAMGQUADTREE_H
+
+#include "./include.h"
+
+namespace bamg {
+
+	const int  MaxDepth = 30;
+	const long MaxISize = ( 1L << MaxDepth);  // = 2^30 : 010000000000..000 (bitwise operation)
+
+	class BamgVertex;
+
+	class BamgQuadtree{
+
+		private:
+
+			/*A quadtree box contains a maximum of 4 vertices. 4 other quadtree boxes are
+			 * created if a fifth vertex is added to the same box. A Quadtree box is therefore
+			 * composed of EITHER:
+			 * - up to 4 vertices
+			 * - 4 "sub" quadtree boxes*/
+			class BamgQuadtreeBox: public Object{ 
+				public:
+					int nbitems; // number of current vertices in the box
+					union{
+						BamgQuadtreeBox* b[4];
+						BamgVertex*  v[4];
+					};
+					/*Object functions*/
+					void    Echo()       {_error2_("not implemented yet"); };
+					void    DeepEcho()   {_error2_("not implemented yet"); };
+					int     Id()         {_error2_("not implemented yet"); };
+					int     MyRank()     {_error2_("not implemented yet"); };
+					int     ObjectEnum() {_error2_("not implemented yet"); };
+					Object *copy()       {_error2_("not implemented yet"); };
+			};
+
+			/*BamgQuadtree private Fields*/
+			DataSet* boxcontainer;
+
+		public:
+
+			/*BamgQuadtree public Fields*/
+			BamgQuadtreeBox* root;
+			long         NbBamgQuadtreeBox;
+			long         NbVertices;
+
+			BamgQuadtree();
+			BamgQuadtree(Mesh *t,long nbv=-1);
+			~BamgQuadtree();
+
+			BamgVertex      *NearestVertex(Icoor1 i,Icoor1 j);
+			BamgVertex      *NearestVertexWithNormal(Icoor1  i,Icoor1 j);
+			BamgQuadtreeBox *NewBamgQuadtreeBox(void);
+			BamgVertex      *ToClose(BamgVertex &,double ,Icoor1,Icoor1);
+			void             Add(BamgVertex &w);
+	};
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.cpp	(revision 12821)
@@ -0,0 +1,256 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "../objects.h"
+
+namespace bamg {
+
+	/*Methods*/
+	/*FUNCTION BamgVertex::Echo {{{*/
+
+	void BamgVertex::Echo(void){
+
+		_printLine_("Vertex:");
+		_printLine_("  integer   coordinates i.x: " << i.x << ", i.y: " << i.y);
+		_printLine_("  Euclidean coordinates r.x: " << r.x << ", r.y: " << r.y);
+		_printLine_("  ReferenceNumber = " << ReferenceNumber);
+		m.Echo();
+
+		return;
+	}
+	/*}}}*/
+	/*FUNCTION BamgVertex::GetReferenceNumber{{{*/
+	int  BamgVertex::GetReferenceNumber() const { 
+		return ReferenceNumber;
+	}
+	/*}}}*/
+	/*FUNCTION BamgVertex::MetricFromHessian{{{*/
+	void BamgVertex::MetricFromHessian(const double Hxx,const double Hyx, const double Hyy,const double smin,const double smax,const double s,double err,BamgOpts* bamgopts){
+		/*Compute Metric from Hessian*/
+
+		/*get options*/
+		double power=(bamgopts->power);
+		double anisomax=(bamgopts->anisomax);
+		double CutOff=bamgopts->cutoff;
+		double hmin=(bamgopts->hmin);
+		double hmax=(bamgopts->hmax);
+		double coef=bamgopts->coeff;
+		int    Metrictype=(bamgopts->Metrictype);
+
+		/*Intermediary*/
+		double ci;
+
+		/*compute multiplicative coefficient depending on Metric Type (2/9 because it is 2d)*/
+
+		//Absolute Error
+		/*
+		 *            2         1       
+		 *Metric M = ---  ------------   Abs(Hessian)
+		 *            9   err * coeff^2  
+		 */
+		if (Metrictype==0){
+			ci= 2.0/9.0 * 1/(err*coef*coef);
+		}
+
+		//Relative Error
+		/*
+		 *            2         1            Abs(Hessian)
+		 *Metric M = ---  ------------  ----------------------
+		 *            9   err * coeff^2  max( |s| , cutoff*max(|s|) )
+		 *
+		 */
+		else if (Metrictype==1){
+			ci= 2.0/9.0 * 1/(err*coef*coef) * 1/Max( Abs(s), CutOff*(Max(Abs(smin),Abs(smax))));
+		}
+
+		//Rescaled absolute error
+		/*
+		 *            2         1            Abs(Hessian)
+		 *Metric M = ---  ------------  ---------------------- 
+		 *            9   err * coeff^2       (smax-smin)
+		 */
+		else if (Metrictype==2){
+			ci= 2.0/9.0 * 1/(err*coef*coef) * 1/(smax-smin);
+		}
+		else{
+			_error2_("Metrictype " << Metrictype << " not supported yet (use 0,1 or 2(default))");
+		}
+
+		//initialize metric Miv with ci*H
+		Metric Miv(Hxx*ci,Hyx*ci,Hyy*ci);
+
+		//Get eigen values and vectors of Miv
+		EigenMetric Vp(Miv);
+
+		//move eigen valuse to their absolute values
+		Vp.Abs();
+
+		//Apply a power if requested by user
+		if(power!=1.0) Vp.pow(power);
+
+		//modify eigen values according to hmin and hmax
+		Vp.Maxh(hmax);
+		Vp.Minh(hmin);
+
+		//Bound anisotropy by 1/(anisomax)^2
+		Vp.BoundAniso2(1/(anisomax*anisomax));
+
+		//rebuild Metric from Vp
+		Metric MVp(Vp);
+
+		//Apply Metric to vertex
+		m.IntersectWith(MVp);
+
+	}
+	/*}}}*/
+	/*FUNCTION BamgVertex::Optim {{{*/
+	long BamgVertex::Optim(int i,int koption){ 
+		long ret=0;
+		if ( t && (IndexInTriangle >= 0 ) && (IndexInTriangle <3) ){
+			ret = t->Optim(IndexInTriangle,koption);
+			if(!i){
+				t =0; // for no future optime 
+				IndexInTriangle= 0;
+			}
+		}
+		return ret;
+	}
+	/*}}}*/
+	/*FUNCTION BamgVertex::Smoothing{{{*/
+	double  BamgVertex::Smoothing(Mesh &Th,const Mesh &BTh,Triangle* &tstart ,double omega){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Smoothing)*/
+
+		register BamgVertex* s=this;
+		BamgVertex &vP = *s,vPsave=vP;
+
+		register Triangle* tbegin= t , *tria = t , *ttc;
+
+		register int k=0,kk=0,j = EdgesVertexTriangle[IndexInTriangle][0],jc;
+		R2 P(s->r),PNew(0,0);
+		do {
+			k++; 
+
+			if (!tria->Hidden(j)){
+				BamgVertex &vQ = (*tria)[VerticesOfTriangularEdge[j][0]]; 
+
+				R2 Q = vQ,QP(P-Q);
+				double lQP = LengthInterpole(vP,vQ,QP);
+				PNew += Q+QP/Max(lQP,1e-20);
+				kk ++;
+			}
+			ttc =  tria->TriangleAdj(j);
+			jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+			tria = ttc;
+			j = NextEdge[jc];
+			if (k>=2000){
+				_error2_("k>=2000 (Maximum number of iterations reached)");
+			}
+		} while ( tbegin != tria); 
+		if (kk<4) return 0;
+		PNew = PNew/(double)kk;
+		R2 Xmove((PNew-P)*omega);
+		PNew = P+Xmove;
+		double delta=Norme2_2(Xmove); 
+
+		Icoor2 deta[3];
+		I2 IBTh  = BTh.R2ToI2(PNew);
+
+		tstart=BTh.TriangleFindFromCoord(IBTh,deta,tstart);  
+
+		if (tstart->det <0){ // outside
+			double ba,bb;
+			AdjacentTriangle edge= CloseBoundaryEdge(IBTh,tstart,ba,bb) ;
+			tstart = edge;
+			vP.m= Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));
+		}
+		else { // inside
+			double   aa[3];
+			double s = deta[0]+deta[1]+deta[2];
+			aa[0]=deta[0]/s;
+			aa[1]=deta[1]/s;
+			aa[2]=deta[2]/s;
+			vP.m = Metric(aa,(*tstart)[0],(*tstart)[1],(*tstart)[2]);
+		}
+
+		// recompute the det of the triangle
+		vP.r = PNew;
+
+		vP.i = Th.R2ToI2(PNew);
+
+		BamgVertex vPnew = vP;
+
+		int ok=1;
+		int loop=1;
+		k=0;
+		while (ok){
+			ok =0;
+			do {
+				k++; 
+				double detold = tria->det;
+				tria->det =  bamg::det( (*tria)[0],(*tria)[1]  ,(*tria)[2]);
+				if (loop) {
+					BamgVertex *v0,*v1,*v2,*v3;
+					if (tria->det<0) ok =1;			       
+					else if (tria->Quadrangle(v0,v1,v2,v3))
+					  {
+						vP = vPsave;
+						double qold =QuadQuality(*v0,*v1,*v2,*v3);
+						vP = vPnew;
+						double qnew =QuadQuality(*v0,*v1,*v2,*v3);
+						if (qnew<qold) ok = 1;
+					  }
+					else if ( (double)tria->det < detold/2 ) ok=1;
+
+				}
+				tria->SetUnMarkUnSwap(0);
+				tria->SetUnMarkUnSwap(1);
+				tria->SetUnMarkUnSwap(2);
+				ttc =  tria->TriangleAdj(j);
+				jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+				tria = ttc;
+				j = NextEdge[jc];
+				if (k>=2000){
+					_error2_("k>=2000");
+				}
+			}while ( tbegin != tria); 
+
+			if (ok && loop) vP=vPsave; // no move 
+			loop=0;
+		}
+		return delta;
+	}
+	/*}}}*/
+
+	/*Intermediary*/
+	/*FUNCTION QuadQuality{{{*/
+	double QuadQuality(const BamgVertex & a,const BamgVertex &b,const BamgVertex &c,const BamgVertex &d) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshQuad.cpp/QuadQuality)*/
+
+		// calcul de 4 angles --
+		R2 A((R2)a),B((R2)b),C((R2)c),D((R2)d);
+		R2 AB(B-A),BC(C-B),CD(D-C),DA(A-D);
+		//  Move(A),Line(B),Line(C),Line(D),Line(A);
+		const Metric & Ma  = a;
+		const Metric & Mb  = b;
+		const Metric & Mc  = c;
+		const Metric & Md  = d;
+
+		double lAB=Norme2(AB);
+		double lBC=Norme2(BC);
+		double lCD=Norme2(CD);
+		double lDA=Norme2(DA);
+		AB /= lAB;  BC /= lBC;  CD /= lCD;  DA /= lDA;
+		// version aniso 
+		double cosDAB= Ma(DA,AB)/(Ma(DA)*Ma(AB)),sinDAB= Det(DA,AB);
+		double cosABC= Mb(AB,BC)/(Mb(AB)*Mb(BC)),sinABC= Det(AB,BC);
+		double cosBCD= Mc(BC,CD)/(Mc(BC)*Mc(CD)),sinBCD= Det(BC,CD);
+		double cosCDA= Md(CD,DA)/(Md(CD)*Md(DA)),sinCDA= Det(CD,DA);
+		double sinmin=Min(Min(sinDAB,sinABC),Min(sinBCD,sinCDA));
+		if (sinmin<=0) return sinmin;
+		return 1.0-Max(Max(Abs(cosDAB),Abs(cosABC)),Max(Abs(cosBCD),Abs(cosCDA)));
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/BamgVertex.h	(revision 12821)
@@ -0,0 +1,58 @@
+#ifndef _BAMGVERTEX_H_
+#define _BAMGVERTEX_H_
+
+#include "./include.h"
+#include "./Metric.h"
+#include "./Direction.h"
+#include "./BamgOpts.h"
+
+namespace bamg {
+
+	//classes
+	class Triangle;
+	class Mesh;
+	class VertexOnGeom;
+	class VertexOnEdge;
+
+	class BamgVertex {
+
+		public:
+
+			/*Fields*/
+			I2        i;                 // integer coordinates
+			R2        r;                 // real coordinates
+			Metric    m;
+			long      ReferenceNumber;
+			Direction DirOfSearch;
+			short     IndexInTriangle;              // the vertex number in triangle; varies between 0 and 2 in t
+
+			union {
+				Triangle     *t;                      // one triangle which is containing the vertex
+				long          color;
+				BamgVertex   *MeshVertexHook;         // used in geometry BamgVertex to know the Mesh Vertex associated
+				VertexOnGeom *GeomEdgeHook;    // if IndexInTriangle == 8; // set with Mesh::SetVertexFieldOn()
+				BamgVertex   *BackgroundVertexHook;   // if IndexInTriangle == 16 on Background vertex Mesh::SetVertexFieldOnBTh()
+				VertexOnEdge *BackgroundEdgeHook;     // if IndexInTriangle == 32 on Background edge
+			};
+
+			/*Operators*/
+			operator I2() const {return i;}             // Cast operator
+			operator const R2 & () const {return r;}    // Cast operator
+			operator Metric () const {return m;}        // Cast operator
+			double operator()(R2 x) const { return m(x);} // Get x in the metric m
+
+			/*methods (No constructor and no destructors...)*/
+			double Smoothing(Mesh & ,const Mesh & ,Triangle  * & ,double =1);
+			void   MetricFromHessian(const double Hxx,const double Hyx, const double Hyy, const double smin,const double smax,const double s,const double err,BamgOpts* bamgopts);
+			void   Echo();
+			int    GetReferenceNumber() const;
+			long   Optim(int =1,int =0); 
+
+			//inline functions
+			inline void Set(const BamgVertex &rec,const Mesh & ,Mesh & ){*this=rec;}
+	};
+
+	//Intermediary
+	double QuadQuality(const BamgVertex &,const BamgVertex &,const BamgVertex &,const BamgVertex &);
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.cpp	(revision 12821)
@@ -0,0 +1,33 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "CrackedEdge.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION CrackedEdge() {{{*/
+	CrackedEdge::CrackedEdge() {
+		a=NULL;
+		b=NULL;
+		E=NULL;
+		e1=NULL;
+		e2=NULL;
+		indexa[0]=-1;
+		indexa[1]=-1;
+		indexa[2]=-1;
+		indexb[0]=-1;
+		indexb[1]=-1;
+		indexb[2]=-1;
+		length=0;
+		normal.x=0;
+		normal.y=0;
+
+	}
+	/*}}}*/
+
+	/*Methods*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/CrackedEdge.h	(revision 12821)
@@ -0,0 +1,31 @@
+#ifndef _CRACKEDEDGE_H_
+#define _CRACKEDEDGE_H_
+
+#include "./typedefs.h"
+
+namespace bamg {
+
+	//classes
+	class Triangle;
+	class GeomEdge;
+	class Edge;
+
+	class CrackedEdge {
+
+		public:
+			Triangle* a;
+			Triangle* b; 
+			GeomEdge* E;
+			Edge* e1;
+			Edge* e2;
+			double length;
+			R2     normal;
+			long   indexa[3];
+			long   indexb[3];
+
+			//Constructors
+			CrackedEdge();
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Curve.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Curve.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Curve.cpp	(revision 12821)
@@ -0,0 +1,37 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "Curve.h"
+#include "Geometry.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION Curve::Curve(){{{*/
+	Curve::Curve(){
+		FirstEdge=NULL;
+		LastEdge=NULL;
+		FirstVertexIndex=0;
+		LastVertexIndex=0;
+	} 
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Curve::Reverse {{{*/
+	void Curve::Reverse() {
+		/*reverse the direction of the curve */
+		Exchange(FirstEdge,LastEdge);
+		Exchange(FirstVertexIndex,LastVertexIndex);
+	}
+	/*}}}*/
+	/*FUNCTION Curve::Set {{{*/
+	void Curve::Set(const Curve & rec,const Geometry & Gh ,Geometry & GhNew){
+		*this = rec;
+		FirstEdge = GhNew.edges + Gh.GetId(FirstEdge);    
+		LastEdge = GhNew.edges + Gh.GetId(LastEdge); 
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/Curve.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Curve.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Curve.h	(revision 12821)
@@ -0,0 +1,27 @@
+#ifndef _CURVE_H_
+#define _CURVE_H_
+
+#include "../../shared/Bamg/shared.h"
+
+namespace bamg {
+
+	//classes
+	class GeomEdge;
+	class Curve;
+	class Geometry;
+
+	class Curve {
+		public:
+			GeomEdge *FirstEdge; //First edge of the curve
+			GeomEdge *LastEdge;  //Last edge of the curve
+			int FirstVertexIndex;       //Last vertex index in the last edge
+			int LastVertexIndex;        //First Vertex index in the first edge
+
+			//Methods
+			Curve();
+			void Reverse(void);
+			void Set(const Curve & rec,const Geometry & Th ,Geometry & ThNew);
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Direction.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Direction.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Direction.cpp	(revision 12821)
@@ -0,0 +1,36 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "Direction.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION Direction() {{{*/
+	Direction::Direction():
+		dir(MaxICoor){
+
+	}/*}}}*/
+	/*FUNCTION Direction(Icoor1 i,Icoor1 j) {{{*/
+	Direction::Direction(Icoor1 i,Icoor1 j) {
+		Icoor2 n2 = 2*(Abs(i)+Abs(j));  
+		Icoor2 r  = MaxICoor* (Icoor2) i;
+		Icoor1 r1 = (Icoor1) (2*(r/ n2)); // odd number 
+		dir = (j>0) ? r1 : r1+1;          // odd-> j>0 even-> j<0
+	}/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Direction::direction{{{*/
+	int Direction::direction(Icoor1 i,Icoor1 j) {
+		int r =1; 
+		if (dir!= MaxICoor) {
+			Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1);
+			r = (x*i + y*j) >=0;
+		}
+		return r;
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/Direction.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Direction.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Direction.h	(revision 12821)
@@ -0,0 +1,21 @@
+#ifndef _DIRECTION_H_
+#define _DIRECTION_H_
+
+#include "./include.h"
+#include "../../shared/Bamg/shared.h"
+
+namespace bamg {
+
+	class Direction {
+		private:
+			Icoor1 dir;
+
+		public:
+			//Methods
+			Direction();
+			Direction(Icoor1 i,Icoor1 j);
+			int direction(Icoor1 i,Icoor1 j);
+	};
+}
+#endif
+
Index: /issm/trunk-jpl/src/c/classes/bamg/DoubleAndInt.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/DoubleAndInt.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/DoubleAndInt.h	(revision 12821)
@@ -0,0 +1,19 @@
+#ifndef _DOUBLEANDINT_H_
+#define _DOUBLEANDINT_H_
+
+#include "./include.h"
+
+namespace bamg {
+
+	class DoubleAndInt {
+		//class used by Mesh::MakeQuadrangles
+
+		public:
+			double q;
+			long i3j;
+
+			//Operators
+			int operator<(DoubleAndInt a){return q > a.q;}
+	};
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Edge.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Edge.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Edge.cpp	(revision 12821)
@@ -0,0 +1,54 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "Edge.h"
+#include "Mesh.h"
+#include "Geometry.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+
+	/*Methods*/
+	/*FUNCTION Edge::Set {{{*/
+	void Edge::Set(const Mesh & Th ,long i,Mesh & ThNew){ 
+		*this = Th.edges[i];
+		v[0] = ThNew.vertices + Th.GetId(v[0]);    
+		v[1] = ThNew.vertices + Th.GetId(v[1]);
+		if (GeomEdgeHook) 
+		 GeomEdgeHook =  ThNew.Gh.edges+Th.Gh.GetId(GeomEdgeHook);
+		if (adj[0]) adj[0] =   ThNew.edges +   Th.GetId(adj[0]);
+		if (adj[1]) adj[1] =   ThNew.edges +   Th.GetId(adj[1]);
+	}
+	/*}}}*/
+	/*FUNCTION Edge::Echo {{{*/
+	void Edge::Echo(void){ 
+		_printLine_("Edge:");
+		_printLine_("   pointers towards two vertices: " << v[0] << " " << v[1]);
+		_printLine_("   ReferenceNumber = " << ReferenceNumber);
+		_printLine_("   GeomEdgeHook = " << GeomEdgeHook);
+		_printLine_("   two adjacent edges on the same curve: " << adj[0] << " " << adj[1]);
+	}
+	/*}}}*/
+	/*FUNCTION Edge::Renumbering{{{*/
+	void Edge::Renumbering(BamgVertex *vb,BamgVertex *ve, long *renu){
+
+		if (v[0] >=vb && v[0] <ve) v[0] = vb + renu[v[0]-vb];
+		if (v[1] >=vb && v[1] <ve) v[1] = vb + renu[v[1]-vb];
+
+	}
+	/*}}}*/
+	/*FUNCTION Edge::Intersection{{{*/
+	int Edge::Intersection(const  Edge & e){ 
+
+		/*some shecks*/
+		if (!(adj[0]==&e || adj[1]==&e)){ _error2_("Intersection bug"); }
+		_assert_(adj[0]==&e || adj[1]==&e);
+
+		return adj[0]==&e?0:1;
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/Edge.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Edge.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Edge.h	(revision 12821)
@@ -0,0 +1,38 @@
+#ifndef _EDGE_H_
+#define _EDGE_H_
+
+#include "./include.h"
+#include "./BamgVertex.h"
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+#include "./GeomEdge.h"
+
+namespace bamg {
+
+	//classes
+	class Mesh;
+	
+	class Edge {
+
+		public:
+			BamgVertex      *v[2];
+			long             ReferenceNumber;
+			GeomEdge *GeomEdgeHook;
+			Edge            *adj[2];       // the 2 adj edges if on the same curve
+
+			//Operators
+			BamgVertex       &operator[](int i){return *v[i];   };
+			BamgVertex       *operator()(int     i){return v[i];};
+			R2                operator()(double  t) const;// return the point
+			const BamgVertex &operator[](int i) const{return *v[i];};
+
+			//Methods
+			void Renumbering(BamgVertex *vb,BamgVertex *ve, long *renu);
+			int  Intersection(const  Edge & e);
+			void Set(const Mesh &,long,Mesh &);
+			void Echo(void);
+
+	};
+}
+#endif
+
Index: /issm/trunk-jpl/src/c/classes/bamg/EigenMetric.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/EigenMetric.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/EigenMetric.cpp	(revision 12821)
@@ -0,0 +1,168 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "Metric.h"
+
+namespace bamg {
+
+	/*Constructor*/
+	/*FUNCTION EigenMetric::EigenMetric(const Metric M){{{*/
+	EigenMetric::EigenMetric(const Metric& M){
+		/*From a metric (a11,a21,a22), get eigen values lambda1 and lambda2 and one eigen vector v*/
+
+		/*Intermediaries*/
+		double a11=M.a11,a21=M.a21,a22=M.a22;
+		double normM;
+		double delta,b;
+
+		/*To get the eigen values, we must solve the following equation:
+		 *     | a11 - lambda    a21        |
+		 * det |                            | = 0
+		 *     | a21             a22-lambda |
+		 *
+		 * We have to solve the following polynom:
+		 *  lamda^2 + ( -a11 -a22)*lambda + (a11*a22-a21*a21) = 0*/
+
+		/*Compute polynom determinant*/
+		b=-a11-a22;
+		delta=b*b - 4*(a11*a22-a21*a21);
+
+
+		/*Compute norm of M to avoid round off errors*/
+		normM=a11*a11 + a22*a22 + a21*a21;
+
+		/*1: normM too small: eigen values = 0*/
+		if(normM<1.e-30){
+			lambda1=0;
+			lambda2=0;
+			v.x=1;
+			v.y=0;
+		}
+		/*2: delta is small -> double root*/
+		else if (delta < 1.e-5*normM){
+			lambda1=-b/2;
+			lambda2=-b/2;
+			v.x=1;
+			v.y=0;
+		}
+		/*3: general case -> two roots*/
+		else{
+			delta     = sqrt(delta);
+			lambda1   = (-b-delta)/2.0;
+			lambda2   = (-b+delta)/2.0;
+
+			/*Now, one must find the eigen vectors. For that we use the following property of the inner product
+			 *    <Ax,y> = <x,tAy>
+			 * Here, M'(M-lambda*Id) is symmetrical, which gives:
+			 *    ∀(x,y)∈R²xR² <M'x,y> = <M'y,x>
+			 * And we have the following:
+			 *    if y∈Ker(M'), ∀x∈R² <M'x,y> = <x,M'y> = 0
+			 * We have shown that
+			 *    Im(M') ⊥ Ker(M')
+			 *
+			 * To find the eigen vectors of M, we only have to find two vectors
+			 * of the image of M' and take their perpendicular as long as they are
+			 * not 0.
+			 * To do that, we take the images (1,0) and (0,1):
+			 *  x1 = (a11 - lambda)      x2 = a21
+			 *  y1 = a21                 y2 = (a22-lambda)
+			 *
+			 * We take the vector that has the larger norm and take its perpendicular.*/
+
+			double norm1 = (a11-lambda1)*(a11-lambda1) + a21*a21; 
+			double norm2 = a21*a21 + (a22-lambda1)*(a22-lambda1);
+
+			if (norm2<norm1){
+				norm1=sqrt(norm1);
+				v.x = - a21/norm1;
+				v.y = (a11-lambda1)/norm1;
+			}
+			else{
+				norm2=sqrt(norm2);
+				v.x = - (a22-lambda1)/norm2;
+				v.y = a21/norm2;
+			}
+		}
+
+	}
+	/*}}}*/
+	/*FUNCTION EigenMetric::EigenMetric(double r1,double r2,const D2 vp1){{{*/
+	EigenMetric::EigenMetric(double r1,double r2,const D2& vp1): lambda1(r1),lambda2(r2),v(vp1){
+
+	}/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION EigenMetric::Abs{{{*/
+	void   EigenMetric::Abs(){
+		lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Aniso{{{*/
+	double EigenMetric::Aniso() const  { 
+		return sqrt( Aniso2());
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Aniso2{{{*/
+	double EigenMetric::Aniso2() const  { 
+		return lmax()/lmin();
+	}/*}}}*/
+	/*FUNCTION EigenMetric::BoundAniso{{{*/
+	void   EigenMetric::BoundAniso(const double c){ 
+		BoundAniso2(1/(c*c));
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Echo {{{*/
+	void EigenMetric::Echo(void){
+
+		_printLine_("EigenMetric:");
+		_printLine_("   lambda1: " << lambda1);
+		_printLine_("   lambda2: " << lambda2);
+		_printLine_("   v.x: " << v.x);
+		_printLine_("   v.y: " << v.y);
+
+		return;
+	}
+	/*}}}*/
+	/*FUNCTION EigenMetric::hmin{{{*/
+	double EigenMetric::hmin() const {
+		return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));
+	}/*}}}*/
+	/*FUNCTION EigenMetric::hmax{{{*/
+	double EigenMetric::hmax() const {
+		return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Isotrope{{{*/
+	void   EigenMetric::Isotrope() {
+		lambda1=lambda2=bamg::Max(lambda1,lambda2);
+	}/*}}}*/
+	/*FUNCTION EigenMetric::lmax{{{*/
+	double EigenMetric::lmax() const {
+		return bamg::Max3(lambda1,lambda2,1e-30);
+	}/*}}}*/
+	/*FUNCTION EigenMetric::lmin{{{*/
+	double EigenMetric::lmin() const {
+		return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Min{{{*/
+	void   EigenMetric::Min(double a) { 
+		lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Max{{{*/
+	void   EigenMetric::Max(double a) { 
+		//change eigen values
+		lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Minh{{{*/
+	void   EigenMetric::Minh(double h) {
+		Min(1.0/(h*h));
+	}/*}}}*/
+	/*FUNCTION EigenMetric::Maxh{{{*/
+	void   EigenMetric::Maxh(double h) {
+		//Call Max function
+		Max(1.0/(h*h));
+	}/*}}}*/
+	/*FUNCTION EigenMetric::pow{{{*/
+	void   EigenMetric::pow(double p){
+		lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);
+	}/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.cpp	(revision 12821)
@@ -0,0 +1,190 @@
+#include <cstdio>
+#include <string.h>
+#include <cmath>
+
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+
+#include "GeomEdge.h"
+#include "Geometry.h"
+
+using namespace std;
+
+namespace bamg {
+
+	/*Constructor/Destructor*/
+
+	/*Methods*/
+	/*FUNCTION GeomEdge::Cracked{{{*/
+	int    GeomEdge::Cracked() const  {
+		return type &1;  
+	}/*}}}*/
+	/*FUNCTION GeomEdge::F{{{*/
+	R2 GeomEdge::F(double theta) const{
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/F)*/
+		// parametrization of the curve edge
+
+	   R2 A=v[0]->r,B=v[1]->r;
+		double ca,cb,cta,ctb;
+
+		//Check that theta is in [0 1]
+		_assert_(theta>-1e-12 && theta<1+1e-12);
+
+		if (TgA()){ 
+			if (TgB()){ //Hermite interpolation
+				cb =  theta*theta*(3-2*theta);
+				ca =  1-cb;     
+				cta = (1-theta)*(1-theta)*theta;
+				ctb = (theta-1)*theta*theta ;
+			}
+			else {
+				double t = theta;
+				cb = t*t;
+				ca = 1-cb;
+				cta= t-cb;
+				ctb=0;    
+			}
+		}
+		else{
+			if (TgB()){
+				double t = 1-theta;
+				ca = t*t;
+				cb = 1-ca;
+				ctb= -t+ca;
+				cta=0;    
+			}
+			else { // lagrange P1
+				ca =(1-theta);
+				cb = theta;
+				cta=ctb=0;
+			}
+		}
+		return A*ca + B*cb + tg[0]*cta + tg[1]*ctb;
+	  }
+	/*}}}*/
+	/*FUNCTION GeomEdge::Mark{{{*/
+	int    GeomEdge::Mark()    const  {
+		return type &16; 
+	}/*}}}*/
+	/*FUNCTION GeomEdge::R1tg{{{*/
+	double GeomEdge::R1tg(double theta,R2 & t) const{
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/R1tg)*/
+		// 1/R of radius of cuvature
+
+		R2 A=v[0]->r,B=v[1]->r;
+		double dca,dcb,dcta,dctb;
+		double ddca,ddcb,ddcta,ddctb;
+		double tt = theta*theta;
+
+		//check theta
+		_assert_(theta>=0 && theta<=1);
+
+		if (TgA()){ 
+			if (TgB()){
+				// Tangent A and B provided:
+				// interpolation d'hermite
+				dcb = 6*theta*(1-theta);
+				ddcb = 6*(1-2*theta);
+				dca = -dcb;
+				ddca = -ddcb;
+				dcta =  (3*theta - 4)*theta + 1;
+				ddcta=6*theta-4;
+				dctb = 3*tt - 2*theta;
+				ddctb = 6*theta-2;
+			}
+			else {
+				//Tangent A provided but tangent B not provided
+				// 1-t*t, t-t*t, t*t
+				double t = theta;
+				dcb = 2*t;
+				ddcb = 2;
+				dca = -dcb;
+				ddca = -2;
+				dcta = 1-dcb;
+				ddcta = -ddcb;
+				dctb=0;    
+				ddctb=0;    
+			}
+		}
+		else{
+			if (TgB()){
+				//Tangent B provided but tangent A not provided
+				double t = 1-theta;
+				dca = -2*t;
+				ddca = 2;
+				dcb = -dca;
+				ddcb = -2;
+				dctb = 1+dca;
+				ddctb= ddca;
+				dcta =0;
+				ddcta =0;
+			}
+			else {
+				//Neither thangent A nor tangent B provided
+				// lagrange P1
+				t=B-A;
+				return 0;
+			} 
+		}
+		R2 d  =  A*dca  + B*dcb  + tg[0]* dcta  + tg[1] * dctb;
+		R2 dd =  A*ddca + B*ddcb + tg[0]* ddcta + tg[1] * ddctb;
+		double d2=(d,d);
+		double sd2 = sqrt(d2);
+		t=d;
+		if(d2>1.0e-20){
+			t/=sd2;
+			return Abs(Det(d,dd))/(d2*sd2);
+		}
+		else return 0;
+	}
+	/*}}}*/
+	/*FUNCTION GeomEdge::Required{{{*/
+	int    GeomEdge::Required()       {
+		return type &64; 
+	}/*}}}*/
+	/*FUNCTION GeomEdge::Set {{{*/
+	void GeomEdge::Set(const GeomEdge & rec,const Geometry & Gh ,Geometry & GhNew){ 
+		*this = rec;
+		v[0] = GhNew.vertices + Gh.GetId(v[0]);    
+		v[1] = GhNew.vertices + Gh.GetId(v[1]); 
+		if (Adj[0]) Adj[0] =  GhNew.edges + Gh.GetId(Adj[0]);     
+		if (Adj[1]) Adj[1] =  GhNew.edges + Gh.GetId(Adj[1]);     
+	}
+	/*}}}*/
+	/*FUNCTION GeomEdge::SetCracked{{{*/
+	void   GeomEdge::SetCracked()     { 
+		type |= 1;/*=>1st digit to 1*/
+	}/*}}}*/
+	/*FUNCTION GeomEdge::SetTgA{{{*/
+	void   GeomEdge::SetTgA()         { 
+		type |=4; /*=>2d digit to 1*/
+	}/*}}}*/
+	/*FUNCTION GeomEdge::SetTgB{{{*/
+	void   GeomEdge::SetTgB()         { 
+		type |=8; /*=> 3d digit to 1*/
+	}/*}}}*/
+	/*FUNCTION GeomEdge::SetMark{{{*/
+	void   GeomEdge::SetMark()        { 
+		type |=16;/*=> 4th digiy to 1*/
+	}/*}}}*/
+	/*FUNCTION GeomEdge::SetUnMark{{{*/
+	void   GeomEdge::SetUnMark()      { 
+		type &= 1007 /* 1023-16 = 000111110111 => 4th digit to 0*/;
+	}/*}}}*/
+	/*FUNCTION GeomEdge::SetRequired{{{*/
+	void   GeomEdge::SetRequired()    { 
+		type |= 64;/*=>6th digit to 1*/ 
+	}/*}}}*/
+	  /*FUNCTION GeomEdge::Tg{{{*/
+	int    GeomEdge::Tg(int i) const  {
+		return i==0 ? TgA() : TgB();
+	}/*}}}*/
+	/*FUNCTION GeomEdge::TgA{{{*/
+	int    GeomEdge::TgA()     const  {
+		return type &4;  
+	}/*}}}*/
+	/*FUNCTION GeomEdge::TgB{{{*/
+	int    GeomEdge::TgB()     const  {
+		return type &8;  
+	}/*}}}*/
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomEdge.h	(revision 12821)
@@ -0,0 +1,47 @@
+#ifndef _GEOMETRICALEDGE_H_
+#define _GEOMETRICALEDGE_H_
+
+#include "./include.h"
+
+namespace bamg {
+
+	//classes
+	class GeomVertex;
+	class Geometry;
+
+	class GeomEdge {
+
+		public:
+			GeomVertex *v[2];
+			long               ReferenceNumber;
+			long               CurveNumber;
+			R2                 tg[2];              // the 2 tangentes (tg[0] =0 => no continuity)
+			GeomEdge   *Adj[2];
+			int                AdjVertexIndex[2]; // for a given vertex, this gives the index of the vertex in the adjacent edge (0 or 1)
+			int                type;
+
+			//Operators
+			GeomVertex       & operator[](int i){return *v[i];};
+			const GeomVertex & operator[](int i) const { return *v[i];};
+			GeomVertex       * operator()(int i){return v[i];};  
+
+			//Methods
+			R2     F(double theta) const ; // parametrization of the curve edge
+			double R1tg(double theta,R2 &t) const ; // 1/radius of curvature + tangente
+			int    Tg(int i) const;
+			int    Cracked() const;
+			int    TgA()     const;
+			int    TgB()     const;
+			int    Mark()    const;
+			int    Required();
+			void   SetCracked();
+			void   SetTgA();
+			void   SetTgB();
+			void   SetMark();
+			void   SetUnMark();
+			void   SetRequired();
+			void   Set(const GeomEdge & rec,const Geometry & Th ,Geometry & ThNew);
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.cpp	(revision 12821)
@@ -0,0 +1,20 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "GeomSubDomain.h"
+#include "Geometry.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+
+	/*Methods*/
+	/*FUNCTION GeomSubDomain::Set {{{*/
+	void GeomSubDomain::Set(const GeomSubDomain & rec,const Geometry & Gh ,const Geometry & GhNew){
+		*this = rec;
+		edge = Gh.GetId(edge) + GhNew.edges;
+	}/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomSubDomain.h	(revision 12821)
@@ -0,0 +1,23 @@
+#ifndef _GEOMETRICALSUBDOMAIN_H_
+#define _GEOMETRICALSUBDOMAIN_H_
+
+#include "./include.h"
+
+namespace bamg {
+
+	//classes
+	class GeomEdge;
+	class Geometry;
+
+	class GeomSubDomain {
+		public:
+			GeomEdge *edge;
+			int              direction;   // -1 or 1
+			long             ReferenceNumber;
+
+			//Methods
+			void Set(const GeomSubDomain &,const Geometry & ,const Geometry &);
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.cpp	(revision 12821)
@@ -0,0 +1,38 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "GeomVertex.h"
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	//See header file
+
+	/*Methods*/
+	/*FUNCTION GeomVertex::Corner {{{*/
+	int  GeomVertex::Corner() const {
+		return type & 4;
+	}
+	/*}}}*/
+	/*FUNCTION GeomVertex::Required {{{*/
+	int  GeomVertex::Required()const {
+		// a corner is required
+		return type & 6;
+	}
+	/*}}}*/
+	/*FUNCTION GeomVertex::SetCorner {{{*/
+	void GeomVertex::SetCorner(){
+		type |= 4;
+	}
+	/*}}}*/
+	/*FUNCTION GeomVertex::SetRequired {{{*/
+	void GeomVertex::SetRequired(){
+		type |= 2;
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/GeomVertex.h	(revision 12821)
@@ -0,0 +1,30 @@
+#ifndef _GEOMETRICALVERTEX_H_
+#define _GEOMETRICALVERTEX_H_
+
+#include "./include.h"
+#include "BamgVertex.h"
+
+namespace bamg {
+
+	class Geometry;
+
+	class GeomVertex : public BamgVertex { 
+
+		public:
+			friend class Geometry;
+
+			int type;
+
+			//Constructors
+			GeomVertex():type(0){};
+
+			//Methods
+			int  Corner() const;
+			int  Required()const;
+			void SetCorner();
+			void SetRequired();
+
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Geometry.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Geometry.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Geometry.cpp	(revision 12821)
@@ -0,0 +1,971 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "../objects.h"
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+
+namespace bamg {
+
+	static const  Direction NoDirOfSearch=Direction();
+
+	/*Constructors/Destructors*/
+	/*FUNCTION Geometry::Geometry(){{{*/
+	Geometry::Geometry(){
+		Init();
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::Geometry(BamgGeom* bamggeom, BamgOpts* bamgopts){{{*/
+	Geometry::Geometry(BamgGeom* bamggeom, BamgOpts* bamgopts){
+		Init();
+		ReadGeometry(bamggeom,bamgopts);
+		PostRead();
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::Geometry(const Geometry & Gh) (COPY operator){{{*/
+	Geometry::Geometry(const Geometry & Gh) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/Geometry)*/
+
+		long i;
+		*this = Gh;
+		NbRef =0;
+		quadtree=0;
+		vertices = nbv ? new GeomVertex[nbv] : NULL;
+		edges = nbe ? new GeomEdge[nbe]:NULL;
+		curves= nbcurves ? new Curve[nbcurves]:NULL;
+		subdomains = nbsubdomains ? new GeomSubDomain[nbsubdomains]:NULL;
+		for (i=0;i<nbe;i++)
+		 edges[i].Set(Gh.edges[i],Gh,*this);
+		for (i=0;i<nbcurves;i++)
+		 curves[i].Set(Gh.curves[i],Gh,*this);
+		for (i=0;i<nbsubdomains;i++)
+		 subdomains[i].Set(Gh.subdomains[i],Gh,*this);
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::~Geometry(){{{*/
+	Geometry::~Geometry() {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/~Geometry)*/
+		if(NbRef>0){   _printString_("Trying to delete geometry and NbRef>0, probably due to an error"); return;}
+		if(vertices)   delete [] vertices;  vertices=0;
+		if(edges)      delete [] edges;     edges=0;
+		if(quadtree)   delete    quadtree;  quadtree=0;
+		if(curves)     delete [] curves;    curves=0;nbcurves=0;
+		if(subdomains) delete [] subdomains;subdomains=0;
+		Init();
+	}
+	/*}}}*/
+
+	/*IO*/
+	/*FUNCTION Geometry::ReadGeometry{{{*/
+	void Geometry::ReadGeometry(BamgGeom* bamggeom,BamgOpts* bamgopts){
+
+		int verbose;
+		nbv=0;
+		nbe=0;
+		nbcurves=0;
+
+		double Hmin = HUGE_VAL;// the infinie value 
+		int i,j,k,n,i0,i1,i2,i3;
+
+		/*initialize some variables*/
+		verbose= bamgopts->verbose;
+		nbv    = bamggeom->VerticesSize[0];
+		nbe    = bamggeom->EdgesSize[0];
+
+		//some checks
+		if (bamggeom->Vertices==NULL) _error2_("the domain provided does not contain any vertex");
+		if (bamggeom->Edges==NULL) _error2_("the domain provided does not contain any edge");
+
+		//Vertices
+		if (bamggeom->Vertices){
+			if(verbose>5) _printLine_("      processing Vertices");
+			if (bamggeom->VerticesSize[1]!=3) _error2_("Vertices should have 3 columns");
+			vertices = new GeomVertex[nbv];
+			for (i=0;i<nbv;i++) {
+				vertices[i].r.x=(double)bamggeom->Vertices[i*3+0];
+				vertices[i].r.y=(double)bamggeom->Vertices[i*3+1];
+				vertices[i].ReferenceNumber=(long)bamggeom->Vertices[i*3+2];
+				vertices[i].DirOfSearch=NoDirOfSearch;
+				vertices[i].color =0;
+				vertices[i].type=0;
+			}
+			/*find domain extrema (pmin,pmax) that will define the square box used for by the quadtree*/
+			pmin =  vertices[0].r;
+			pmax =  vertices[0].r;
+			for (i=0;i<nbv;i++) {
+				pmin.x = Min(pmin.x,vertices[i].r.x);
+				pmin.y = Min(pmin.y,vertices[i].r.y);
+				pmax.x = Max(pmax.x,vertices[i].r.x);
+				pmax.y = Max(pmax.y,vertices[i].r.y);
+			}
+			/*Offset pmin and pmax to avoid round-off errors*/
+			R2 offset = (pmax-pmin)*0.05;
+			pmin -= offset;
+			pmax += offset;
+			/*coefIcoor is the coefficient used for integer coordinates:
+			 *                       (x-pmin.x)
+			 * Icoor x = (2^30 -1) ------------ 
+			 *                          D
+			 * where D is the longest side of the domain (direction x or y)
+			 * so that (x-pmin.x)/D is in ]0 1[
+			 *
+			 * coefIcoor = (2^30 -1)/D
+			 */
+			coefIcoor=(MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+			if(coefIcoor<=0) _error2_("coefIcoor should be positive");
+		}
+		else{
+			_error2_("No BamgVertex provided");
+		}
+
+		//Edges
+		if (bamggeom->Edges){
+			R2      zerovector(0,0);
+			double* verticeslength=NULL;
+
+			if(verbose>5) _printLine_("      processing Edges");
+			if (bamggeom->EdgesSize[1]!=3) _error2_("Edges should have 3 columns");
+			edges = new GeomEdge[nbe];
+
+			//initialize verticeslength (sum of the lengths of the edges holding vertex)
+			verticeslength = new double[nbv];
+			for(i=0;i<nbv;i++) verticeslength[i]=0;
+
+			/*Loop over the edges*/
+			for (i=0;i<nbe;i++){
+
+				i1=(int)bamggeom->Edges[i*3+0]-1; //-1 for C indexing
+				i2=(int)bamggeom->Edges[i*3+1]-1; //-1 for C indexing
+				edges[i].v[0]= vertices + i1;     //pointer toward vertex i1 (=&vertices[i1])
+				edges[i].v[1]= vertices + i2;     //pointer toward vertex i2
+				edges[i].ReferenceNumber=(long)bamggeom->Edges[i*3+2];
+
+				//get length of edge
+				R2     x12=vertices[i2].r-vertices[i1].r;
+				double l12=sqrt((x12,x12));
+				Hmin=Min(Hmin,l12);
+
+				//initialize other fields
+				edges[i].tg[0]=zerovector;
+				edges[i].tg[1]=zerovector;
+				edges[i].AdjVertexIndex[0] = edges[i].AdjVertexIndex[1] = -1;
+				edges[i].Adj[0] = edges[i].Adj[1] = NULL;
+				edges[i].type = 0;
+
+				//Cracked?
+				if (edges[i].ReferenceNumber!=1) edges[i].SetCracked();
+
+				//prepare metric
+				vertices[i1].color++;
+				vertices[i2].color++;
+				verticeslength[i1] += l12;
+				verticeslength[i2] += l12;
+			}
+
+			// definition the default of the given mesh size 
+			for (i=0;i<nbv;i++) {
+				if (vertices[i].color > 0) 
+				 vertices[i].m=Metric(verticeslength[i] /(double) vertices[i].color);
+				else 
+				 vertices[i].m=Metric(Hmin);
+			}
+			delete [] verticeslength;
+			
+		}
+		else{
+			_error2_("No edges provided");
+		}
+
+		//hVertices
+		if(bamgopts->hVertices && bamgopts->hVerticesSize[0]==nbv){
+			if(verbose>5) _printLine_("      processing hVertices");
+			for (i=0;i< nbv;i++){
+				if (!xIsNan<IssmDouble>(bamgopts->hVertices[i])){
+					vertices[i].m=Metric((double)bamgopts->hVertices[i]);
+				}
+			}
+		}
+
+		//MetricVertices
+		if(bamgopts->metric && bamgopts->metric[0]==nbv){
+			if(verbose>5) _printLine_("      processing MetricVertices");
+			for (i=0;i< nbv;i++) {
+				vertices[i].m = Metric((double)bamgopts->metric[i*3+0],(double)bamgopts->metric[i*3+1],(double)bamgopts->metric[i*3+2]);
+			}
+		}
+
+		//MaxCornerAngle
+		if (bamgopts->MaxCornerAngle){
+			if(verbose>5) _printLine_("      processing MaxCornerAngle");
+			MaxCornerAngle=bamgopts->MaxCornerAngle*Pi/180;
+		}
+
+		//TangentAtEdges
+		if (bamggeom->TangentAtEdges){
+			if(verbose>5) _printString_("      processing TangentAtEdges");
+			if (bamggeom->TangentAtEdgesSize[1]!=4) _error2_("TangentAtEdges should have 4 columns");
+			int n,i,j,k;
+			R2 tg;
+
+			n=bamggeom->TangentAtEdgesSize[0];
+			for (k=0;k<n;k++) {
+				i=(int)bamggeom->TangentAtEdges[k*4+0]-1; //for C indexing
+				j=(int)bamggeom->TangentAtEdges[k*4+1]-1; //for C indexing
+				tg.x=bamggeom->TangentAtEdges[k*4+2];
+				tg.y=bamggeom->TangentAtEdges[k*4+3];
+				if (i<0 || i>=nbe) _error2_("TangentAtEdges first index exceeds matrix dimension");
+				if (j!=0 && j!=1)  _error2_("TangentAtEdges second index should be 1 or 2 only");
+				edges[i].tg[j] = tg;
+			}
+		}
+
+		//Corners
+		if(bamggeom->Corners){
+			if(verbose>5) _printString_("      processing Corners");
+			if (bamggeom->CornersSize[1]!=1) _error2_("Corners should have 1 column");
+			n=bamggeom->CornersSize[0];
+			for (i=0;i<n;i++) {     
+				j=(int)bamggeom->Corners[i]-1; //for C indexing
+				if (j>nbv-1 || j<0) _error2_("Bad corner definition: should in [0 " << nbv << "]");
+				/*Required => at the same time SetRequired and SetCorner*/
+				vertices[j].SetCorner();
+				vertices[j].SetRequired();
+			}
+		}
+
+		//RequiredVertices
+		if(bamggeom->RequiredVertices){
+			if(verbose>5) _printLine_("      processing RequiredVertices");
+			if (bamggeom->RequiredVerticesSize[1]!=1) _error2_("RequiredVertices should have 1 column");
+			n=bamggeom->RequiredVerticesSize[0];
+			for (i=0;i<n;i++) {     
+				j=(int)bamggeom->RequiredVertices[i]-1; //for C indexing
+				if (j>nbv-1 || j<0) _error2_("Bad RequiredVerticess  definition: should in [0 " << nbv << "]");
+				vertices[j].SetRequired();
+			}
+		}
+
+		//RequiredEdges
+		if(bamggeom->RequiredEdges){
+			if(verbose>5) _printLine_("      processing RequiredEdges");
+			if (bamggeom->RequiredEdgesSize[1]!=1) _error2_("RequiredEdges should have 1 column");
+			n=bamggeom->RequiredEdgesSize[0];
+			for (i=0;i<n;i++) {     
+				j=(int)bamggeom->RequiredEdges[i]-1; //for C indexing
+				if (j>nbe-1 || j<0) _error2_("Bad RequiredEdges definition: should in [0 " << nbe << "]");
+				edges[j].SetRequired();  
+			}
+		}
+
+		//SubDomain
+		if(bamggeom->SubDomains){
+			if(verbose>5) _printLine_("      processing SubDomains");
+			if (bamggeom->SubDomainsSize[1]!=4) _error2_("SubDomains should have 4 columns");
+			nbsubdomains=bamggeom->SubDomainsSize[0];
+			subdomains = new GeomSubDomain[nbsubdomains];
+			for (i=0;i<nbsubdomains;i++){
+				i0=(int)bamggeom->SubDomains[i*4+0];
+				i1=(int)bamggeom->SubDomains[i*4+1];
+				i2=(int)bamggeom->SubDomains[i*4+2];
+				i3=(int)bamggeom->SubDomains[i*4+3];
+				if (i0!=2) _error2_("Bad Subdomain definition: first number should be 2 (for Edges)");
+				if (i1>nbe || i1<=0) _error2_("Bad Subdomain definition: second number should in [1 " << nbe << "] (edge number)");
+				subdomains[i].edge=edges + (i1-1);
+				subdomains[i].direction = (int) i2;
+				subdomains[i].ReferenceNumber = i3;
+			}
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::WriteGeometry{{{*/
+	void Geometry::WriteGeometry(BamgGeom* bamggeom, BamgOpts* bamgopts){
+
+		int verbose;
+		int nbreq=0;
+		int nbreqv=0;
+		int nbtan=0;
+		int nbcracked=0;
+		int i,count;
+
+		/*Get options*/
+		verbose=bamgopts->verbose;
+
+		/*Vertices*/
+		if(verbose>5) _printLine_("      writing Vertices");
+		bamggeom->VerticesSize[0]=nbv;
+		bamggeom->VerticesSize[1]=3;
+		if (nbv){
+			bamggeom->Vertices=xNew<double>(3*nbv);
+			for (i=0;i<nbv;i++){
+				bamggeom->Vertices[i*3+0]=vertices[i].r.x;
+				bamggeom->Vertices[i*3+1]=vertices[i].r.y;
+				bamggeom->Vertices[i*3+2]=vertices[i].GetReferenceNumber();
+
+				//update counters
+				if (vertices[i].Required()) nbreqv++;
+			}
+		}
+
+		/*Edges*/
+		if(verbose>5) _printLine_("      writing Edges");
+		bamggeom->EdgesSize[0]=nbe;
+		bamggeom->EdgesSize[1]=3;
+		if (nbe){
+			bamggeom->Edges=xNew<double>(3*nbe);
+			for (i=0;i<nbe;i++){
+				bamggeom->Edges[i*3+0]=GetId(edges[i][0])+1; //back to Matlab indexing
+				bamggeom->Edges[i*3+1]=GetId(edges[i][1])+1; //back to Matlab indexing
+				bamggeom->Edges[i*3+2]=(double)edges[i].ReferenceNumber;
+
+				//update counters
+				if (edges[i].Required()) nbreq++;
+				if (edges[i].TgA() && edges[i][0].Corner()) nbtan++;
+				if (edges[i].TgB() && edges[i][1].Corner()) nbtan++;
+			}
+		}
+
+		/*RequiredEdges*/
+		if(verbose>5) _printLine_("      writing " << nbreq << " RequiredEdges");
+		bamggeom->RequiredEdgesSize[0]=nbreq;
+		bamggeom->RequiredEdgesSize[1]=1;
+		if (nbreq){
+			bamggeom->RequiredEdges=xNew<double>(1*nbreq);
+			count=0;
+			for (i=0;i<nbe;i++){
+				if (edges[i].Required()){
+					bamggeom->RequiredEdges[count]=i+1; //back to Matlab indexing
+					count=count+1;
+				}
+			}
+		}
+
+		//No corners
+
+		/*RequiredVertices*/
+		if(verbose>5) _printLine_("      writing " << nbreqv << " RequiredVertices");
+		bamggeom->RequiredVerticesSize[0]=nbreqv;
+		bamggeom->RequiredVerticesSize[1]=1;
+		if (nbreqv){
+			bamggeom->RequiredVertices=xNew<double>(1*nbreqv);
+			count=0;
+			for (i=0;i<nbv;i++){
+				if (vertices[i].Required()){
+					bamggeom->RequiredVertices[count]=i+1; //back to Matlab indexing
+					count=count+1;
+				}
+			}
+		}
+
+		/*SubDomains*/
+		if(verbose>5) _printLine_("      writing SubDomains");
+		bamggeom->SubDomainsSize[0]=nbsubdomains;
+		bamggeom->SubDomainsSize[1]=4;
+		if (nbsubdomains){
+			bamggeom->SubDomains=xNew<double>(4*nbsubdomains);
+			for (i=0;i<nbsubdomains;i++){
+				bamggeom->SubDomains[4*i+0]=2;
+				bamggeom->SubDomains[4*i+1]=GetId(subdomains[i].edge)+1; //back to Matlab indexing
+				bamggeom->SubDomains[4*i+2]=subdomains[i].direction;
+				bamggeom->SubDomains[4*i+3]=subdomains[i].ReferenceNumber;
+			}
+		}
+
+		/*TangentAtEdges*/
+		if(verbose>5) _printLine_("      writing TangentAtEdges");
+		bamggeom->TangentAtEdgesSize[0]=nbtan;
+		bamggeom->TangentAtEdgesSize[1]=4;
+		if (nbtan){
+			bamggeom->TangentAtEdges=xNew<double>(4*nbtan);
+			count=0;
+			for (i=0;i<nbe;i++){
+				if (edges[i].TgA() && edges[i][0].Corner()){
+					bamggeom->TangentAtEdges[4*i+0]=i+1; //back to Matlab indexing
+					bamggeom->TangentAtEdges[4*i+1]=1;
+					bamggeom->TangentAtEdges[4*i+2]=edges[i].tg[0].x;
+					bamggeom->TangentAtEdges[4*i+3]=edges[i].tg[0].y;
+				}
+				if (edges[i].TgB() && edges[i][1].Corner()){
+					bamggeom->TangentAtEdges[4*i+0]=i+1; //back to Matlab indexing
+					bamggeom->TangentAtEdges[4*i+1]=2;
+					bamggeom->TangentAtEdges[4*i+2]=edges[i].tg[1].x;
+					bamggeom->TangentAtEdges[4*i+3]=edges[i].tg[1].y;
+				}
+				count=count+1;
+			}
+		}
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Geometry::Echo {{{*/
+	void Geometry::Echo(void){
+
+		_printLine_("Geometry:");
+		_printLine_("   nbv  (number of vertices) : " << nbv);
+		_printLine_("   nbe  (number of edges)    : " << nbe);
+		_printLine_("   nbsubdomains: " << nbsubdomains);
+		_printLine_("   nbcurves: " << nbcurves);
+		_printLine_("   vertices: " << vertices);
+		_printLine_("   edges: " << edges);
+		_printLine_("   quadtree: " << quadtree);
+		_printLine_("   subdomains: " << subdomains);
+		_printLine_("   curves: " << curves);
+		_printLine_("   pmin (x,y): (" << pmin.x << " " << pmin.y << ")");
+		_printLine_("   pmax (x,y): (" << pmax.x << " " << pmax.y << ")");
+		_printLine_("   coefIcoor: " << coefIcoor);
+		_printLine_("   MaxCornerAngle: " << MaxCornerAngle);
+
+		return;
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::Init{{{*/
+	void Geometry::Init(void){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/EmptyGeometry)*/
+
+		NbRef=0;
+		nbv=0;
+		nbe=0;
+		quadtree=NULL;
+		curves=NULL;
+		edges=NULL;
+		vertices=NULL;
+		nbsubdomains=0;
+		nbcurves=0;
+		subdomains=NULL;
+		MaxCornerAngle = 10*Pi/180; //default is 10 degres
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::MinimalHmin{{{*/
+	double Geometry::MinimalHmin() {
+		/* coeffIcoor = (2^30-1)/D
+		 * We cannot go beyond hmin = D/2^30 because of the quadtree
+		 * hmin is therefore approximately 2/coeffIcoor */
+		return 2.0/coefIcoor;
+	}/*}}}*/
+	/*FUNCTION Geometry::MaximalHmax{{{*/
+	double Geometry::MaximalHmax() {
+		return Max(pmax.x-pmin.x,pmax.y-pmin.y);
+	}/*}}}*/
+	/*FUNCTION Geometry::GetId(const GeomVertex &t){{{*/
+	long Geometry::GetId(const GeomVertex & t) const  {
+		return &t - vertices;
+	}/*}}}*/
+	/*FUNCTION Geometry::GetId(const GeomVertex * t){{{*/
+	long Geometry::GetId(const GeomVertex * t) const  {
+		return t - vertices;
+	}/*}}}*/
+	/*FUNCTION Geometry::GetId(const GeomEdge & t){{{*/
+	long Geometry::GetId(const GeomEdge & t) const  {
+		return &t - edges;
+	}/*}}}*/
+	/*FUNCTION Geometry::GetId(const GeomEdge * t){{{*/
+	long Geometry::GetId(const GeomEdge * t) const  {
+		return t - edges;
+	}/*}}}*/
+	/*FUNCTION Geometry::GetId(const Curve * c){{{*/
+	long Geometry::GetId(const Curve * c) const  {
+		return c - curves;
+	}/*}}}*/
+	/*FUNCTION Geometry::Containing{{{*/
+	GeomEdge* Geometry::Containing(const R2 P,  GeomEdge * start) const {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/Contening)*/
+
+		GeomEdge* on =start,* pon=0;
+		// walk with the cos on geometry
+		int counter=0;
+		while(pon != on){  
+			counter++;
+			_assert_(counter<100);
+			pon = on;
+			R2 A= (*on)[0];
+			R2 B= (*on)[1];
+			R2 AB = B-A;
+			R2 AP = P-A;
+			R2 BP = P-B;
+			if ( (AB,AP) < 0) 
+			 on = on->Adj[0];
+			else if ( (AB,BP)  > 0) 
+			 on = on->Adj[1];
+			else
+			 return on;
+		}
+		return on;
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::PostRead{{{*/
+	void Geometry::PostRead(){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/AfterRead)*/
+
+		long               i,j,k;
+		int                jj;
+		long              *head_v   = new long[nbv];
+		long              *next_p   = new long[2*nbe];
+		float             *eangle   = new float[nbe];
+		double             eps      = 1e-20;
+		BamgQuadtree           quadtree; // build quadtree to find duplicates
+		BamgVertex        *v0       = vertices;
+		GeomVertex *v0g      = (GeomVertex*) (void*)v0;
+
+		k=0;
+
+		//build quadtree for this geometry
+		for (i=0;i<nbv;i++){
+
+			/*build integer coordinates (non unique)
+			  these coordinates are used by the quadtree to group
+			  the vertices by groups of 5:
+			  All the coordinates are transformed to ]0,1[^2
+			  then, the integer coordinates are computed using 
+			  the transformation ]0,1[^2 -> [0 2^30-1[^2 for a quadtree of depth 30*/
+			vertices[i].i=R2ToI2(vertices[i].r); 
+
+			/*find nearest vertex already present in the quadtree (NULL if empty)*/
+			BamgVertex* v=quadtree.NearestVertex(vertices[i].i.x,vertices[i].i.y); 
+
+			/*if there is a vertex found that is to close to vertices[i] -> error*/
+			if( v && Norme1(v->r - vertices[i].r) < eps ){
+				_printLine_("reference numbers: " << v->ReferenceNumber << " " << vertices[i].ReferenceNumber);
+				_printLine_("Id: " << i+1);
+				delete [] next_p;
+				delete [] head_v;
+				delete [] eangle;
+				_error2_("two points of the geometry are very closed to each other (see reference numbers above)");
+			}
+
+			/*Add vertices[i] to the quadtree*/
+			quadtree.Add(vertices[i]);
+		}
+
+		/* Here we use a powerful chaining algorithm
+		 *
+		 * 1. What is a chaining algorithm?
+		 *
+		 * If F is a function that goes from i in [0 n] to j in [0 m]
+		 * and we want to compute the reciprocal function F-1 of F
+		 * (what are the antecedents of a given j in Im(F) )
+		 * We use 2 lists:
+		 *    head_F[j] that holds the head of lists
+		 *    next_F[i] that holds the list of elements that have the same image
+		 *
+		 * Example:
+		 *    i1, i2, ..., ip in [0,n] are all antecedents of a given j in [0 m]
+		 *    head_F[j] = ip
+		 *    next_F[ip]= ip-1
+		 *    ....
+		 *    next_F[i2]= i1
+		 *    next_F[i1]= -1  //end of the list
+		 *
+		 * Algorithm:
+		 *    for(j=0;j<m;j++)  head_F[j] = -1 //initialization
+		 *    for(i=0;i<n;i++){
+		 *       j=F[i];
+		 *       next_F[i]= head_F[j];
+		 *       head_F[j]=i;
+		 *    }
+		 * 
+		 *    Then, we can go through all the elements that have for image j:
+		 *    for(i=head_F[j]; i!=-1; i=next_F[i])
+		 *    initialization of i by i=head_F[j]
+		 *    stop the loop when i=-1 (end of the chain)
+		 *    iterate using i=next_F[i] (next element that have for image j)
+		 * 
+		 * 2. How to use this algorithm here?
+		 * 
+		 * Here F is a function that associates two vertices v0 and v1 for a given edge E
+		 * We want to build the reciprocal function: what are the edges that contains
+		 * a vertex v?
+		 * To do so, we use the same chaining algorithm but there is a difficulty
+		 * coming from the fact that for F we have a couple of vertices and not one 
+		 * vertex.
+		 * To overcome this difficulty, we use a global indexing exactly like in 
+		 * C/C++ so that
+		 * a member of a 2-column-table can be described by one index p=i*2+j
+		 * i=(int)p/2 line number of p
+		 * j=p%2      column number of p
+		 *
+		 * Algorithm:
+		 *    for(i=0;i<nbv;i++)  head_v[i] = -1 //initialization
+		 *    for(i=0;i<nbe;i++){
+		 *       for(j=0;j<2;j++){
+		 *          p=2*i+j;
+		 *          v=edges(i,j);
+		 *          next_p[p]= head_v[v];
+		 *          head_v[v]=p;
+		 *       }
+		 *    }
+		 */
+
+		//initialize head_v as -1
+		for (i=0;i<nbv;i++) head_v[i]=-1;
+		k=0;
+		for (i=0;i<nbe;i++) {
+			//compute vector of edge i that goes from vertex 0 to vertex 1
+			R2 v10=edges[i].v[1]->r - edges[i].v[0]->r;
+			double lv10=Norme2(v10);
+			//check that its length is not 0
+			if(lv10==0){
+				delete [] next_p;
+				delete [] head_v;
+				delete [] eangle;
+				_error2_("Length of edge " << i << " is 0");
+			}
+			//compute angle in [-Pi Pi]
+			eangle[i] = atan2(v10.y,v10.x);
+			//build chains head_v and next_p
+			for (j=0;j<2;j++){
+				long v=GetId(edges[i].v[j]);
+				next_p[k]=head_v[v];
+				head_v[v]=k++; //post increment: head_v[v]=k; and then k=k+1;
+			}
+		}
+
+		//sort head_v by order of increasing edges angle
+		for (i=0;i<nbv;i++) {
+			int exch=1,ord=0;      
+
+			//exchange vertices position in head_v and next_p till tey are sorted
+			while (exch){
+				long *p=head_v+i;               
+				long *po=p;                     
+				long  n=*p;                     
+				register float angleold=-1000 ; // angle = - infinity
+				ord=0; exch=0;
+
+				// loop over the edges that contain the vertex i (till -1)
+				while (n >=0){
+					ord++;
+					long  i1=n/2;       // i1 = floor (n/2)      -> Edge number
+					long  j1=n%2;       // j1 = 1 if n is odd    -> Vertex index for this edge (0 or 1)
+					long* pn=next_p+n;
+
+					//Next vertex index
+					n=*pn;                       
+
+					//compute angle between horizontal axis and v0->v1
+					float angle = j1 ? OppositeAngle(eangle[i1]):  eangle[i1]; 
+
+					//exchange if the current edge angle is smaller than the previous one
+					if (angleold > angle){
+						exch=1;
+						*pn=*po;  // next_p[n] = n + 1
+						*po=*p;   // 
+						*p=n;     // next_p[n+1] = n
+						po=pn;    // po now point toward pn (invert next and current)
+					}
+
+					//else, continue going to the next edge position
+					else{                        //  to have : po -> p -> pn
+						angleold=angle; // update maximum angle
+						po=p;           // po now point toward p  (current position)
+						p=pn;           // p  now point toward pn (next position)
+					}
+				}
+			}
+
+			// angular test on current vertex to guess whether it is a corner (ord = number of edges holding i)
+			if(ord==2) { 
+				long  n1 = head_v[i];
+				long  n2 = next_p[n1];
+				long  i1 = n1/2, i2 = n2/2; // edge number
+				long  j1 = n1%2, j2 = n2%2; // vertex in the edge 
+				float angle1=  j1 ? OppositeAngle(eangle[i1]) : eangle[i1];
+				float angle2= !j2 ? OppositeAngle(eangle[i2]) : eangle[i2];
+				float da12 = Abs(angle2-angle1);
+				if (( da12 >= MaxCornerAngle ) && (da12 <= 2*Pi -MaxCornerAngle)) {
+					vertices[i].SetCorner() ; 
+				}
+				// if the edge type/referencenumber a changing then is SetRequired();
+				if (edges[i1].type != edges[i2].type || edges[i1].Required()){
+					vertices[i].SetRequired();
+				}
+				if (edges[i1].ReferenceNumber != edges[i2].ReferenceNumber) {
+					vertices[i].SetRequired();
+				}
+			}
+			if(ord != 2) {
+				vertices[i].SetCorner();
+			}
+
+			/*close the list around the vertex to have a circular loop*/
+			long no=-1, ne = head_v[i];
+			while (ne >=0) ne = next_p[no=ne];        
+			if(no>=0) next_p[no] = head_v[i];
+		}
+
+		/*Check that the list makes sense (we have all the time the same vertex)
+		 * and build adjacent edges*/
+		k =0;
+		for (i=0;i<nbe;i++){
+			for (j=0;j<2;j++){
+
+				long n1 = next_p[k++]; 
+				long i1 = n1/2 ,j1=n1%2;
+
+				if( edges[i1].v[j1] != edges[i].v[j]) _error2_("Problem while processing edges: check the edge list");
+
+				edges[i1].Adj[j1] = edges + i;
+				edges[i1].AdjVertexIndex[j1] = j;
+			}
+		}
+
+		/* generation of  all the tangents*/
+		for (i=0;i<nbe;i++) {
+			R2    AB =edges[i].v[1]->r -edges[i].v[0]->r;// AB = vertex0 -> vertex1
+			double lAB=Norme2(AB);                       // Get length of AB
+			double ltg2[2]={0.0};                        // initialize tangent
+
+			//loop over the 2 vertices of the edge
+			for (j=0;j<2;j++) {
+				R2     tg =edges[i].tg[j];
+				double ltg=Norme2(tg);
+
+				//by default, tangent=[0 0]
+				if(ltg==0){
+					//if the current vertex of the edge is not a corner
+					if(!edges[i].v[j]->Corner()){
+						/*The tangent is set as the vector between the
+						 * previous and next vertices connected to current vertex
+						 * normed by the edge length*/
+						tg = edges[i].v[1-j]->r - edges[i].Adj[j]->v[1-edges[i].AdjVertexIndex[j]]->r;
+						ltg= Norme2(tg);
+						tg = tg *(lAB/ltg);
+						ltg= lAB;
+					}
+					//else:  a Corner no tangent => nothing to do    
+				}
+				else{
+					//tangent has already been computed
+					tg = tg*(lAB/ltg),ltg=lAB;
+				}
+
+				ltg2[j] = ltg;
+
+				if ((tg,AB)<0) tg = -tg;
+
+				edges[i].tg[j]=tg;
+			}
+			if (ltg2[0]!=0) edges[i].SetTgA();
+			if (ltg2[1]!=0) edges[i].SetTgB();
+		} 
+
+		/* generation of  all curves (from corner to corner)*/
+		/*We proceed in 2 steps: first allocate, second build*/
+		for (int step=0;step<2;step++){
+
+			//unmark all edges
+			for (i=0;i<nbe;i++) edges[i].SetUnMark();
+			long  nb_marked_edges=0;
+
+			//initialize number of curves
+			nbcurves = 0;
+
+			for (int level=0;level<2 && nb_marked_edges!=nbe;level++){
+				for (i=0;i<nbe;i++){
+
+					GeomEdge & ei=edges[i];   
+					for(j=0;j<2;j++){
+						/*If current edge ei is unmarked and (level=1 or vertex i is required (corner)):
+						 * we do have the first edge of a new curve*/
+						if (!ei.Mark() && (level || ei[j].Required())) { 
+							int k0=j,k1;
+							GeomEdge   *e=&ei;
+							GeomVertex *a=(*e)(k0); // begin 
+							if(curves){
+								curves[nbcurves].FirstEdge=e;
+								curves[nbcurves].FirstVertexIndex=k0;
+							}
+							int nee=0;
+							for(;;){ 
+								nee++;
+								k1 = 1-k0; // next vertex of the edge 
+								e->SetMark();
+								nb_marked_edges++;
+								e->CurveNumber=nbcurves;
+								GeomVertex *b=(*e)(k1);
+
+								//break if we have reached the other end of the curve
+								if (a==b || b->Required()){
+									if(curves){
+										curves[nbcurves].LastEdge=e;
+										curves[nbcurves].LastVertexIndex=k1;
+									}
+									break;
+								}
+								//else: go to next edge (adjacent)
+								else{
+									k0 = e->AdjVertexIndex[k1];//  vertex in next edge
+									e  = e->Adj[k1]; // next edge
+								}
+							}
+							nbcurves++;
+							if(level) a->SetRequired();
+						}
+					}
+				} 
+			}
+			_assert_(nb_marked_edges && nbe);
+			//allocate if first step
+			if(step==0) curves=new Curve[nbcurves];
+		} 
+
+		/*clean up*/
+		delete [] next_p;
+		delete [] head_v;
+		delete [] eangle;
+
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::ProjectOnCurve {{{*/
+	GeomEdge* Geometry::ProjectOnCurve(const Edge &e,double s,BamgVertex &V,VertexOnGeom &GV) const {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/ProjectOnCurve)*/
+		/*Add a vertex on an existing geometrical edge according to the metrics of the two vertices constituting the edge*/
+
+		double save_s=s;
+		int NbTry=0;
+
+retry:
+
+		s=save_s;
+		GeomEdge* on=e.GeomEdgeHook;
+		if (!on){
+			_error2_("ProjectOnCurve error message: edge provided should be on geometry");
+		}
+		if (!e[0].GeomEdgeHook ||  !e[1].GeomEdgeHook){
+			_error2_("ProjectOnCurve error message: at least one of the vertex of the edge provided is not on geometry");
+		}
+
+		//Get the two vertices of the edge
+		const BamgVertex &v0=e[0];
+		const BamgVertex &v1=e[1];
+
+		//Get position of V0, V1 and vector v0->v1
+		R2 V0=v0,V1=v1,V01=V1-V0;
+
+		//Get geometrical vertices corresponding to v0 and v1
+		VertexOnGeom  vg0=*v0.GeomEdgeHook,  vg1=*v1.GeomEdgeHook;
+
+		//build two pointers towrad current geometrical edge
+		GeomEdge *eg0=on, *eg1=on;
+
+		//Get edge direction and swap v0 and v1 if necessary
+		R2 Ag=(R2)(*on)[0],Bg=(R2)(*on)[1],AB=Bg-Ag; 
+		int OppositeSens = (V01,AB)<0;
+		int direction0=0,direction1=1;
+		if (OppositeSens) s=1-s,Exchange(vg0,vg1),Exchange(V0,V1);
+
+		//Compute metric of new vertex as a linear interpolation of the two others
+		V.m=Metric(1.0-s,v0,s,v1);
+
+		const int mxe=100;
+		GeomEdge* ge[mxe+1];
+		int     directionge[mxe+1];
+		double  lge[mxe+1];
+		int bge=mxe/2,tge=bge;
+		ge[bge] = e.GeomEdgeHook;
+		directionge[bge]=1;
+
+		while (eg0!=(GeomEdge*)vg0 && (*eg0)(direction0)!=(GeomVertex*)vg0){ 
+			if (bge<=0) {
+				if(NbTry) {
+					_printLine_("Fatal Error: on the class Mesh before call Geometry::ProjectOnCurve");
+					_printLine_("That bug might come from:");
+					_printLine_(" 1)  a mesh edge  containing more than " << mxe/2 << " geometrical edges");
+					_printLine_(" 2)  code bug : be sure that we call   Mesh::SetVertexFieldOn() before");
+					_printLine_("To solve the problem do a coarsening of the geometrical mesh or change the constant value of mxe (dangerous)");
+					_error2_("see above");
+				}
+				NbTry++;
+				goto retry;
+			}
+			GeomEdge* tmpge = eg0;
+			ge[--bge] =eg0 = eg0->Adj[direction0];
+			_assert_(bge>=0 && bge<=mxe);
+			direction0 = 1-( directionge[bge] = tmpge->AdjVertexIndex[direction0]);
+		}
+		while (eg1 != (GeomEdge*) vg1  &&  (*eg1)(direction1) != (GeomVertex*) vg1) { 
+			if(tge>=mxe ) { 
+				_printLine_("WARNING: on the class Mesh before call Geometry::ProjectOnCurve is having issues (isn't it Eric?)");
+				NbTry++;
+				if (NbTry<2) goto retry;
+				_printLine_("Fatal Error: on the class Mesh before call Geometry::ProjectOnCurve");
+				_printLine_("That bug might come from:");
+				_printLine_(" 1)  a mesh edge  contening more than " << mxe/2 << " geometrical edges");
+				_printLine_(" 2)  code bug : be sure that we call   Mesh::SetVertexFieldOn() before");
+				_printLine_("To solve the problem do a coarsening of the geometrical mesh or change the constant value of mxe (dangerous)");
+				_error2_("see above");
+			}
+			GeomEdge* tmpge = eg1;
+			ge[++tge] =eg1 = eg1->Adj[direction1];
+			directionge[tge]= direction1 = 1-tmpge->AdjVertexIndex[direction1];
+			_assert_(tge>=0 && tge<=mxe);
+		}
+
+
+		if ((*eg0)(direction0)==(GeomVertex*)vg0)
+		 vg0=VertexOnGeom(*(BamgVertex*) vg0,*eg0,direction0); //vg0 = absisce
+
+		if ((*eg1)(direction1)==(GeomVertex*)vg1)
+		 vg1=VertexOnGeom(*(BamgVertex*) vg1,*eg1,direction1);
+
+		double sg;
+		if (eg0 == eg1) { 
+			register double s0=vg0,s1=vg1;
+			sg =  s0*(1.0-s) +  s*s1;
+			on=eg0;
+		}
+		else {
+			R2 AA=V0,BB;
+			double s0,s1;
+			int i=bge;
+			double ll=0;
+			for(i=bge;i<tge;i++){
+				_assert_(i>=0 && i<=mxe);
+				BB =  (*ge[i])[directionge[i]];
+				lge[i]=ll += Norme2(AA-BB);
+				AA=BB ;}
+				lge[tge]=ll+=Norme2(AA-V1); 
+				// search the geometrical edge
+				_assert_(s<=1.0);
+				double ls= s*ll;
+				on =0;
+				s0 = vg0;
+				s1= directionge[bge];
+				double l0=0,l1;
+				i=bge;
+				while (  (l1=lge[i]) < ls ) {
+					_assert_(i>=0 && i<=mxe);
+					i++,s0=1-(s1=directionge[i]),l0=l1;
+				}
+				on=ge[i];
+				if (i==tge) 
+				 s1=vg1;
+
+				s  =(ls-l0)/(l1-l0);
+				sg =s0*(1.0-s)+s*s1;    
+		} 
+		_assert_(on);
+		V.r= on->F(sg);
+		GV=VertexOnGeom(V,*on,sg);
+		return on;
+	}
+	/*}}}*/
+	/*FUNCTION Geometry::R2ToI2{{{*/
+	I2 Geometry::R2ToI2(const R2 & P) const {
+		/*coefIcoor is the coefficient used for integer coordinates:
+		 *                       (x-pmin.x)
+		 * Icoor x = (2^30 -1) ------------ 
+		 *                          D
+		 * where D is the longest side of the domain (direction x or y)
+		 * so that (x-pmin.x)/D is in ]0 1[
+		 *
+		 * coefIcoor = (2^30 -1)/D
+		 */
+		return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x)) ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );
+	}/*}}}*/
+	/*FUNCTION Geometry::UnMarkEdges{{{*/
+	void Geometry::UnMarkEdges() {
+		for (int i=0;i<nbe;i++) edges[i].SetUnMark();
+	}/*}}}*/
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/Geometry.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Geometry.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Geometry.h	(revision 12821)
@@ -0,0 +1,68 @@
+#ifndef _GEOMETRY_H_
+#define _GEOMETRY_H_
+
+#include "./include.h"
+#include "./BamgGeom.h"
+#include "./BamgOpts.h"
+#include "./GeomVertex.h"
+#include "./GeomEdge.h"
+#include "./Curve.h"
+
+namespace bamg {
+
+	class Triangle;
+	class BamgQuadtree;
+	class GeomSubDomain;
+	class Edge;
+
+	class Geometry { 
+
+		public:
+
+			long           NbRef;                 // counter of ref on the this class if 0 we can delete
+			long           nbv;                   // number of vertices
+			long           nbe;                   // number of edges
+			long           nbsubdomains;
+			long           nbcurves;
+			GeomVertex    *vertices;
+			GeomEdge      *edges;
+			BamgQuadtree  *quadtree;
+			GeomSubDomain *subdomains;
+			Curve         *curves;
+			R2             pmin,pmax;             // domain extrema coordinates
+			double         coefIcoor;             // coef to integer Icoor1;
+			double         MaxCornerAngle;
+
+			//Constructor/Destructors
+			~Geometry(); 
+			Geometry();
+			Geometry(const Geometry & Gh);
+			Geometry(BamgGeom* bamggeom, BamgOpts* bamgopts);
+
+			//Operators
+			const GeomVertex &operator[](long i) const { return vertices[i]; };
+			GeomVertex       &operator[](long i) { return vertices[i];       };
+			const GeomEdge   &operator()(long i) const { return edges[i];    };
+			GeomEdge         &operator()(long  i) { return edges[i];         };
+
+			//Methods
+			void             Echo();
+			I2               R2ToI2(const R2 &P) const;
+			double           MinimalHmin();
+			double           MaximalHmax();
+			void             ReadGeometry(BamgGeom *bamggeom, BamgOpts*bamgopts);
+			void             Init(void);
+			void             PostRead();
+			long             GetId(const GeomVertex &t) const;
+			long             GetId(const GeomVertex *t) const;
+			long             GetId(const GeomEdge &t) const;
+			long             GetId(const GeomEdge *t) const;
+			long             GetId(const Curve *c) const;
+			void             UnMarkEdges();
+			GeomEdge *ProjectOnCurve(const Edge &,double,BamgVertex &,VertexOnGeom &) const;
+			GeomEdge *Containing(const R2 P, GeomEdge *start) const;
+			void             WriteGeometry(BamgGeom *bamggeom, BamgOpts*bamgopts);
+	};
+	
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.cpp	(revision 12821)
@@ -0,0 +1,425 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "../objects.h"
+
+namespace bamg {
+
+	/*Constructors Destructors*/
+	/*FUNCTION ListofIntersectionTriangles::ListofIntersectionTriangles{{{*/
+	ListofIntersectionTriangles::ListofIntersectionTriangles(int n,int m)
+	  : MaxSize(n), Size(0), len(-1),state(-1),lIntTria(new IntersectionTriangles[n]) ,
+	  NbSeg(0), MaxNbSeg(m), lSegsI(new SegInterpolation[m]){
+	  }
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::~ListofIntersectionTriangles{{{*/
+	ListofIntersectionTriangles::~ListofIntersectionTriangles(){
+		if (lIntTria) delete [] lIntTria,lIntTria=0;
+		if (lSegsI) delete [] lSegsI,lSegsI=0;
+	} 
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION ListofIntersectionTriangles::Init{{{*/
+	void ListofIntersectionTriangles::Init(void){
+		state=0;
+		len=0;
+		Size=0;
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::Length{{{*/
+	double  ListofIntersectionTriangles::Length(){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Length)*/
+
+		// computation of the length
+
+		// check Size
+		if (Size<=0){
+			_error2_("Size<=0");
+		}
+
+		Metric Mx,My;
+		int ii,jj;
+		R2 x,y,xy;
+
+		SegInterpolation* SegI=lSegsI;
+		SegI=lSegsI;
+		lSegsI[NbSeg].last=Size;
+		int EndSeg=Size;
+
+		y = lIntTria[0].x;
+		double sxy, s = 0;
+		lIntTria[0].s =0;
+		SegI->lBegin=s;
+
+		for (jj=0,ii=1;ii<Size;jj=ii++) {  
+			// seg jj,ii
+			x  = y;
+			y  = lIntTria[ii].x;
+			xy = y-x;
+			Mx = lIntTria[ii].m;
+			My = lIntTria[jj].m;
+			sxy= LengthInterpole(Mx,My,xy);
+			s += sxy;
+			lIntTria[ii].s = s;
+			if (ii == EndSeg){
+				SegI->lEnd=s;
+				SegI++;
+				EndSeg=SegI->last;
+				SegI->lBegin=s;
+			}
+		}
+		len = s;
+		SegI->lEnd=s;
+
+		return s;
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::NewItem(Triangle * tt,double d0,double d1,double d2) {{{*/
+	int  ListofIntersectionTriangles::NewItem(Triangle * tt,double d0,double d1,double d2) { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NewItem)*/
+
+		register int n;
+		R2 x(0,0);
+		if ( d0) x =      (*tt)[0].r * d0;
+		if ( d1) x = x +  (*tt)[1].r * d1;
+		if ( d2) x = x +  (*tt)[2].r * d2;
+		// newer add same point 
+		if(!Size ||  Norme2_2(lIntTria[Size-1].x-x)) {
+			if (Size==MaxSize) ReShape();
+			lIntTria[Size].t=tt;
+			lIntTria[Size].bary[0]=d0;
+			lIntTria[Size].bary[1]=d1;
+			lIntTria[Size].bary[2]=d2;
+			lIntTria[Size].x = x;
+			Metric m0,m1,m2;
+			register BamgVertex * v;
+			if ((v=(*tt)(0))) m0    = v->m;
+			if ((v=(*tt)(1))) m1    = v->m;
+			if ((v=(*tt)(2))) m2    = v->m;
+			lIntTria[Size].m =  Metric(lIntTria[Size].bary,m0,m1,m2);
+			n=Size++;}
+		else n=Size-1;
+		return n;
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::NewItem(R2 A,const Metric & mm){{{*/
+	int ListofIntersectionTriangles::NewItem(R2 A,const Metric & mm) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NewItem)*/
+
+		register int n;
+		if(!Size ||  Norme2_2(lIntTria[Size-1].x-A)) {
+			if (Size==MaxSize) ReShape();
+			lIntTria[Size].t=0;
+			lIntTria[Size].x=A;
+			lIntTria[Size].m=mm;
+			n=Size++;
+		}
+		else  n=Size-1;
+		return  n; 
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::NewPoints{{{*/
+	long ListofIntersectionTriangles::NewPoints(BamgVertex* vertices,long &nbv,long maxnbv){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NewPoints)*/
+
+		//If length<1.5, do nothing
+		double s=Length();
+		if (s<1.5) return 0;
+
+		const long nbvold=nbv;
+		int ii = 1 ;
+		R2 y,x;
+		Metric My,Mx ;
+		double sx =0,sy;
+		int nbi=Max(2,(int) (s+0.5));
+		double sint=s/nbi;
+		double si  =sint;
+
+		int EndSeg=Size;
+		SegInterpolation* SegI=NULL;
+		if (NbSeg) SegI=lSegsI,EndSeg=SegI->last;
+
+		for (int k=1;k<nbi;k++){
+			while ((ii < Size) && ( lIntTria[ii].s <= si )){
+				if (ii++ == EndSeg){
+					SegI++;
+					EndSeg=SegI->last;
+				}
+			}
+
+			int ii1=ii-1;
+			x  =lIntTria[ii1].x;
+			sx =lIntTria[ii1].s;
+			Metric Mx=lIntTria[ii1].m;
+			y  =lIntTria[ii].x;
+			sy =lIntTria[ii].s;
+			Metric My=lIntTria[ii].m;
+			double lxy = sy-sx;
+			double cy = abscisseInterpole(Mx,My,y-x,(si-sx)/lxy);
+
+			R2 C;
+			double cx = 1-cy;
+			C = SegI ? SegI->F(si): x * cx + y *cy;
+			//C.Echo();
+			//x.Echo();
+			//y.Echo();
+			//_printLine_("cx = " << cx << ", cy=" << cy);
+
+			si += sint;
+			if ( nbv<maxnbv) {
+				vertices[nbv].r = C;
+				vertices[nbv++].m = Metric(cx,lIntTria[ii-1].m,cy,lIntTria[ii].m);
+			}
+			else return nbv-nbvold;
+		  }
+		return nbv-nbvold;
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::NewSubSeg{{{*/
+	void  ListofIntersectionTriangles::NewSubSeg(GeomEdge *e,double s0,double s1){ 
+		long int verbosity=0;
+		if (NbSeg>=MaxNbSeg) {
+			int mneo= MaxNbSeg;
+			MaxNbSeg *= 2;
+			if (verbosity>3){
+				_printLine_("   reshape lSegsI from " << mneo << " to " << MaxNbSeg);
+			}
+			_assert_(lSegsI && NbSeg<MaxNbSeg);
+			SegInterpolation * lEn =  new SegInterpolation[MaxNbSeg];
+			for (int i=0;i< NbSeg;i++) lEn[i] = lSegsI[MaxNbSeg]; // copy old to new            
+			delete []  lSegsI; // remove old
+			lSegsI = lEn;        
+		}
+		if (NbSeg) lSegsI[NbSeg-1].last=Size;
+		lSegsI[NbSeg].e=e;
+		lSegsI[NbSeg].sBegin=s0;
+		lSegsI[NbSeg].sEnd=s1;     
+		NbSeg++;           
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::ReShape{{{*/
+	void ListofIntersectionTriangles::ReShape(){ 
+
+		register int newsize = MaxSize*2;
+		IntersectionTriangles* nw = new IntersectionTriangles[newsize];
+		_assert_(nw);
+
+		// recopy
+		for (int i=0;i<MaxSize;i++) nw[i] = lIntTria[i];       
+		long int verbosity=0;
+		if(verbosity>3) _printLine_("   ListofIntersectionTriangles  ReShape Maxsize " << MaxSize << " -> " << MaxNbSeg);
+		MaxSize = newsize; 
+		delete [] lIntTria;// remove old
+		lIntTria = nw; // copy pointer
+	}
+	/*}}}*/
+	/*FUNCTION ListofIntersectionTriangles::SplitEdge{{{*/
+	void ListofIntersectionTriangles::SplitEdge(const Mesh & Bh, const R2 &A,const R2  &B,int nbegin) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ListofIntersectionTriangles)*/
+
+		Triangle *tbegin, *t;
+
+		long int verbose=2;
+		Icoor2 deta[3], deti,detj;
+		double ba[3];
+		int nbt =0,ifirst=-1,ilast;
+		int i0,i1,i2;
+		int ocut,i,j,k=-1;
+		//  int OnAVertices =0;
+		Icoor2 dt[3];
+		I2 a = Bh.R2ToI2(A) ,b= Bh.R2ToI2(B);// compute  the Icoor a,b
+		I2 vi,vj;  
+		int iedge =-1;// not a edge
+
+		if(nbegin)  {// optimisation 
+			// we suppose  knowing the starting  triangle
+			t=tbegin=lIntTria[ilast=(Size-1)].t;
+			if (tbegin->det>=0) 
+			 ifirst = ilast;}  
+		else {// not optimisation 
+			Init();
+			t=tbegin = Bh.TriangleFindFromCoord(a,deta);
+			if( t->det>=0)
+			 ilast=NewItem(t,double(deta[0])/t->det,double(deta[1])/t->det,double(deta[2])/t->det);
+			else 
+			  {// find the nearest boundary edge  of the vertex A
+				// find a edge or such normal projection a the edge IJ is on the edge
+				//   <=> IJ.IA >=0 && IJ.AJ >=0
+				ilast=ifirst;
+				double ba,bb;
+				AdjacentTriangle edge=CloseBoundaryEdge(a,t,ba,bb);
+				BamgVertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+				NewItem(A,Metric(ba,v0,bb,v1));
+				t=edge;
+				// test if the point b is in the same side
+				if (det(v0.i,v1.i,b)>=0) {
+					AdjacentTriangle edge=CloseBoundaryEdge(a,t,ba,bb);
+					BamgVertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+					NewItem(A,Metric(ba,v0,bb,v1));
+					return;
+				}
+			  } // find the nearest boundary edge  of the vertex A
+		} // end not optimisation 
+		if (t->det<0) {  // outside departure
+			while (t->det <0) { // intersection boundary edge and a,b,
+				k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+				if (k<0){
+					_error2_("k<0");
+				}
+				ocut = OppositeEdge[k];
+				i=VerticesOfTriangularEdge[ocut][0];
+				j=VerticesOfTriangularEdge[ocut][1];
+				vi=(*t)[i];
+				vj=(*t)[j];
+				deti = bamg::det(a,b,vi);
+				detj = bamg::det(a,b,vj);
+				if (deti>0) // go to  i direction on gamma
+				 ocut = PreviousEdge[ocut];      
+				else if (detj<=0) // go to j direction on gamma
+				 ocut = NextEdge[ocut];         
+				AdjacentTriangle tadj =t->Adj(ocut);
+				t = tadj;
+				iedge= tadj; 
+				if (t == tbegin) { // 
+					double ba,bb;
+					long int verbose=2;
+					AdjacentTriangle edge=CloseBoundaryEdge(a,t,ba,bb);
+					BamgVertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+					NewItem(A,Metric(ba,v0,bb,v1));
+					return;
+				}
+			} //  end while (t->det <0)
+			// theoriticaly we have: deti =<0 and detj>0
+
+			// computation of barycentric coor
+			// test if the point b is on size on t
+			// we revert vi,vj because vi,vj is def in Adj triangle
+			if ( det(vi,vj,b)>=0) {
+				t=tbegin;
+				double ba,bb;
+				AdjacentTriangle edge=CloseBoundaryEdge(b,t,ba,bb);
+				NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+				return;
+			}
+			else
+			  {
+				k = OppositeVertex[iedge];
+				i=VerticesOfTriangularEdge[iedge][0];
+				j=VerticesOfTriangularEdge[iedge][1];
+				double dij = detj-deti;
+				if (i+j+k != 0 + 1 +2){
+					_error2_("i+j+k != 0 + 1 +2");
+				}
+				ba[j] =  detj/dij;
+				ba[i] = -deti/dij;
+				ba[k] = 0;
+				ilast=NewItem(t,ba[0],ba[1],ba[2]); }
+		}  //  outside departure
+
+
+
+		// recherche the intersection of [a,b] with Bh Mesh.
+		// we know  a triangle ta contening the vertex a
+		// we have 2 case for intersection [a,b] with a edge [A,B] of Bh
+		// 1) the intersection point is in ]A,B[
+		// 2)                        is A or B
+		// first version --- 
+		for (;;) {
+			//    t->Draw();
+			if (iedge < 0) {
+				i0 =0;i1=1;i2=2;
+				dt[0] =bamg::det(a,b,(*t)[0]);
+				dt[1] =bamg::det(a,b,(*t)[1]);
+				dt[2] =bamg::det(a,b,(*t)[2]);}
+			else {
+				i2 = iedge;
+				i0 = NextEdge[i2];
+				i1 = NextEdge[i0]; 
+				dt[VerticesOfTriangularEdge[iedge][0]] = detj;// we revert i,j because
+				dt[VerticesOfTriangularEdge[iedge][1]] = deti;// we take the Triangle by the other side
+				dt[iedge] = det(a,b,(*t)[OppositeVertex[iedge]]);}
+
+				// so we have just to see the transition from - to + of the det0..2 on edge of t
+				// because we are going from a to b
+				if       ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] > 0))
+				 ocut =i0;
+				else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+				 ocut =i1;
+				else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+				 ocut =i2;
+				else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] == 0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] >  0))
+				 ocut =i0;
+				else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] == 0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+				 ocut =i1;
+				else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] == 0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+				 ocut =i2;
+				else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] == 0))
+				 ocut =i0;
+				else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] == 0))
+				 ocut =i1;
+				else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] == 0))
+				 ocut =i2;
+				else { //  On a edge (2 zero)
+					k =0;
+					if (dt[0]) ocut=0,k++; 
+					if (dt[1]) ocut=1,k++; 
+					if (dt[2]) ocut=2,k++;
+					if(k == 1) {
+						if (dt[ocut] >0) // triangle upper AB
+						 ocut = NextEdge[ocut];
+						i= VerticesOfTriangularEdge[ocut][0];
+						j= VerticesOfTriangularEdge[ocut][1];
+					}
+					else {
+						_error2_("Bug Split Edge");
+					}
+				}
+
+				k = OppositeVertex[ocut];
+
+				Icoor2 detbij = bamg::det((*t)[i],(*t)[j],b);
+
+
+				if (detbij >= 0) { //we find the triangle contening b
+					dt[0]=bamg::det((*t)[1],(*t)[2],b);
+					dt[1]=bamg::det((*t)[2],(*t)[0],b);
+					dt[2]=bamg::det((*t)[0],(*t)[1],b);
+					double dd = t->det;
+					NewItem(t,dt[0]/dd,dt[1]/dd,dt[2]/dd);      
+					return ;}
+				else { // next triangle by  adjacent by edge ocut 
+					deti = dt[i];
+					detj = dt[j];
+					double dij = detj-deti;
+					ba[i] =  detj/dij;
+					ba[j] = -deti/dij;
+					ba[3-i-j ] = 0;
+					ilast=NewItem(t, ba[0],ba[1],ba[2]);      
+
+					AdjacentTriangle ta =t->Adj(ocut);
+					t = ta;
+					iedge= ta; 
+					if (t->det <= 0)  {
+						double ba,bb;
+						AdjacentTriangle edge=CloseBoundaryEdge(b,t,ba,bb);
+						NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+						return;
+					}
+				}// we  go outside of omega 
+		} // for(;;)
+	}
+	/*}}}*/
+
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/ListofIntersectionTriangles.h	(revision 12821)
@@ -0,0 +1,73 @@
+#ifndef _LISTOFINTERSECTIONTRIANGLES_H_
+#define _LISTOFINTERSECTIONTRIANGLES_H_
+
+#include "./include.h"
+
+namespace bamg {
+
+	class Triangle;
+
+	class ListofIntersectionTriangles {
+
+		class IntersectionTriangles {
+
+			public: 
+				Triangle *t;
+				double    bary[3];   // use if t != 0
+				R2        x;
+				Metric    m;
+				double    s;         // curvilinear coordinate
+				double    sp;        // length of the previous segment in m
+				double    sn;        // length of the next segment in m
+		};
+
+		class SegInterpolation {
+
+			public:
+				GeomEdge *e;
+				double           sBegin  ,sEnd; // abscisse of the seg on edge parameter
+				double           lBegin  ,lEnd; // length abscisse set in ListofIntersectionTriangles::Length
+				int              last;          // last index in ListofIntersectionTriangles for this Sub seg of edge
+
+				//Methods
+				R2 F(double s){ 
+					double c01=lEnd-lBegin, c0=(lEnd-s)/c01, c1=(s-lBegin)/c01;
+					if (lBegin>s || s>lEnd){
+						_error2_("lBegin>s || s>lEnd");
+					}
+					return e->F(sBegin*c0+sEnd*c1);
+				}
+		};
+
+		public:
+
+			int                    MaxSize;
+			int                    Size;
+			double                 len;
+			int                    state;
+			IntersectionTriangles *lIntTria;
+			int                    NbSeg;
+			int                    MaxNbSeg;
+			SegInterpolation      *lSegsI;
+
+			//Constructors/Destructors
+			ListofIntersectionTriangles(int n=256,int m=16);
+			~ListofIntersectionTriangles();
+
+			//Operators
+			IntersectionTriangles & operator[](int i) {return lIntTria[i];}
+			operator int&() {return Size;}
+
+			//Methods
+			void   Init();
+			int    NewItem(Triangle *tt,double d0,double d1,double d2);
+			int    NewItem(R2 ,const Metric &);
+			void   SplitEdge(const Mesh &,const R2 &,const R2 &,int nbegin=0);
+			double Length();
+			long   NewPoints(BamgVertex *,long &nbv,long maxnbv);
+			void   NewSubSeg(GeomEdge *e,double s0,double s1);
+			void   ReShape();
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Mesh.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Mesh.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Mesh.cpp	(revision 12821)
@@ -0,0 +1,6006 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "../objects.h"
+
+namespace bamg {
+
+	static const  Direction NoDirOfSearch=Direction();
+
+	/*Constructors/Destructors*/
+	/*FUNCTION Mesh::Mesh(BamgGeom* bamggeom,BamgMesh* bamgmesh, BamgOpts* bamgopts){{{*/
+	Mesh::Mesh(BamgGeom* bamggeom,BamgMesh* bamgmesh, BamgOpts* bamgopts):Gh(*(new Geometry())),BTh(*this){ 
+
+		/*Initialize fields*/
+		Init(0);
+
+		/*Read Geometry if provided*/
+		if(bamggeom->Edges) {
+			Gh.ReadGeometry(bamggeom,bamgopts);
+			Gh.PostRead();
+		}
+
+		/*Read background mesh*/
+		ReadMesh(bamgmesh,bamgopts);
+
+		/*Build Geometry if not provided*/
+		if(bamggeom->Edges==NULL) {
+			/*Recreate geometry if needed*/
+			_printLine_("WARNING: mesh present but no geometry found. Reconstructing...");
+			BuildGeometryFromMesh(bamgopts);
+			Gh.PostRead();
+		}
+
+		/*Set integer coordinates*/
+		SetIntCoor();
+
+		/*Fill holes and generate mesh properties*/
+		ReconstructExistingMesh();
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(int* index,double* x,double* y,int nods,int nels){{{*/
+	Mesh::Mesh(int* index,double* x,double* y,int nods,int nels):Gh(*(new Geometry())),BTh(*this){
+
+		Init(0);
+		ReadMesh(index,x,y,nods,nels);
+		SetIntCoor();
+		ReconstructExistingMesh();
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(double* x,double* y,int nods){{{*/
+	Mesh::Mesh(double* x,double* y,int nods):Gh(*(new Geometry())),BTh(*this){
+		Triangulate(x,y,nods);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(const Mesh & Tho,const int *flag ,const int *bb){{{*/
+	Mesh::Mesh(const Mesh & Tho,const int *flag ,const int *bb,BamgOpts* bamgopts) : Gh(*(new Geometry())), BTh(*this) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
+
+		  int i,k,itadj;
+		  int kt=0;
+		  int * kk    = new int [Tho.nbv];
+		  long * reft = new long[Tho.nbt];
+		  long nbInT =    Tho.TriangleReferenceList(reft);
+		  long * refv = new long[Tho.nbv];
+
+		  for (i=0;i<Tho.nbv;i++)
+			kk[i]=-1;
+		  for (i=0;i<Tho.nbv;i++)
+			refv[i]=0;
+		  int nbNewBedge =0;
+		  //  int nbOldBedge =0;  
+		  for (i=0;i<Tho.nbt;i++)
+			if(  reft[i] >=0 && flag[i]) 
+			  {
+				const Triangle & t = Tho.triangles[i];
+				kt++;
+				kk[Tho.GetId(t[0])]=1;
+				kk[Tho.GetId(t[1])]=1;
+				kk[Tho.GetId(t[2])]=1;
+				itadj=Tho.GetId(t.TriangleAdj(0));
+				if (  reft[itadj] >=0 && !flag[itadj])
+				  { nbNewBedge++;
+					refv[Tho.GetId(t[VerticesOfTriangularEdge[0][0]])]=bb[i];
+					refv[Tho.GetId(t[VerticesOfTriangularEdge[0][1]])]=bb[i];
+				  }
+				itadj=Tho.GetId(t.TriangleAdj(1));
+				if (  reft[itadj] >=0 && !flag[itadj])
+				  { nbNewBedge++;
+					refv[Tho.GetId(t[VerticesOfTriangularEdge[1][0]])]=bb[i];
+					refv[Tho.GetId(t[VerticesOfTriangularEdge[1][1]])]=bb[i];}
+					itadj=Tho.GetId(t.TriangleAdj(2));
+					if (  reft[itadj] >=0 && !flag[itadj])
+					  { nbNewBedge++;
+						refv[Tho.GetId(t[VerticesOfTriangularEdge[2][0]])]=bb[i];
+						refv[Tho.GetId(t[VerticesOfTriangularEdge[2][1]])]=bb[i];}
+			  }
+		  k=0;
+		  for (i=0;i<Tho.nbv;i++){
+			  if (kk[i]>=0) kk[i]=k++;
+			}
+		  _printLine_("   number of vertices " << k << ", remove = " << Tho.nbv - k);
+		  _printLine_("   number of triangles " << kt << ", remove = " << nbInT-kt);
+		  _printLine_("   number of New boundary edge " << nbNewBedge);
+		  long imaxnbv =k;
+		  Init(imaxnbv);
+		  for (i=0;i<Tho.nbv;i++)
+			if (kk[i]>=0) 
+			  {
+				vertices[nbv] = Tho.vertices[i];
+				if (!vertices[nbv].GetReferenceNumber())
+				 vertices[nbv].ReferenceNumber = refv[i];
+				nbv++;
+			  }
+		  if (imaxnbv != nbv){
+			  delete [] kk;
+			  delete [] refv;
+			  _error2_("imaxnbv != nbv");
+		  }
+		  for (i=0;i<Tho.nbt;i++)
+			if(  reft[i] >=0 && flag[i]) 
+			  {
+				const Triangle & t = Tho.triangles[i];
+				int i0 = Tho.GetId(t[0]);
+				int i1 = Tho.GetId(t[1]);
+				int i2 = Tho.GetId(t[2]);
+				if (i0<0 || i1<0 || i2<0){
+					delete [] refv;
+					_error2_("i0<0 || i1<0 || i2< 0");
+				}
+				if (i0>=Tho.nbv || i1>=Tho.nbv || i2>=Tho.nbv){
+					_error2_("i0>=Tho.nbv || i1>=Tho.nbv || i2>=Tho.nbv");
+				}
+				triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]);
+				triangles[nbt].color = Tho.subdomains[reft[i]].ReferenceNumber; 
+				nbt++;           
+			  }
+		  if (kt!=nbt){
+			  _error2_("kt!=nbt");
+		  }
+		  if (nbt==0 && nbv==0) {
+			  _error2_("All triangles have been removed");
+		  }
+		  delete [] kk;
+		  delete [] reft;
+		  delete [] refv;
+		  //double cutoffradian = 10.0/180.0*Pi;
+		  BuildGeometryFromMesh(bamgopts);
+		  Gh.PostRead(); 
+		  SetIntCoor();
+		  ReconstructExistingMesh();
+
+		  if (!nbsubdomains){
+			  _error2_("nbsubdomains==0");
+		  }
+		  if (!subdomains[0].head || !subdomains[0].head->link){
+			  _error2_("!subdomains[0].head || !subdomains[0].head->link");
+		  }
+
+	  }
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(Mesh & Th,Geometry * pGh,Mesh * pBth,long maxnbv_in) COPY{{{*/
+	Mesh::Mesh(Mesh & Th,Geometry * pGh,Mesh * pBth,long maxnbv_in)
+	  : Gh(*(pGh?pGh:&Th.Gh)), BTh(*(pBth?pBth:this)) {
+		  /*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
+		  Gh.NbRef++;
+		  maxnbv_in = Max(maxnbv_in,Th.nbv); 
+		  long i;
+		  // do all the allocation to be sure all the pointer existe
+
+		  Init(maxnbv_in);// to make the allocation 
+		  // copy of triangles
+		  nbv = Th.nbv;
+		  nbt = Th.nbt;
+		  nbe = Th.nbe;
+		  nbsubdomains = Th.nbsubdomains;
+		  nbtout = Th.nbtout;
+		  nbq =  Th.nbq ;
+		  NbVerticesOnGeomVertex = Th.NbVerticesOnGeomVertex;
+		  if(NbVerticesOnGeomVertex)
+			VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+		  NbVerticesOnGeomEdge = Th.NbVerticesOnGeomEdge;
+		  if (NbVerticesOnGeomEdge)
+			VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge] ;
+		  if (& BTh == & Th.BTh){ // same background 
+			  BTh.NbRef++;
+			  NbVertexOnBThVertex = Th.NbVertexOnBThVertex;
+			  if(NbVertexOnBThVertex)
+				VertexOnBThVertex = new VertexOnVertex[NbVertexOnBThVertex];
+			  NbVertexOnBThEdge = Th.NbVertexOnBThEdge;
+			  if(NbVertexOnBThEdge)
+				VertexOnBThEdge = new VertexOnEdge[NbVertexOnBThEdge];
+			 }
+		  else { // no add on background mesh 
+			  BTh.NbRef++;
+			  NbVertexOnBThVertex=0;
+			  VertexOnBThVertex=0;
+			  NbVertexOnBThEdge=0;
+			  VertexOnBThEdge=0;
+			 }
+
+
+		  if(nbe)
+			edges = new Edge[nbe];
+		  if(nbsubdomains)
+			subdomains = new SubDomain[nbsubdomains];
+		  pmin = Th.pmin;
+		  pmax = Th.pmax;
+		  coefIcoor = Th.coefIcoor;
+		  for(i=0;i<nbt;i++)
+			triangles[i].Set(Th.triangles[i],Th,*this);
+		  for(i=0;i<nbe;i++)
+			edges[i].Set(Th,i,*this);
+		  for(i=0;i<nbv;i++)
+			vertices[i].Set(Th.vertices[i],Th,*this);
+		  for(i=0;i<nbsubdomains;i++)  
+			subdomains[i].Set(Th,i,*this);
+		  for (i=0;i<NbVerticesOnGeomVertex;i++)
+			VerticesOnGeomVertex[i].Set(Th.VerticesOnGeomVertex[i],Th,*this);
+		  for (i=0;i<NbVerticesOnGeomEdge;i++)
+			VerticesOnGeomEdge[i].Set(Th.VerticesOnGeomEdge[i],Th,*this);
+		  quadtree=0;
+
+	  }
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(long maxnbv,Mesh & BT,BamgOpts* bamgopts,int keepBackVertices){{{*/
+	Mesh::Mesh(long imaxnbv,Mesh & BT,BamgOpts* bamgopts,int keepBackVertices) :Gh(BT.Gh),BTh(BT) {
+		this->Init(imaxnbv);
+		TriangulateFromGeom1(bamgopts,keepBackVertices);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Mesh(long maxnbv,Geometry & G,BamgOpts* bamgopts){{{*/
+	Mesh::Mesh(long imaxnbv,Geometry & G,BamgOpts* bamgopts):Gh(G),BTh(*this){
+		Init(imaxnbv);
+		TriangulateFromGeom0(bamgopts);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::~Mesh(){{{*/
+	Mesh::~Mesh() {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Triangles)*/
+
+		//if (vertices)             delete [] vertices;
+		if (edges)                delete [] edges;
+		if (triangles)            delete [] triangles;
+		if (quadtree)             delete    quadtree;
+		//if (orderedvertices)                delete [] orderedvertices;
+		if (subdomains)           delete []  subdomains;
+		if (VerticesOnGeomEdge)   delete [] VerticesOnGeomEdge;
+		if (VerticesOnGeomVertex) delete [] VerticesOnGeomVertex;
+		if (VertexOnBThVertex)    delete [] VertexOnBThVertex;
+		if (VertexOnBThEdge)      delete [] VertexOnBThEdge;
+
+		if (&Gh) {
+			if (Gh.NbRef>0) Gh.NbRef--;
+			else if (Gh.NbRef==0) delete &Gh;
+		}
+		if (&BTh && (&BTh != this)) {
+			if (BTh.NbRef>0) BTh.NbRef--;
+			else if (BTh.NbRef==0) delete &BTh;
+		}
+		Init(0); // set all to zero 
+	}
+	/*}}}*/
+
+	/*IO*/
+	/*FUNCTION Mesh::ReadMesh(int* index,double* x,double* y,int nods,int nels){{{*/
+	void Mesh::ReadMesh(int* index,double* x,double* y,int nods,int nels){
+
+		double Hmin = HUGE_VAL;// the infinie value 
+		long i1,i2,i3;
+		long i,j;
+		Metric M1(1);
+		int verbose=0;
+		bool* nodeflags=NULL;
+
+		nbv=nods;
+		maxnbv=nbv;
+		nbt=nels;
+
+		//Vertices
+		if (verbose) _printLine_("Reading vertices (" << nbv << ")");
+		vertices=xNew<BamgVertex>(nbv);
+		orderedvertices=xNew<BamgVertex*>(nbv);
+		for (i=0;i<nbv;i++){
+			vertices[i].r.x=x[i];
+			vertices[i].r.y=y[i];
+			vertices[i].ReferenceNumber=1;
+			vertices[i].DirOfSearch =NoDirOfSearch;
+			vertices[i].m=M1;
+			vertices[i].color=0;
+		}
+		maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals 
+
+		//Triangles
+		if (verbose) _printLine_("Reading triangles (" << nbt << ")");
+		triangles =new Triangle[maxnbt]; //we cannot allocate only nbt triangles since 
+		nodeflags=xNew<bool>(nbv);
+		for(i=0;i<nbv;i++) nodeflags[i]=false;
+		//other triangles will be added for each edge
+		for (i=0;i<nbt;i++){
+			Triangle & t = triangles[i];
+			i1=(long)index[i*3+0]-1; //for C indexing
+			i2=(long)index[i*3+1]-1; //for C indexing
+			i3=(long)index[i*3+2]-1; //for C indexing
+			t=Triangle(this,i1,i2,i3);
+			t.color=1;
+			nodeflags[i1]=nodeflags[i2]=nodeflags[i3]=true;
+		}
+
+		/*Recreate geometry: */
+		if (verbose) _printLine_("Building Geometry");
+		BuildGeometryFromMesh();
+		if (verbose) _printLine_("Completing geometry");
+		Gh.PostRead();
+
+		/*Check that there is no orphan*/
+		bool isorphan=false;
+		for(i=0;i<nbv;i++){
+			if(!nodeflags[i]){
+				_printLine_("Vertex " << i+1 << " does not belong to any element");
+				isorphan=true;
+			}
+		}
+		if(isorphan) _error2_("Orphan found in mesh, see ids above");
+
+		/*Clean up*/
+		xDelete<bool>(nodeflags);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::ReadMesh(BamgMesh* bamgmesh, BamgOpts* bamgopts){{{*/
+	void Mesh::ReadMesh(BamgMesh* bamgmesh, BamgOpts* bamgopts){
+
+		int    verbose;
+		double Hmin = HUGE_VAL;    // the infinie value
+		long   i1,i2,i3;
+		long   i,j;
+		Metric M1(1);
+
+		verbose=bamgopts->verbose;
+
+		nbv=bamgmesh->VerticesSize[0];
+		maxnbv=nbv;
+		nbt=bamgmesh->TrianglesSize[0];
+
+		//Vertices
+		if(bamgmesh->Vertices){
+			if(verbose>5) _printLine_("      processing Vertices");
+
+			vertices=xNew<BamgVertex>(nbv);
+			orderedvertices=xNew<BamgVertex*>(nbv);
+
+			for (i=0;i<nbv;i++){
+				vertices[i].r.x=bamgmesh->Vertices[i*3+0];
+				vertices[i].r.y=bamgmesh->Vertices[i*3+1];
+				vertices[i].ReferenceNumber=(long)bamgmesh->Vertices[i*3+2];
+				vertices[i].DirOfSearch =NoDirOfSearch;
+				vertices[i].m=M1;
+				vertices[i].color=0;
+			}
+			maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals 
+		}
+		else{
+			if(verbose>5) _error2_("no Vertices found in the initial mesh");
+		}
+
+		//Triangles
+		if(bamgmesh->Triangles){
+			if(verbose>5) _printLine_("      processing Triangles");
+			triangles =new Triangle[maxnbt]; //we cannot allocate only nbt triangles since 
+			//other triangles will be added for each edge
+			for (i=0;i<nbt;i++){
+				Triangle &t=triangles[i];
+				i1=(long)bamgmesh->Triangles[i*4+0]-1; //for C indexing
+				i2=(long)bamgmesh->Triangles[i*4+1]-1; //for C indexing
+				i3=(long)bamgmesh->Triangles[i*4+2]-1; //for C indexing
+				t=Triangle(this,i1,i2,i3);
+				t.color=(long)bamgmesh->Triangles[i*4+3];
+			}
+		}
+		else{
+			if(verbose>5) _error2_("no Triangles found in the initial mesh");
+		}
+
+		//Quadrilaterals
+		if(bamgmesh->Quadrilaterals){
+			if(verbose>5) _printLine_("      processing Quadrilaterals");
+			long i1,i2,i3,i4,iref;
+			triangles =new Triangle[nbt];
+			for (i=0;i<bamgmesh->QuadrilateralsSize[0];i++){
+				//divide the quad into two triangles
+				Triangle & t1 = triangles[2*i];
+				Triangle & t2 = triangles[2*i+1];
+				i1=(long)bamgmesh->Quadrilaterals[i*5+0]-1; //for C indexing
+				i2=(long)bamgmesh->Quadrilaterals[i*5+1]-1; //for C indexing
+				i3=(long)bamgmesh->Quadrilaterals[i*5+2]-1; //for C indexing
+				i4=(long)bamgmesh->Quadrilaterals[i*5+3]-1; //for C indexing
+				t1=Triangle(this,i1,i2,i3);
+				t2=Triangle(this,i3,i4,i1);
+				t1.color=(long)bamgmesh->Quadrilaterals[i*5+4];
+				t2.color=(long)bamgmesh->Quadrilaterals[i*5+4];
+				t1.SetHidden(OppositeEdge[1]); // two times  because the adj was not created 
+				t2.SetHidden(OppositeEdge[1]); 
+			}
+		}
+
+		//VerticesOnGeomEdge
+		if(bamgmesh->VerticesOnGeomEdge){
+			if(verbose>5) _printLine_("      processing VerticesOnGeomEdge");
+			NbVerticesOnGeomEdge=bamgmesh->VerticesOnGeomEdgeSize[0];
+			VerticesOnGeomEdge= new  VertexOnGeom[NbVerticesOnGeomEdge] ;
+			for (i=0;i<NbVerticesOnGeomEdge;i++){
+				long  i1,i2;
+				double s;
+				i1=(long)  bamgmesh->VerticesOnGeomEdge[i*3+0]-1; //for C indexing
+				i2=(long)  bamgmesh->VerticesOnGeomEdge[i*3+1]-1; //for C indexing
+				s =(double)bamgmesh->VerticesOnGeomEdge[i*3+2];
+				VerticesOnGeomEdge[i]=VertexOnGeom(vertices[i1],Gh.edges[i2],s);
+			}
+		}
+
+		//VerticesOnGeomVertex
+		if(bamgmesh->VerticesOnGeomVertexSize[0]){
+			if(verbose>5) _printLine_("      processing VerticesOnGeomVertex");
+			NbVerticesOnGeomVertex=bamgmesh->VerticesOnGeomVertexSize[0];
+			VerticesOnGeomVertex  = new  VertexOnGeom[NbVerticesOnGeomVertex] ;
+			for (i=0;i<NbVerticesOnGeomVertex;i++){
+				long  i1,i2;
+				i1=(long)bamgmesh->VerticesOnGeomVertex[i*2+0]-1; //for C indexing
+				i2=(long)bamgmesh->VerticesOnGeomVertex[i*2+1]-1; //for C indexing
+				VerticesOnGeomVertex[i]=VertexOnGeom(vertices[i1],Gh.vertices[i2]);
+			}
+		}
+
+		//Edges
+		if (bamgmesh->Edges){
+			int i1,i2;
+			double* len=NULL;
+
+			if(verbose>5) _printLine_("      processing Edges");
+			nbe=bamgmesh->EdgesSize[0];
+			edges= new Edge[nbe];
+			//initialize length of each edge (used to provided metric)
+			len= new double[nbv];
+			for(i=0;i<nbv;i++) len[i]=0;
+
+			for (i=0;i<nbe;i++){
+				i1=(int)bamgmesh->Edges[i*3+0]-1; //-1 for C indexing
+				i2=(int)bamgmesh->Edges[i*3+1]-1; //-1 for C indexing
+				edges[i].ReferenceNumber=(long)bamgmesh->Edges[i*3+2];
+				edges[i].v[0]= vertices +i1;
+				edges[i].v[1]= vertices +i2;
+				edges[i].adj[0]=NULL;
+				edges[i].adj[1]=NULL;
+				R2 x12=vertices[i2].r-vertices[i1].r;
+				double l12=sqrt((x12,x12));
+
+				//prepare metric
+				vertices[i1].color++;
+				vertices[i2].color++;
+				len[i1]+=l12;
+				len[i2]+=l12;
+				Hmin = Min(Hmin,l12);
+			}
+
+			// definition  the default of the given mesh size 
+			for (i=0;i<nbv;i++){
+				if (vertices[i].color>0) 
+				 vertices[i].m=Metric(len[i]/(double)vertices[i].color);
+				else 
+				 vertices[i].m=Metric(Hmin);
+			}
+			delete [] len;
+
+			// construction of edges[].adj 
+			for (i=0;i<nbv;i++){ 
+				vertices[i].color=(vertices[i].color ==2) ?-1:-2;
+			}
+			for (i=0;i<nbe;i++){
+				for (j=0;j<2;j++) { 
+					BamgVertex *v=edges[i].v[j];
+					long i0=v->color,j0;
+					if(i0==-1){
+						v->color=i*2+j;
+					}
+					else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
+						j0 = i0%2;
+						i0 = i0/2;
+						_assert_(v==edges[i0 ].v[j0]);
+						edges[i ].adj[j ] =edges +i0;
+						edges[i0].adj[j0] =edges +i ;
+						v->color = -3;
+					}
+				}
+			}
+		}
+
+		//EdgeOnGeomEdge
+		if(bamgmesh->EdgesOnGeomEdge){
+			if(verbose>5) _printLine_("      processing EdgesOnGeomEdge");
+			int i1,i2,i,j;
+			i2=bamgmesh->EdgesOnGeomEdgeSize[0];
+			for (i1=0;i1<i2;i1++) {
+				i=(int)bamgmesh->EdgesOnGeomEdge[i1*2+0]-1; //C indexing
+				j=(int)bamgmesh->EdgesOnGeomEdge[i1*2+1]-1; //C indexing
+				//Check value
+				if(!(i>=0 && j>=0 && i<nbe && j<Gh.nbe)) {
+					_error2_("ReadMesh error: EdgesOnGeomEdge edge provided (line " << i1+1 << ": [" << i+1 << " " << j+1 << "]) is incorrect (must be positive, [0<i<nbe=" << nbe << " 0<j<Gh.nbe=" << Gh.nbe << "]");
+				}
+				edges[i].GeomEdgeHook=Gh.edges+j;
+			}
+		}
+
+		//SubDomain
+		if(bamgmesh->SubDomains){
+			long i3,head,direction;
+			if(verbose>5) _printLine_("      processing SubDomains");
+			nbsubdomains=bamgmesh->SubDomainsSize[0];
+			subdomains = new SubDomain [ nbsubdomains ];
+			for (i=0;i<nbsubdomains;i++) {
+				i3  =(int)bamgmesh->SubDomains[i*3+0];
+				head=(int)bamgmesh->SubDomains[i*3+1]-1;//C indexing
+				direction=(int)bamgmesh->SubDomains[i*3+2];
+				if (i3!=23) _error2_("Bad Subdomain definition: first number should be 3");
+				if (head<0 || head>=nbt) _error2_("Bad Subdomain definition: head should in [1 " << nbt << "] (triangle number)");
+				subdomains[i].head = triangles+head;
+			}
+		}
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::WriteMesh {{{*/
+	void Mesh::WriteMesh(BamgMesh* bamgmesh,BamgOpts* bamgopts){
+
+		/*Intermediary*/
+		int i,j,k,num,i1,i2;
+		long n;
+		int* head_1=NULL;
+		int* next_1=NULL;
+		int* connectivitysize_1=NULL;
+		int  connectivitymax_1=0;
+
+		/*Get options*/
+		int verbose=bamgopts->verbose;
+
+		/*Build reft that holds the number the subdomain number of each triangle, and the real numbering of the elements*/
+		long* reft = new long[nbt];
+		long* numt = new long[nbt];
+		long nbInT = TriangleReferenceList(reft);
+		TriangleIntNumbering(numt);
+
+		/*Chaining algorithm used to generate connectivity tables and other outputs*/
+
+		//Memory Allocation
+		head_1=xNew<int>(nbv);
+		next_1=xNew<int>(3*nbt);
+		connectivitysize_1=xNew<int>(nbv);
+
+		//Initialization
+		for (i=0;i<nbv;i++) head_1[i]=-1;
+		for (i=0;i<nbv;i++) connectivitysize_1[i]=0;
+		k=0;
+		//Chains generation
+		for (i=0;i<nbt;i++) {
+			//Do not take into account outside triangles (reft<0)
+			if (reft[i]>=0){
+				for (j=0;j<3;j++){
+					int v=GetId(triangles[i][j]); //jth vertex of the ith triangle
+					if (k>3*nbt-1 || k<0) _error2_("k = " << k << ", nbt = " << nbt);
+					next_1[k]=head_1[v];
+					if (v>nbv-1 || v<0)   _error2_("v = " << v << ", nbv = " << nbv);
+					head_1[v]=k++;
+					connectivitysize_1[v]+=1;
+				}
+			}
+		}
+		//Get maximum connectivity
+		connectivitymax_1=0;
+		for (i=0;i<nbv;i++){
+			if (connectivitysize_1[i]>connectivitymax_1) connectivitymax_1=connectivitysize_1[i];
+		}
+
+		/*OK, now build outputs*/
+
+		/*Vertices*/
+		if(verbose>5) _printLine_("      writing Vertices");
+		bamgmesh->VerticesSize[0]=nbv;
+		bamgmesh->VerticesSize[1]=3;
+		if (nbv){
+			bamgmesh->Vertices=xNew<double>(3*nbv);
+			for (i=0;i<nbv;i++){
+				bamgmesh->Vertices[i*3+0]=vertices[i].r.x;
+				bamgmesh->Vertices[i*3+1]=vertices[i].r.y;
+				bamgmesh->Vertices[i*3+2]=vertices[i].GetReferenceNumber();
+			}
+		}
+
+		/*Edges*/
+		if(verbose>5) _printLine_("      writing Edges");
+		bamgmesh->EdgesSize[0]=nbe;
+		bamgmesh->EdgesSize[1]=3;
+		int NumIssmSegments=0;
+		if (nbe){
+			bamgmesh->Edges=xNew<double>(3*nbe);
+			for (i=0;i<nbe;i++){
+				bamgmesh->Edges[i*3+0]=GetId(edges[i][0])+1; //back to M indexing
+				bamgmesh->Edges[i*3+1]=GetId(edges[i][1])+1; //back to M indexing
+				bamgmesh->Edges[i*3+2]=edges[i].ReferenceNumber;
+				if(edges[i].GeomEdgeHook){
+					NumIssmSegments++;
+				}
+			}
+		}
+
+		/*Element edges*/
+		if(verbose>5) _printLine_("      writing element edges");
+		SetOfEdges4* edge4=new SetOfEdges4(nbt*3,nbv);
+		double* elemedge=NULL;
+		elemedge=xNew<double>(3*nbt);
+		for (i=0;i<3*nbt;i++) elemedge[i]=-2.;//will become -1
+		k=0;
+		for (i=0;i<nbt;i++){
+			//Do not take into account outside triangles (reft<0)
+			if (reft[i]>=0){
+				for  (j=0;j<3;j++) {
+					i1=GetId(triangles[i][VerticesOfTriangularEdge[j][0]]);
+					i2=GetId(triangles[i][VerticesOfTriangularEdge[j][1]]);
+					n =edge4->SortAndFind(i1,i2);
+					if (n==-1){
+						//first time
+						n=edge4->SortAndAdd(i1,i2);
+						elemedge[n*2+0]=double(k);
+					}
+					else{
+						//second time
+						elemedge[n*2+1]=double(k);
+					}
+				}
+				k++;
+			}
+		}
+		bamgmesh->IssmEdgesSize[0]=edge4->nb();
+		bamgmesh->IssmEdgesSize[1]=4;
+		bamgmesh->IssmEdges=xNew<double>(4*edge4->nb());
+		for (i=0;i<edge4->nb();i++){
+			/*Invert first two vertices if necessary*/
+			bool found=false;
+			for (j=0;j<3;j++){
+				if (triangles[(int)elemedge[2*i+0]](j)==vertices+edge4->i(i)){
+					if (triangles[(int)elemedge[2*i+0]]((j+1)%3)==vertices+edge4->j(i)){
+						//trigonometric direction
+						bamgmesh->IssmEdges[i*4+0]=edge4->i(i)+1;// back to M indexing
+						bamgmesh->IssmEdges[i*4+1]=edge4->j(i)+1;// back to M indexing
+					}
+					else{
+						bamgmesh->IssmEdges[i*4+0]=edge4->j(i)+1;// back to M indexing
+						bamgmesh->IssmEdges[i*4+1]=edge4->i(i)+1;// back to M indexing
+					}
+					found=true;
+					break;
+				}
+			}
+			_assert_(found);
+			bamgmesh->IssmEdges[i*4+2]=elemedge[2*i+0]+1; // back to M indexing
+			bamgmesh->IssmEdges[i*4+3]=elemedge[2*i+1]+1; // back to M indexing
+		}
+		//clean up
+		delete edge4;
+		xDelete<double>(elemedge);
+
+		/*IssmSegments*/
+		if(verbose>5) _printLine_("      writing IssmSegments");
+		bamgmesh->IssmSegmentsSize[0]=NumIssmSegments;
+		bamgmesh->IssmSegmentsSize[1]=4;
+		bamgmesh->IssmSegments=xNew<double>(4*NumIssmSegments);
+		num=0;
+		for (i=0;i<nbe;i++){
+			if(edges[i].GeomEdgeHook){
+				//build segment
+				int i1=GetId(edges[i][0]);
+				int i2=GetId(edges[i][1]);
+				bool stop=false;
+				for(j=head_1[i1];j!=-1;j=next_1[j]){
+					for(k=0;k<3;k++){
+						if (GetId(triangles[(int)j/3][k])==i1){
+							if (GetId(triangles[(int)j/3][(int)((k+1)%3)])==i2){
+								bamgmesh->IssmSegments[num*4+0]=GetId(edges[i][0])+1; //back to M indexing
+								bamgmesh->IssmSegments[num*4+1]=GetId(edges[i][1])+1; //back to M indexing
+								bamgmesh->IssmSegments[num*4+2]=(int)j/3+1;            //back to M indexing
+								bamgmesh->IssmSegments[num*4+3]=edges[i].ReferenceNumber;
+								num+=1;
+								stop=true;
+								break;
+							}
+							if (GetId(triangles[(int)j/3][(int)((k+2)%3)])==i2){
+								bamgmesh->IssmSegments[num*4+0]=GetId(edges[i][1])+1; //back to M indexing
+								bamgmesh->IssmSegments[num*4+1]=GetId(edges[i][0])+1; //back to M indexing
+								bamgmesh->IssmSegments[num*4+2]=(int)j/3+1;            //back to M indexing
+								bamgmesh->IssmSegments[num*4+3]=edges[i].ReferenceNumber;
+								num+=1;
+								stop=true;
+								break;
+							}
+						}
+					}
+					if(stop) break;
+				}
+				if (!stop){
+					_error2_("Element holding segment [" << i1+1 << " " << i2+1 << "] not found...");
+				}
+			}
+		}
+
+		/*Triangles*/
+		if(verbose>5) _printLine_("      writing Triangles");
+		k=nbInT-nbq*2;
+		num=0;
+		bamgmesh->TrianglesSize[0]=k;
+		bamgmesh->TrianglesSize[1]=4;
+		if (k){
+			bamgmesh->Triangles=xNew<double>(4*k);
+			for (i=0;i<nbt;i++){
+				Triangle &t=triangles[i];
+				//reft[i]=-1 for outside triangle
+				if (reft[i]>=0 && !( t.Hidden(0) || t.Hidden(1) || t.Hidden(2) )){
+					bamgmesh->Triangles[num*4+0]=GetId(t[0])+1; //back to M indexing
+					bamgmesh->Triangles[num*4+1]=GetId(t[1])+1; //back to M indexing
+					bamgmesh->Triangles[num*4+2]=GetId(t[2])+1; //back to M indexing
+					bamgmesh->Triangles[num*4+3]=subdomains[reft[i]].ReferenceNumber;
+					num=num+1;
+				}
+			}
+		}
+
+		/*Quadrilaterals*/
+		if(verbose>5) _printLine_("      writing Quadrilaterals");
+		bamgmesh->QuadrilateralsSize[0]=nbq;
+		bamgmesh->QuadrilateralsSize[1]=5;
+		if (nbq){
+			bamgmesh->Quadrilaterals=xNew<double>(5*nbq);
+			for (i=0;i<nbt;i++){
+				Triangle &t =triangles[i];
+				Triangle* ta;
+				BamgVertex *v0,*v1,*v2,*v3;
+				if (reft[i]<0) continue;
+				if ((ta=t.Quadrangle(v0,v1,v2,v3)) !=0 && &t<ta) { 
+					bamgmesh->Quadrilaterals[i*5+0]=GetId(v0)+1; //back to M indexing
+					bamgmesh->Quadrilaterals[i*5+1]=GetId(v1)+1; //back to M indexing
+					bamgmesh->Quadrilaterals[i*5+2]=GetId(v2)+1; //back to M indexing
+					bamgmesh->Quadrilaterals[i*5+3]=GetId(v3)+1; //back to M indexing
+					bamgmesh->Quadrilaterals[i*5+4]=subdomains[reft[i]].ReferenceNumber;
+				}
+			}
+		}
+
+		/*SubDomains*/
+		if(verbose>5) _printLine_("      writing SubDomains");
+		bamgmesh->SubDomainsSize[0]=nbsubdomains;
+		bamgmesh->SubDomainsSize[1]=4;
+		if (nbsubdomains){
+			bamgmesh->SubDomains=xNew<double>(4*nbsubdomains);
+			for (i=0;i<nbsubdomains;i++){
+				bamgmesh->SubDomains[i*4+0]=3;
+				bamgmesh->SubDomains[i*4+1]=reft[GetId(subdomains[i].head)];
+				bamgmesh->SubDomains[i*4+2]=1;
+				bamgmesh->SubDomains[i*4+3]=subdomains[i].ReferenceNumber;
+			}
+		}
+
+		/*SubDomainsFromGeom*/
+		if(verbose>5) _printLine_("      writing SubDomainsFromGeom");
+		bamgmesh->SubDomainsFromGeomSize[0]=Gh.nbsubdomains;
+		bamgmesh->SubDomainsFromGeomSize[1]=4;
+		if (Gh.nbsubdomains){
+			bamgmesh->SubDomainsFromGeom=xNew<double>(4*Gh.nbsubdomains);
+			for (i=0;i<Gh.nbsubdomains;i++){
+				bamgmesh->SubDomainsFromGeom[i*4+0]=2;
+				bamgmesh->SubDomainsFromGeom[i*4+1]=GetId(subdomains[i].edge)+1; //back to Matlab indexing
+				bamgmesh->SubDomainsFromGeom[i*4+2]=subdomains[i].direction;
+				bamgmesh->SubDomainsFromGeom[i*4+3]=Gh.subdomains[i].ReferenceNumber;
+			}
+		}
+
+		/*VerticesOnGeomVertex*/
+		if(verbose>5) _printLine_("      writing VerticesOnGeomVertex");
+		bamgmesh->VerticesOnGeomVertexSize[0]=NbVerticesOnGeomVertex;
+		bamgmesh->VerticesOnGeomVertexSize[1]=2;
+		if (NbVerticesOnGeomVertex){
+			bamgmesh->VerticesOnGeomVertex=xNew<double>(2*NbVerticesOnGeomVertex);
+			for (i=0;i<NbVerticesOnGeomVertex;i++){
+				VertexOnGeom &v=VerticesOnGeomVertex[i];
+				_assert_(v.OnGeomVertex());
+				bamgmesh->VerticesOnGeomVertex[i*2+0]=GetId((BamgVertex*)v)+1; //back to Matlab indexing
+				bamgmesh->VerticesOnGeomVertex[i*2+1]=Gh.GetId((GeomVertex*)v)+1; //back to Matlab indexing
+			}
+		}
+
+		/*VertexOnGeomEdge*/
+		if(verbose>5) _printLine_("      writing VerticesOnGeomEdge");
+		bamgmesh->VerticesOnGeomEdgeSize[0]=NbVerticesOnGeomEdge;
+		bamgmesh->VerticesOnGeomEdgeSize[1]=3;
+		if (NbVerticesOnGeomEdge){
+			bamgmesh->VerticesOnGeomEdge=xNew<double>(3*NbVerticesOnGeomEdge);
+			for (i=0;i<NbVerticesOnGeomEdge;i++){
+				const VertexOnGeom &v=VerticesOnGeomEdge[i];
+				if (!v.OnGeomEdge()){
+					_error2_("A vertices supposed to be OnGeomEdge is actually not");
+				}
+				bamgmesh->VerticesOnGeomEdge[i*3+0]=GetId((BamgVertex*)v)+1; //back to Matlab indexing
+				bamgmesh->VerticesOnGeomEdge[i*3+1]=Gh.GetId((const GeomEdge*)v)+1; //back to Matlab indexing
+				bamgmesh->VerticesOnGeomEdge[i*3+2]=(double)v; //absisce
+			}
+		}
+
+		/*EdgesOnGeomEdge*/
+		if(verbose>5) _printLine_("      writing EdgesOnGeomEdge");
+		k=0;
+		for (i=0;i<nbe;i++){
+			if (edges[i].GeomEdgeHook) k=k+1;
+		}
+		bamgmesh->EdgesOnGeomEdgeSize[0]=k;
+		bamgmesh->EdgesOnGeomEdgeSize[1]=2;
+		if (k){
+			bamgmesh->EdgesOnGeomEdge=xNew<double>(2*(int)k);
+			int count=0;
+			for (i=0;i<nbe;i++){
+				if (edges[i].GeomEdgeHook){
+					bamgmesh->EdgesOnGeomEdge[count*2+0]=(double)i+1; //back to Matlab indexing
+					bamgmesh->EdgesOnGeomEdge[count*2+1]=(double)Gh.GetId(edges[i].GeomEdgeHook)+1; //back to Matlab indexing
+					count=count+1;
+				}
+			}
+		}
+
+		/*Element Connectivity*/
+		if(verbose>5) _printLine_("      writing Element connectivity");
+		bamgmesh->ElementConnectivitySize[0]=nbt-nbtout;
+		bamgmesh->ElementConnectivitySize[1]=3;
+		bamgmesh->ElementConnectivity=xNew<double>(3*(nbt-nbtout));
+		for (i=0;i<3*(nbt-nbtout);i++) bamgmesh->ElementConnectivity[i]=NAN;
+		num=0;
+		for (i=0;i<nbt;i++){
+			if (reft[i]>=0){
+				for (j=0;j<3;j++){
+					k=GetId(triangles[i].TriangleAdj(j));
+					if (reft[k]>=0){
+						_assert_(3*num+j<3*(nbt-nbtout));
+						bamgmesh->ElementConnectivity[3*num+j]=k+1; // back to Matlab indexing
+					}
+				}
+				num+=1;
+			}
+		}
+
+		/*ElementNodal Connectivity*/
+		if(verbose>5) _printLine_("      writing Nodal element connectivity");
+		bamgmesh->NodalElementConnectivitySize[0]=nbv;
+		bamgmesh->NodalElementConnectivitySize[1]=connectivitymax_1;
+		bamgmesh->NodalElementConnectivity=xNew<double>(connectivitymax_1*nbv);
+		for (i=0;i<connectivitymax_1*nbv;i++) bamgmesh->NodalElementConnectivity[i]=NAN;
+		for (i=0;i<nbv;i++){
+			k=0;
+			for(j=head_1[i];j!=-1;j=next_1[j]){
+				_assert_(connectivitymax_1*i+k < connectivitymax_1*nbv);
+				bamgmesh->NodalElementConnectivity[connectivitymax_1*i+k]=floor((double)j/3)+1;
+				k++;
+			}
+		}
+
+		/*Nodal Connectivity*/
+		if(verbose>5) _printLine_("      writing Nodal connectivity");
+		//chaining algorithm (again...)
+		int* head_2=NULL;
+		int* next_2=NULL;
+		int* connectivitysize_2=NULL;
+		int  connectivitymax_2=0;
+		i1=bamgmesh->IssmEdgesSize[0];
+		i2=bamgmesh->IssmEdgesSize[1];
+		head_2=xNew<int>(nbv);
+		next_2=xNew<int>(2*i1);
+		connectivitysize_2=xNew<int>(nbv);
+		//Initialization
+		for (i=0;i<nbv;i++) head_2[i]=-1;
+		for (i=0;i<nbv;i++) connectivitysize_2[i]=0;
+		k=0;
+		//Chains generation
+		for (i=0;i<i1;i++) {
+			for (j=0;j<2;j++){
+				int v=(int)bamgmesh->IssmEdges[i*i2+j]-1; //back to C indexing
+				if (k>2*i1-1 || k<0) _error2_("Index exceed matrix dimensions (k=" << k << " not in [0 " << 2*i1-1 << "]");
+				next_2[k]=head_2[v];
+				if (v>nbv-1 || v<0)   _error2_("Index exceed matrix dimensions (v=" << v << " not in [0 " << nbv-1 << "])");
+				head_2[v]=k++;
+				connectivitysize_2[v]+=1;
+			}
+		}
+		//Get maximum connectivity
+		for (i=0;i<nbv;i++){
+			if (connectivitysize_2[i]>connectivitymax_2) connectivitymax_2=connectivitysize_2[i];
+		}
+		//Build output
+		bamgmesh->NodalConnectivitySize[0]=nbv;
+		bamgmesh->NodalConnectivitySize[1]=connectivitymax_2;
+		bamgmesh->NodalConnectivity=xNew<double>(connectivitymax_2*nbv);
+		for (i=0;i<connectivitymax_2*nbv;i++) bamgmesh->NodalConnectivity[i]=NAN;
+		for (i=0;i<nbv;i++){
+			k=0;
+			for(j=head_2[i];j!=-1;j=next_2[j]){
+				_assert_(connectivitymax_2*i+k < connectivitymax_2*nbv);
+				num=(int)bamgmesh->IssmEdges[int(j/2)*i2+0];
+				if (i+1==num){ //carefull, ElementEdge is in M indexing
+					//i is the first vertex of the edge, it is therefore connected to the second vertex
+					bamgmesh->NodalConnectivity[connectivitymax_2*i+k]=bamgmesh->IssmEdges[int(j/2)*i2+1];
+				}
+				else{
+					bamgmesh->NodalConnectivity[connectivitymax_2*i+k]=num;
+				}
+				k++;
+			}
+		}
+
+		/*Cracked vertices*/
+		if(verbose>5) _printLine_("      writing Cracked vertices");
+		bamgmesh->CrackedVerticesSize[0]=NbCrackedVertices;
+		bamgmesh->CrackedVerticesSize[1]=2;
+		if (NbCrackedVertices){
+			bamgmesh->CrackedVertices=xNew<double>(2*NbCrackedVertices);
+			for (i=0;i<NbCrackedVertices;i++){
+				bamgmesh->CrackedVertices[i*2+0]=CrackedVertices[i*2+0]+1; //M indexing
+				bamgmesh->CrackedVertices[i*2+1]=CrackedVertices[i*2+1]+1; //M indexing
+			}
+		}
+
+		/*Cracked vertices*/
+		if(verbose>5) _printLine_("      writing Cracked vertices");
+		bamgmesh->CrackedEdgesSize[0]=NbCrackedEdges;
+		bamgmesh->CrackedEdgesSize[1]=4;
+		if (NbCrackedEdges){
+			bamgmesh->CrackedEdges=xNew<double>(2*NbCrackedEdges);
+			for (i=0;i<NbCrackedEdges;i++){
+				bamgmesh->CrackedEdges[i*2+0]=0;//CrackedEdges[i]->+1; //M indexing
+				bamgmesh->CrackedEdges[i*2+1]=0;//CrackedEdges[i]-]->+1; //M indexing
+			}
+		}
+
+		//clean up
+		xDelete<int>(connectivitysize_1);
+		xDelete<int>(head_1);
+		xDelete<int>(next_1);
+		xDelete<int>(connectivitysize_2);
+		xDelete<int>(head_2);
+		xDelete<int>(next_2);
+		delete [] reft;
+		delete [] numt;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::ReadMetric{{{*/
+	void Mesh::ReadMetric(const BamgOpts* bamgopts) {
+
+		/*Intermediary*/
+		int  i,j;
+
+		if(bamgopts->verbose>3) _printLine_("      processing metric");
+		double hmin = Max(bamgopts->hmin,MinimalHmin());
+		double hmax = Min(bamgopts->hmax,MaximalHmax());
+		double coef = bamgopts->coeff;
+
+		//for now we only use j==3
+		j=3;
+
+		for (i=0;i<nbv;i++){
+			double h;
+			if (j == 1){
+				h=bamgopts->metric[i];
+				vertices[i].m=Metric(Max(hmin,Min(hmax, h*coef)));
+			}
+			else if (j==3){
+				//do not erase metric computed by hVertices
+				if (vertices[i].m.a11==1 && vertices[i].m.a21==0 && vertices[i].m.a22==1){
+					double a,b,c;	     
+					a=bamgopts->metric[i*3+0];
+					b=bamgopts->metric[i*3+1];
+					c=bamgopts->metric[i*3+2];
+					Metric M(a,b,c);
+					EigenMetric Vp(M/coef);
+
+					Vp.Maxh(hmax);
+					Vp.Minh(hmin);
+					vertices[i].m = Vp;
+				}
+			}
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::WriteMetric{{{*/
+	void Mesh::WriteMetric(BamgOpts* bamgopts) {
+		int i;
+		xDelete<double>(bamgopts->metric);
+		bamgopts->metric=xNew<double>(3*nbv);
+		for (i=0;i<nbv;i++){
+			bamgopts->metric[i*3+0]=vertices[i].m.a11;
+			bamgopts->metric[i*3+1]=vertices[i].m.a21;
+			bamgopts->metric[i*3+2]=vertices[i].m.a22;
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::WriteIndex{{{*/
+	void Mesh::WriteIndex(int** pindex,int* pnels){
+
+		/*Intermediary*/
+		int i,k,num;
+		int verbose=0;
+
+		/*output*/
+		int* index=NULL;
+
+		/*Get number of triangles*/
+		k=0;
+		for (i=0;i<nbt;i++){
+			Triangle &t=triangles[i];
+			if(t.det>0) k++;
+		}
+
+		if (k){
+			index=xNew<int>(3*k);
+			num=0;
+			for (i=0;i<nbt;i++){
+				Triangle &t=triangles[i];
+				if (t.det>0 && !(t.Hidden(0)||t.Hidden(1) || t.Hidden(2) )){
+					//if(t.Anisotropy()<2 & t.Length()<1.e+5){
+						index[num*3+0]=GetId(t[0])+1; //back to M indexing
+						index[num*3+1]=GetId(t[1])+1; //back to M indexing
+						index[num*3+2]=GetId(t[2])+1; //back to M indexing
+						num=num+1;
+					//}
+				}
+			}
+		}
+
+		/*Assign output pointers*/
+		*pindex=index;
+		*pnels=num;
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Mesh::AddGeometryMetric{{{*/
+	void Mesh::AddGeometryMetric(BamgOpts* bamgopts){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/IntersectGeomMetric)*/
+
+		/*Get options*/
+		int    verbose=bamgopts->verbose;
+		double anisomax =bamgopts->anisomax;
+		double errg     =bamgopts->errg;
+
+		double ss[2]={0.00001,0.99999};
+		double errC = 2*sqrt(2*errg);
+		double hmax = Gh.MaximalHmax();
+		double hmin = Gh.MinimalHmin();
+
+		//check that hmax is positive
+		if (hmax<=0){
+			_error2_("hmax<=0");
+		}
+
+		//errC cannot be higher than 1
+		if (errC>1) errC=1;
+
+		//Set all vertices to "on"
+		SetVertexFieldOn();
+
+		//loop over all the vertices on edges
+		for (int  i=0;i<nbe;i++){
+			for (int j=0;j<2;j++){
+
+				BamgVertex V;
+				VertexOnGeom GV;
+				Gh.ProjectOnCurve(edges[i],ss[j],V,GV);
+
+				GeomEdge* eg = GV;
+				double s = GV;
+				R2 tg;
+				double  R1= eg->R1tg(s,tg);
+				double  ht=hmax;
+				// err relative to the length of the edge
+				if (R1>1.0e-20) {  
+					ht = Min(Max(errC/R1,hmin),hmax);
+				}
+				double hn=Min(hmax,ht*anisomax);
+
+				if (ht<=0 || hn<=0){
+					_error2_("ht<=0 || hn<=0");
+				}
+				EigenMetric Vp(1/(ht*ht),1/(hn*hn),tg);
+				Metric MVp(Vp);
+				edges[i][j].m.IntersectWith(MVp);
+			}
+		}
+		// the problem is for the vertex on vertex 
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::AddMetric{{{*/
+	void Mesh::AddMetric(BamgOpts* bamgopts){
+		//  Hessiantype = 0 =>  H is computed using double P2 projection
+		//  Hessiantype = 1 =>  H is computed with green formula
+
+		/*Options*/
+		int Hessiantype=bamgopts->Hessiantype;
+
+		if (Hessiantype==0){
+			BuildMetric0(bamgopts);
+		}
+		else if (Hessiantype==1){
+			BuildMetric1(bamgopts);
+		}
+		else{
+			_error2_("Hessiantype " << Hessiantype << " not supported yet (1->use Green formula, 0-> double P2 projection)");
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::AddVertex{{{*/
+	void Mesh::AddVertex( BamgVertex &s,Triangle* t, Icoor2* det3) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Add)*/
+		// -------------------------------
+		//             s2
+		//                               !
+		//             /|\               !
+		//            / | \              !
+		//           /  |  \             !
+		//    tt1   /   |   \ tt0        !
+		//         /    |s   \           !
+		//        /     .     \          !
+		//       /  .      `   \         !
+		//      / .           ` \        !
+		//      ----------------         !
+		//   s0       tt2       s1
+		//-------------------------------
+
+		/*Intermediaries*/
+		Triangle* tt[3];       //the three triangles
+		Icoor2 det3local[3];   //three determinants (integer)
+		int nbzerodet =0;      //number of zeros in det3
+		int izerodet=-1;       //egde containing the vertex s
+		int iedge; 
+
+		/*three vertices of t*/
+		BamgVertex &s0=(*t)[0];
+		BamgVertex &s1=(*t)[1];
+		BamgVertex &s2=(*t)[2];
+
+		//determinant of t
+		Icoor2 detOld=t->det;
+
+		/* infvertexindex = index of the infinite vertex (NULL)
+			if no infinite vertex (NULL) infvertexindex=-1
+			else if v_i is infinite, infvertexindex=i*/
+		int infvertexindex = &s0 ?  ((  &s1 ? ( &s2  ? -1 : 2) : 1  )) : 0;
+
+		//some checks
+		if (( infvertexindex <0 ) && (detOld <0) ||  ( infvertexindex >=0  ) && (detOld >0) ){
+			_error2_("inconsistent configuration (Contact ISSM developers)");
+		}
+
+		// if det3 does not exist, build it 
+		if (!det3){ 
+			//allocate
+			det3 = det3local;
+			//if no infinite vertex
+			if (infvertexindex<0 ) {
+				det3[0]=bamg::det(s ,s1,s2);
+				det3[1]=bamg::det(s0,s ,s2);
+				det3[2]=bamg::det(s0,s1,s );}
+			else { 
+				// one of &s1  &s2  &s0 is NULL
+				det3[0]= &s0 ? -1 : bamg::det(s ,s1,s2) ;
+				det3[1]= &s1 ? -1 : bamg::det(s0,s ,s2) ;
+				det3[2]= &s2 ? -1 : bamg::det(s0,s1,s ) ;
+			}
+		}
+
+		if (!det3[0]) izerodet=0,nbzerodet++;
+		if (!det3[1]) izerodet=1,nbzerodet++;
+		if (!det3[2]) izerodet=2,nbzerodet++;
+
+		//if nbzerodet>0, point s is on an egde or on a vertex 
+		if  (nbzerodet>0){ 
+			/*s is on an edge*/
+			if (nbzerodet==1) {
+				iedge = OppositeEdge[izerodet];
+				AdjacentTriangle ta = t->Adj(iedge);
+
+				/*if the point is one the boundary 
+				  add the point in outside part */
+				if (t->det>=0){ // inside triangle
+					if (((Triangle*)ta)->det<0 ) {
+						// add in outside triangle 
+						AddVertex(s,( Triangle *)ta);
+						return;
+					}
+				}
+			}
+			else{
+				_error2_("Cannot add a vertex more than once. Check duplicates");
+			}
+		}
+
+		// remove de MarkUnSwap edge
+		t->SetUnMarkUnSwap(0);
+		t->SetUnMarkUnSwap(1);
+		t->SetUnMarkUnSwap(2);
+
+		tt[0]= t;
+		tt[1]= &triangles[nbt++];
+		tt[2]= &triangles[nbt++];
+
+		if (nbt>maxnbt) _error2_("Not enough triangles");
+
+		*tt[1]=*tt[2]=*t;
+		tt[0]->link=tt[1];
+		tt[1]->link=tt[2]; 
+
+		(*tt[0])(OppositeVertex[0])=&s;
+		(*tt[1])(OppositeVertex[1])=&s;
+		(*tt[2])(OppositeVertex[2])=&s;
+
+		tt[0]->det=det3[0];
+		tt[1]->det=det3[1];
+		tt[2]->det=det3[2];         
+
+		//  update adj des triangles externe 
+		tt[0]->SetAdjAdj(0);
+		tt[1]->SetAdjAdj(1);
+		tt[2]->SetAdjAdj(2);
+		//  update des adj des 3 triangle interne
+		const int i0 = 0;
+		const int i1= NextEdge[i0];
+		const int i2 = PreviousEdge[i0];
+
+		tt[i0]->SetAdj2(i2,tt[i2],i0);
+		tt[i1]->SetAdj2(i0,tt[i0],i1);
+		tt[i2]->SetAdj2(i1,tt[i1],i2);
+
+		tt[0]->SetSingleVertexToTriangleConnectivity();
+		tt[1]->SetSingleVertexToTriangleConnectivity();
+		tt[2]->SetSingleVertexToTriangleConnectivity();
+
+
+		// swap if the point s is on a edge
+		if(izerodet>=0) {
+			int rswap=tt[izerodet]->swap(iedge);
+
+			if (!rswap) {
+				_error2_("swap the point s is on a edge");
+			}
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::BoundAnisotropy{{{*/
+	void  Mesh::BoundAnisotropy(double anisomax,double hminaniso) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/BoundAnisotropy)*/
+
+		long int verbose=0;
+		double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100));
+
+		//display info
+		if (verbose > 1)  _printLine_("   BoundAnisotropy by " << anisomax);
+
+		double h1=1.e30,h2=1e-30;
+		double coef = 1./(anisomax*anisomax);
+		double hn1=1.e30,hn2=1e-30,rnx =1.e-30,rx=0;  
+
+		//loop over all vertices
+		for (int i=0;i<nbv;i++){
+			EigenMetric Vp(vertices[i]);
+			double lmax=Vp.lmax();
+			Vp*=Min(lminaniso,lmax)/lmax;
+			Vp.BoundAniso2(coef);
+			vertices[i].m = Vp;
+
+			//info to be displayed
+			if (verbose>2){
+				h1 =Min(h1,Vp.lmin());
+				h2 =Max(h2,Vp.lmax());
+				hn1=Min(hn1,Vp.lmin());
+				hn2=Max(hn2,Vp.lmax());
+				rx =Max(rx,Vp.Aniso2());
+				rnx= Max(rnx,Vp.Aniso2());
+			}
+		}
+
+		//display info
+		if (verbose>2){
+			_printLine_("      input:  Hmin = " << pow(h2,-0.5)  << ", Hmax = " << pow(h1,-0.5) << ", factor of anisotropy max  = " << pow(rx,0.5));
+			_printLine_("      output: Hmin = " << pow(hn2,-0.5) << ", Hmax = " << pow(hn1,-0.5)<< ", factor of anisotropy max  = " <<pow(rnx,0.5));
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::BuildGeometryFromMesh{{{*/
+	void Mesh::BuildGeometryFromMesh(BamgOpts* bamgopts){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshGeom.cpp/ConsGeometry)*/
+
+		/*Reconstruct Geometry from Mesh*/
+
+		/*Intermediary*/
+		int i,j,k,kk,it,jt;
+		int    verbose=0;
+		double cutoffradian=10*Pi/180;
+
+		/*Recover options*/
+		if (bamgopts){
+			verbose=bamgopts->verbose;
+			cutoffradian=bamgopts->MaxCornerAngle*Pi/180;
+		}
+
+		//display info
+		if (verbose>1) _printLine_("   construction of the geometry from the 2d mesh");
+
+		//check that the mesh is not empty
+		if (nbt<=0 || nbv <=0 ) {
+			_error2_("nbt or nbv is negative (Mesh empty?)");
+		}
+
+		//Gh is the geometry of the mesh (this), initialize MaxCornerAngle
+		if (cutoffradian>=0) Gh.MaxCornerAngle = cutoffradian;
+
+		/*Construction of the edges*/
+
+		//initialize st and edge4
+		SetOfEdges4* edge4= new SetOfEdges4(nbt*3,nbv);
+		long*        st   = new long[nbt*3];
+
+		//initialize st as -1 (chaining algorithm)
+		for (i=0;i<nbt*3;i++) st[i]=-1;
+
+		//build edge4 (chain)
+		for (i=0;i<nbe;i++){
+			edge4->SortAndAdd(GetId(edges[i][0]),GetId(edges[i][1]));
+		}
+		//check that there is no double edge
+		if (nbe !=  edge4->nb()){ 
+			delete [] st;
+			_error2_("Some Double edge in the mesh, the number is " << nbe << ", nbe4=" << edge4->nb()); 
+		}
+		//keep nbe in nbeold
+		long nbeold = nbe;
+
+		//Go through the triangles and ass the edges in edge4 if they are not there yet
+		for (i=0;i<nbt;i++){
+			//3 edges per triangle
+			for  (j=0;j<3;j++) {
+				//Add Edge to edge4 (k=numberofedges in edge4)
+				long k =edge4->SortAndAdd(GetId(triangles[i][VerticesOfTriangularEdge[j][0]]), GetId(triangles[i][VerticesOfTriangularEdge[j][1]]));
+				long invisible = triangles[i].Hidden(j);
+
+				//if st[k] has not been changed yet, add 3*i+j (= vertex position in the index)
+				if(st[k]==-1) st[k]=3*i+j;
+
+				//else st[k]>=0 -> the edge already exist, check
+				else if(st[k]>=0) {
+					//check that it is not an edge on boundary (should not already exist)
+					if (triangles[i].TriangleAdj(j) || triangles[st[k]/3].TriangleAdj((int) (st[k]%3))){
+						_error2_("problem in Geometry reconstruction: an edge on boundary is duplicated (double element?)");
+					}
+					//OK, the element is not on boundary, is belongs to 2 triangles -> build Adjacent triangles list
+					triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
+					if (invisible)  triangles[i].SetHidden(j);
+					// if k < nbe mark the edge as on Boundary (Locked)
+					if (k<nbe) {
+						triangles[i].SetLocked(j);
+					}
+					//set st[k] as negative so that the edge should not be called again
+					st[k]=-2-st[k]; 
+				}
+				//else (see 3 lines above), the edge has been called more than twice: return error
+				else {
+					_printLine_("The edge (" << GetId(triangles[i][VerticesOfTriangularEdge[j][0]]) << "," << GetId(triangles[i][VerticesOfTriangularEdge[j][1]]) << ") belongs to more than 2 triangles (" << k << ")");
+					_printLine_("Edge " << j << " of triangle " << i);
+					_printLine_("Edge " << (-st[k]+2)%3 << " of triangle " << (-st[k]+2)/3);
+					_printLine_("Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3)) << " of triangle " << GetId(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))));
+					_error2_("An edge belongs to more than 2 triangles");
+				}	
+			}
+		}
+
+		//delete edge4
+		long nbedges = edge4->nb(); // the total number of edges 
+		delete edge4; edge4=NULL;
+
+		//display info
+		if(verbose>5) {
+			_printLine_("         info on Mesh:");
+			_printLine_("            - number of vertices    = " << nbv); 
+			_printLine_("            - number of triangles   = " << nbt); 
+			_printLine_("            - number of given edges = " << nbe); 
+			_printLine_("            - number of all edges   = " << nbedges); 
+			_printLine_("            - Euler number 1 - nb of holes = " << nbt-nbedges+nbv); 
+		}
+
+		// check consistency of edge[].adj and geometrical required  vertices
+		k=0; kk=0;
+		for (i=0;i<nbedges;i++){
+			//internal edge
+			if (st[i] <-1) {
+				//get triangle number back
+				it =  (-2-st[i])/3;
+				//get edge position back
+				j  =  (int) ((-2-st[i])%3);
+				Triangle &tt=*triangles[it].TriangleAdj(j);
+				if (triangles[it].color != tt.color|| i < nbeold) k++;
+			}
+			//boundary edge (alone)
+			else if (st[i] >=0) 
+			 kk++;
+		}
+
+		/*Constructions of edges*/
+
+		k += kk;
+		kk=0;
+		if (k) {
+			nbe = k;
+			Edge* edgessave=edges;
+			edges = new Edge[nbe];
+			k =0;
+
+			//display info
+			if(verbose>4) _printLine_("   Construction of the edges " << nbe);
+
+			for (i=0;i<nbedges;i++){ 
+				long  add= -1;
+
+				//internal edge (belongs to two triangles)
+				if (st[i] <-1){ 
+					it =  (-2-st[i])/3;
+					j  =  (int) ((-2-st[i])%3);
+					Triangle & tt = * triangles[it].TriangleAdj(j);
+					if (triangles[it].color !=  tt.color || i < nbeold) add=k++;
+				}
+				//boundary edge
+				else if (st[i] >=0){
+					it = st[i]/3;
+					j  = (int) (st[i]%3);
+					add=k++;
+				}
+				if (add>=0 && add < nbe){
+					edges[add].v[0] = &triangles[it][VerticesOfTriangularEdge[j][0]];
+					edges[add].v[1] = &triangles[it][VerticesOfTriangularEdge[j][1]];
+					edges[add].GeomEdgeHook=NULL; 
+					//if already existed
+					if (i<nbeold){
+						edges[add].ReferenceNumber=edgessave[i].ReferenceNumber; 		      
+						edges[add].GeomEdgeHook=edgessave[i].GeomEdgeHook; //  HACK to get required edges
+						_printLine_("oh no...");
+					}
+					else
+					 edges[add].ReferenceNumber=Min(edges[add].v[0]->GetReferenceNumber(),edges[add].v[1]->GetReferenceNumber());
+				  }
+			}
+
+			//check that we have been through all edges
+			if (k!=nbe){
+				_error2_("problem in edge construction process: k!=nbe (should not happen)");
+			}
+			//delete edgessave
+			if (edgessave) delete [] edgessave;
+		}
+
+		/*Color the vertices*/
+
+		//initialize color of all vertices as 0
+		for (i=0;i<nbv;i++) vertices[i].color =0;
+
+		//go through the edges and add a color to corresponding vertices
+		//(A vertex in 4 edges will have a color 4)
+		for (i=0;i<nbe;i++){
+		 for (j=0;j<2;j++) edges[i].v[j]->color++;
+		}
+
+		//change the color: if a vertex belongs to 2 edges -1, else -2
+		for (i=0;i<nbv;i++) {
+			vertices[i].color=(vertices[i].color ==2)? -1 : -2;
+		}
+
+		/*Build edges[i].adj: adjacency of each edge (if on the same curve)*/
+		for (i=0;i<nbe;i++){
+			for (j=0;j<2;j++){ 
+				//get current vertex
+				BamgVertex* v=edges[i].v[j];
+				//get vertex color (i0)
+				long i0=v->color;
+				long j0;
+
+				//if color<0 (first time), no adjacent edge
+				if(i0<0) edges[i].adj[j]=NULL;
+
+				//if color=-1 (corner),change the vertex color as 2*i+j (position of the vertex in edges)
+				if(i0==-1) v->color=i*2+j;
+
+				//if color>=0 (i and i0 edge are adjacent by the vertex v)
+				else if (i0>=0) {
+					//get position of v in edges back
+					j0 =  i0%2; //column in edges
+					i0 =  i0/2; //line in edges
+
+					//check that we have the correct vertex
+					if (v!=edges[i0 ].v[j0]){
+						_error2_("v!=edges[i0 ].v[j0]: this should not happen as the vertex belongs to this edge");
+					}
+
+					//Add adjacence
+					edges[i ].adj[j ]=edges +i0;
+					edges[i0].adj[j0]=edges +i ;
+
+					//change color to -3
+					v->color = -3;
+				}
+			}
+		}
+
+		/*Reconstruct subdomains info*/
+
+		//check that nbsubdomains is empty
+		if (nbsubdomains){
+			_error2_("nbsubdomains should be 0");
+		}
+		nbsubdomains=0;
+
+		//color the subdomains
+		long* colorT= new long[nbt];
+		Triangle *tt,*t;
+
+		//initialize the color of each triangle as -1
+		for (it=0;it<nbt;it++) colorT[it]=-1;
+
+		//loop over the triangles
+		for (it=0;it<nbt;it++){
+
+			//if the triangle has not been colored yet:
+			if (colorT[it]<0){
+
+				//color = number of subdomains
+				colorT[it]=nbsubdomains;
+
+				//color all the adjacent triangles of T that share a non marked edge
+				int level =1;
+				int kolor=triangles[it].color;
+				st[0]=it; // stack 
+				st[1]=0;
+				k=1;
+				while (level>0){
+					if( (j=st[level]++)<3 ){ 
+						t = &triangles[st[level-1]];
+						tt=t->TriangleAdj((int)j);
+
+						//color the adjacent triangle
+						if ( ! t->Locked(j) && tt && (colorT[jt = GetId(tt)] == -1) && ( tt->color==kolor)) {
+							colorT[jt]=nbsubdomains;
+							st[++level]=jt;
+							st[++level]=0;
+							k++;
+						}
+					}
+					else level-=2;
+				}
+				nbsubdomains++;
+			}
+		}
+		if (verbose> 3) _printLine_("      The Number of sub domain = " << nbsubdomains); 
+
+		//build subdomains
+		long isd;
+		subdomains = new SubDomain[nbsubdomains];
+
+		//initialize subdomains[isd].head as 0
+		for (isd=0;isd<nbsubdomains;isd++) subdomains[isd].head =0;
+		  
+		k=0;
+		for (it=0;it<nbt;it++){
+			for (int j=0;j<3;j++){
+				tt=triangles[it].TriangleAdj(j);
+				if ((!tt || tt->color != triangles[it].color) && !subdomains[isd=colorT[it]].head){
+					subdomains[isd].head = triangles+it;
+					subdomains[isd].ReferenceNumber =  triangles[it].color;
+					subdomains[isd].direction = j; // hack
+					subdomains[isd].edge = 0;
+					k++;
+				}
+			}
+		}
+		//check that we have been through all subdomains
+		if (k!= nbsubdomains){
+			delete [] colorT;
+			_error2_("k!= nbsubdomains");
+		}
+		//delete colorT and st
+		delete [] colorT;
+		delete [] st;
+
+		/*Reconstruct Geometry Gh*/
+
+		//build colorV -1 for all vertex and 0 for the vertices belonging to edges
+		long* colorV = new long[nbv];
+		for (i=0;i<nbv;i++) colorV[i]=-1;
+		for (i=0;i<nbe;i++){
+		 for ( j=0;j<2;j++) colorV[GetId(edges[i][j])]=0;
+		}
+		//number the vertices belonging to edges
+		k=0;
+		for (i=0;i<nbv;i++){
+		 if(!colorV[i]) colorV[i]=k++;
+		}
+
+		//Build Gh
+		Gh.nbv=k;
+		Gh.nbe = nbe;
+		Gh.vertices = new GeomVertex[k];
+		Gh.edges = new GeomEdge[nbe];
+		Gh.nbsubdomains = nbsubdomains;
+		Gh.subdomains = new GeomSubDomain[nbsubdomains];
+		if (verbose>3) _printLine_("   number of vertices = " << Gh.nbv << "\n   number of edges = " << Gh.nbe);
+		NbVerticesOnGeomVertex = Gh.nbv;
+		VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+		NbVerticesOnGeomEdge =0;
+		VerticesOnGeomEdge =0;
+
+		//Build VertexOnGeom
+		for (i=0;i<nbv;i++){
+			if((j=colorV[i])>=0){
+				BamgVertex & v = Gh.vertices[j];
+				v = vertices[i];
+				v.color =0;
+				VerticesOnGeomVertex[j] = VertexOnGeom(vertices[i], Gh.vertices[j]);
+			}
+		}
+
+		//Buid pmin and pmax of Gh (extrema coordinates)
+		Gh.pmin =  Gh.vertices[0].r;
+		Gh.pmax =  Gh.vertices[0].r;
+		// recherche des extrema des vertices pmin,pmax
+		for (i=0;i<Gh.nbv;i++) {
+			Gh.pmin.x = Min(Gh.pmin.x,Gh.vertices[i].r.x);
+			Gh.pmin.y = Min(Gh.pmin.y,Gh.vertices[i].r.y);
+			Gh.pmax.x = Max(Gh.pmax.x,Gh.vertices[i].r.x);
+			Gh.pmax.y = Max(Gh.pmax.y,Gh.vertices[i].r.y);
+		}
+		R2 DD05 = (Gh.pmax-Gh.pmin)*0.05;
+		Gh.pmin -=  DD05;
+		Gh.pmax +=  DD05;
+
+		//Build Gh.coefIcoor
+		Gh.coefIcoor= (MaxICoor)/(Max(Gh.pmax.x-Gh.pmin.x,Gh.pmax.y-Gh.pmin.y));
+		if (Gh.coefIcoor<=0){
+			delete [] colorV;
+			_error2_("Gh.coefIcoor<=0 in infered Geometry (this should not happen)");
+		}
+
+		/*Build Gh.edges*/
+
+		//initialize len as 0
+		double * len = new double[Gh.nbv];
+		for(i=0;i<Gh.nbv;i++) len[i]=0;
+
+		//initialize edge4 again
+		edge4= new SetOfEdges4(nbe,nbv);  
+		double hmin = HUGE_VAL;
+		int kreq=0;
+		for (i=0;i<nbe;i++){
+
+			long i0 = GetId(edges[i][0]);
+			long i1 = GetId(edges[i][1]);
+			long j0 = colorV[i0];
+			long j1 = colorV[i1];
+
+			Gh.edges[i].v[0] = Gh.vertices +  j0;
+			Gh.edges[i].v[1] = Gh.vertices +  j1;
+
+			Gh.edges[i].type = 0;
+
+			Gh.edges[i].tg[0]=R2();
+			Gh.edges[i].tg[1]=R2();
+
+			bool required= edges[i].GeomEdgeHook; 
+			if(required) kreq++;
+			edges[i].GeomEdgeHook =  Gh.edges + i;
+			if(required){
+				Gh.edges[i].v[0]->SetRequired();
+				Gh.edges[i].v[1]->SetRequired();
+				Gh.edges[i].SetRequired();
+			}
+
+			R2 x12 = Gh.vertices[j0].r-Gh.vertices[j1].r;
+			double l12=Norme2(x12);        
+			hmin = Min(hmin,l12);
+
+			Gh.vertices[j1].color++;
+			Gh.vertices[j0].color++;
+
+			len[j0]+= l12;
+			len[j1] += l12;
+			hmin = Min(hmin,l12);
+			Gh.edges[i].ReferenceNumber  = edges[i].ReferenceNumber;
+
+			k = edge4->SortAndAdd(i0,i1);
+			if (k != i){
+				delete [] len;
+				delete [] colorV;
+				_error2_("problem in Edge4 construction: k != i");
+			}
+		}
+
+		//Build metric for all vertices of Gh
+		for (i=0;i<Gh.nbv;i++){
+		 if (Gh.vertices[i].color > 0) 
+		  Gh.vertices[i].m=  Metric(len[i] /(double) Gh.vertices[i].color);
+		 else 
+		  Gh.vertices[i].m=  Metric(hmin);
+		}
+		//delete len
+		delete [] len;
+
+		//Build Gh.subdomains
+		for (i=0;i<nbsubdomains;i++){
+			it = GetId(subdomains[i].head);
+			j = subdomains[i].direction;
+			long i0 = GetId(triangles[it][VerticesOfTriangularEdge[j][0]]);
+			long i1 = GetId(triangles[it][VerticesOfTriangularEdge[j][1]]);
+			k = edge4->SortAndFind(i0,i1);
+			if(k>=0){
+				subdomains[i].direction = (vertices + i0 == edges[k].v[0]) ? 1 : -1;
+				subdomains[i].edge = edges+k;
+				Gh.subdomains[i].edge = Gh.edges + k;
+				Gh.subdomains[i].direction  =  subdomains[i].direction;
+				Gh.subdomains[i].ReferenceNumber =  subdomains[i].ReferenceNumber;
+			}
+			else
+			 _error2_("%i should be >=0");
+		  }
+
+		delete edge4;
+		delete [] colorV;
+
+		//unset adj
+		for (i=0;i<nbt;i++){
+			for ( j=0;j<3;j++){
+				triangles[i].SetAdj2(j,0,triangles[i].GetAllflag(j));
+			}
+		}
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::BuildMetric0 (double P2 projection){{{*/
+	void Mesh::BuildMetric0(BamgOpts* bamgopts){
+
+		/*Options*/
+		double* s=NULL;
+		long    nbsol;
+		int     verbose;
+
+		int   i,j,k,iA,iB,iC;
+		int   iv;
+
+		/*Recover options*/
+		verbose=bamgopts->verbose;
+
+		/*Get and process fields*/
+		s=bamgopts->field;
+		nbsol=bamgopts->fieldSize[1];
+
+		/*Check size*/
+		if (bamgopts->fieldSize[0] != nbv) _error2_("'field' should have " << nbv << " rows");
+
+		//initialization of some variables
+		double* ss=(double*)s;
+		double  sA,sB,sC;
+		double*  detT = new double[nbt];
+		double*  sumareas = new double[nbv];
+		double*  alpha= new double[nbt*3];
+		double*  beta = new double[nbt*3];
+		double*  dx_elem    = new double[nbt];
+		double*  dy_elem    = new double[nbt];
+		double*  dx_vertex  = new double[nbv];
+		double*  dy_vertex  = new double[nbv];
+		double*  dxdx_elem  = new double[nbt];
+		double*  dxdy_elem  = new double[nbt];
+		double*  dydy_elem  = new double[nbt];
+		double*  dxdx_vertex= new double[nbv];
+		double*  dxdy_vertex= new double[nbv];
+		double*  dydy_vertex= new double[nbv];
+
+		//display infos
+		if(verbose>1) {
+			_printLine_("   Construction of Metric: number of field: " << nbsol << " (nbt=" << nbt << ", nbv=" << nbv << ")");
+		}
+
+		//first, build the chains that will be used for the Hessian computation, as weel as the area of each element
+		int* head_s=NULL;
+		head_s=xNew<int>(nbv);
+		int* next_p=NULL;
+		next_p=xNew<int>(3*nbt);
+		int  p=0;
+		//initialization
+		for(i=0;i<nbv;i++){
+			sumareas[i]=0;
+			head_s[i]=-1;
+		}
+		for(i=0;i<nbt;i++){
+
+			//lopp over the real triangles (no boundary elements)
+			if(triangles[i].link){ 
+
+				//get current triangle t
+				const Triangle &t=triangles[i];
+
+				// coor of 3 vertices 
+				R2 A=t[0];
+				R2 B=t[1];
+				R2 C=t[2];
+
+				//compute triangle determinant (2*Area)
+				double dett = bamg::Area2(A,B,C);
+				detT[i]=dett;
+
+				/*The nodal functions are such that for a vertex A:
+				 *    N_A(x,y)=alphaA x + beta_A y +gamma_A
+				 *    N_A(A) = 1,   N_A(B) = 0,   N_A(C) = 0
+				 * solving this system of equation (determinant = 2Area(T) != 0 if A,B and C are not inlined)
+				 * leads to:
+				 *    N_A = (xB yC - xC yB + x(yB-yC) +y(xC-xB))/(2*Area(T))
+				 * and this gives:
+				 *    alpha_A = (yB-yC)/(2*Area(T))*/
+				alpha[i*3+0]=(B.y-C.y)/dett;
+				alpha[i*3+1]=(C.y-A.y)/dett;
+				alpha[i*3+2]=(A.y-B.y)/dett;
+				beta[ i*3+0]=(C.x-B.x)/dett;
+				beta[ i*3+1]=(A.x-C.x)/dett;
+				beta[ i*3+2]=(B.x-A.x)/dett;
+
+				//compute chains
+				for(j=0;j<3;j++){
+					k=GetId(triangles[i][j]);
+					next_p[p]=head_s[k];
+					head_s[k]=p++;
+
+					//add area to sumareas
+					sumareas[k]+=dett;
+				}
+
+			}
+		}
+
+		//for all Solutions
+		for (int nusol=0;nusol<nbsol;nusol++) {
+			double smin=ss[nusol],smax=ss[nusol];
+
+			//get min(s), max(s) and initialize Hessian (dxdx,dxdy,dydy)
+			for ( iv=0,k=0; iv<nbv; iv++){
+				smin=Min(smin,ss[iv*nbsol+nusol]);
+				smax=Max(smax,ss[iv*nbsol+nusol]);
+			}
+			double sdelta=smax-smin;
+			double absmax=Max(Abs(smin),Abs(smax));
+
+			//display info
+			if(verbose>2) _printLine_("      Solution " << nusol << ", Min = " << smin << ", Max = " << smax << ", Delta = " << sdelta);
+
+			//skip constant field
+			if (sdelta < 1.0e-10*Max(absmax,1e-20)){
+				_printLine_("      Solution " << nusol << " is constant, skipping...");
+				continue;
+			}
+
+			//initialize the hessian and gradient matrices
+			for ( iv=0,k=0; iv<nbv; iv++) dxdx_vertex[iv]=dxdy_vertex[iv]=dydy_vertex[iv]=dx_vertex[iv]=dy_vertex[iv]=0;
+
+			//1: Compute gradient for each element (exact)
+			for (i=0;i<nbt;i++){
+				if(triangles[i].link){
+					// number of the 3 vertices
+					iA = GetId(triangles[i][0]);
+					iB = GetId(triangles[i][1]);
+					iC = GetId(triangles[i][2]);
+
+					// value of the P1 fonction on 3 vertices 
+					sA = ss[iA*nbsol+nusol];
+					sB = ss[iB*nbsol+nusol];
+					sC = ss[iC*nbsol+nusol];
+
+					//gradient = (sum alpha_i s_i, sum_i beta_i s_i)
+					dx_elem[i]=sA*alpha[3*i+0]+sB*alpha[3*i+1]+sC*alpha[3*i+2];
+					dy_elem[i]=sA*beta[ 3*i+0]+sB*beta[ 3*i+1]+sC*beta[ 3*i+2];
+				}
+			}
+
+			//2: then compute a gradient for each vertex using a P2 projection
+			for(i=0;i<nbv;i++){
+				for(p=head_s[i];p!=-1;p=next_p[p]){
+					//Get triangle number
+					k=(long)(p/3);
+					dx_vertex[i]+=dx_elem[k]*detT[k]/sumareas[i];
+					dy_vertex[i]+=dy_elem[k]*detT[k]/sumareas[i];
+				}
+			}
+
+			//3: compute Hessian matrix on each element
+			for (i=0;i<nbt;i++){
+				if(triangles[i].link){
+					// number of the 3 vertices
+					iA = GetId(triangles[i][0]);
+					iB = GetId(triangles[i][1]);
+					iC = GetId(triangles[i][2]);
+
+					//Hessian
+					dxdx_elem[i]=dx_vertex[iA]*alpha[3*i+0]+dx_vertex[iB]*alpha[3*i+1]+dx_vertex[iC]*alpha[3*i+2];
+					dxdy_elem[i]=dy_vertex[iA]*alpha[3*i+0]+dy_vertex[iB]*alpha[3*i+1]+dy_vertex[iC]*alpha[3*i+2];
+					dydy_elem[i]=dy_vertex[iA]*beta[3*i+0]+dy_vertex[iB]*beta[3*i+1]+dy_vertex[iC]*beta[3*i+2];
+				}
+			}
+
+			//4: finaly compute Hessian on each vertex using the second P2 projection
+			for(i=0;i<nbv;i++){
+				for(p=head_s[i];p!=-1;p=next_p[p]){
+					//Get triangle number
+					k=(long)(p/3);
+					dxdx_vertex[i]+=dxdx_elem[k]*detT[k]/sumareas[i];
+					dxdy_vertex[i]+=dxdy_elem[k]*detT[k]/sumareas[i];
+					dydy_vertex[i]+=dydy_elem[k]*detT[k]/sumareas[i];
+				}
+			}
+
+			/*Compute Metric from Hessian*/
+			for ( iv=0;iv<nbv;iv++){
+				vertices[iv].MetricFromHessian(dxdx_vertex[iv],dxdy_vertex[iv],dydy_vertex[iv],smin,smax,ss[iv*nbsol+nusol],bamgopts->err[nusol],bamgopts);
+			}
+
+		}//for all solutions
+
+		//clean up
+		xDelete<int>(head_s);
+		xDelete<int>(next_p);
+		delete [] detT;
+		delete [] alpha;
+		delete [] beta;
+		delete [] sumareas;
+		delete [] dx_elem;
+		delete [] dy_elem;
+		delete [] dx_vertex;
+		delete [] dy_vertex;
+		delete [] dxdx_elem;
+		delete [] dxdy_elem;
+		delete [] dydy_elem;
+		delete [] dxdx_vertex;
+		delete [] dxdy_vertex;
+		delete [] dydy_vertex;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::BuildMetric1 (Green formula){{{*/
+	void Mesh::BuildMetric1(BamgOpts* bamgopts){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/IntersectConsMetric)*/
+
+		/*Options*/
+		double* s=NULL;
+		long nbsol;
+		int NbJacobi;
+		int verbose;
+
+		/*Recover options*/
+		verbose=bamgopts->verbose;
+		NbJacobi=bamgopts->nbjacobi;
+
+		/*Get and process fields*/
+		s=bamgopts->field;
+		nbsol=bamgopts->fieldSize[1];
+
+		/*Check size*/
+		if (bamgopts->fieldSize[0] != nbv) _error2_("'field' should have " << nbv << " rows");
+
+		//initialization of some variables
+		long    i,k,iA,iB,iC,iv;
+		R2      O(0,0);
+		double* ss=(double*)s;
+		double  sA,sB,sC;
+		double*  detT = new double[nbt];
+		double*  Mmass= new double[nbv];
+		double*  Mmassxx= new double[nbv];
+		double*  dxdx= new double[nbv];
+		double*  dxdy= new double[nbv];
+		double*  dydy= new double[nbv];
+		double*  workT= new double[nbt];
+		double*  workV= new double[nbv];
+		int*    OnBoundary = new int[nbv];
+
+		//display infos
+		if(verbose>1) {
+			_printLine_("   Construction of Metric: number of field: " << nbsol << " (nbt=" << nbt << ", nbv=" << nbv << ")");
+		}
+
+		//initialize Mmass, OnBoundary and Massxx by zero
+		for (iv=0;iv<nbv;iv++){
+			Mmass[iv]=0;
+			OnBoundary[iv]=0;
+			Mmassxx[iv]=0;
+		}
+
+		//Build detT Mmas Mmassxx workT and OnBoundary
+		for (i=0;i<nbt;i++){ 
+
+			//lopp over the real triangles (no boundary elements)
+			if(triangles[i].link){ 
+
+				//get current triangle t
+				const Triangle &t=triangles[i];
+
+				// coor of 3 vertices 
+				R2 A=t[0];
+				R2 B=t[1];
+				R2 C=t[2];
+
+				// number of the 3 vertices
+				iA = GetId(t[0]);
+				iB = GetId(t[1]);
+				iC = GetId(t[2]);
+
+				//compute triangle determinant (2*Area)
+				double dett = bamg::Area2(A,B,C);
+				detT[i]=dett;
+				dett /= 6;
+
+				// construction of OnBoundary (flag=1 if on boundary, else 0)
+				int nbb=0;
+				for(int j=0;j<3;j++){
+					//get adjacent triangle
+					Triangle *ta=t.Adj(j);
+					//if there is no adjacent triangle, the edge of the triangle t is on boundary
+					if ( !ta || !ta->link){
+						//mark the two vertices of the edge as OnBoundary
+						OnBoundary[GetId(t[VerticesOfTriangularEdge[j][0]])]=1;
+						OnBoundary[GetId(t[VerticesOfTriangularEdge[j][1]])]=1;
+						nbb++;
+					}
+				}
+
+				//number of vertices on boundary for current triangle t
+				workT[i] = nbb;
+
+				//Build Mmass Mmass[i] = Mmass[i] + Area/3
+				Mmass[iA] += dett;
+				Mmass[iB] += dett;
+				Mmass[iC] += dett;
+
+				//Build Massxx = Mmass
+				Mmassxx[iA] += dett;
+				Mmassxx[iB] += dett;
+				Mmassxx[iC] += dett;
+			}
+
+			//else: the triangle is a boundary triangle -> workT=-1
+			else workT[i]=-1;
+		}
+
+		//for all Solution  
+		for (int nusol=0;nusol<nbsol;nusol++) {
+
+			double smin=ss[nusol],smax=ss[nusol];
+			double h1=1.e30,h2=1e-30,rx=0;
+			double hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+
+			//get min(s), max(s) and initialize Hessian (dxdx,dxdy,dydy)
+			for ( iv=0,k=0; iv<nbv; iv++ ){
+				dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+				smin=Min(smin,ss[iv*nbsol+nusol]);
+				smax=Max(smax,ss[iv*nbsol+nusol]);
+			}
+			double sdelta=smax-smin;
+			double absmax=Max(Abs(smin),Abs(smax));
+
+			//display info
+			if(verbose>2) _printLine_("      Solution " << nusol << ", Min = " << smin << ", Max = " << smax << ", Delta = " << sdelta << ", number of fields = " << nbsol);
+
+			//skip constant field
+			if (sdelta < 1.0e-10*Max(absmax,1e-20) ){
+				if (verbose>2) _printLine_("      Solution " << nusol << " is constant, skipping...");
+				continue;
+			}
+
+			//pointer toward ss that is also a pointer toward s (solutions)
+			double* sf=ss; 
+
+				//initialize the hessian matrix
+				for ( iv=0,k=0; iv<nbv; iv++) dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+
+				//loop over the triangles
+				for (i=0;i<nbt;i++){
+
+					//for real all triangles 
+					if(triangles[i].link){
+
+						// coor of 3 vertices 
+						R2 A=triangles[i][0];
+						R2 B=triangles[i][1];
+						R2 C=triangles[i][2];
+
+						//warning: the normal is internal and the size is the length of the edge
+						R2 nAB = Orthogonal(B-A);
+						R2 nBC = Orthogonal(C-B);
+						R2 nCA = Orthogonal(A-C);
+						//note that :  nAB + nBC + nCA == 0 
+
+						// number of the 3 vertices
+						iA = GetId(triangles[i][0]);
+						iB = GetId(triangles[i][1]);
+						iC = GetId(triangles[i][2]);
+
+						// for the test of  boundary edge
+						// the 3 adj triangles 
+						Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]);
+						Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]);
+						Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]);
+
+						// value of the P1 fonction on 3 vertices 
+						sA = ss[iA*nbsol+nusol];
+						sB = ss[iB*nbsol+nusol];
+						sC = ss[iC*nbsol+nusol];
+
+						/*The nodal functions are such that for a vertex A:
+						  N_A(x,y)=alphaA x + beta_A y +gamma_A
+						  N_A(A) = 1,   N_A(B) = 0,   N_A(C) = 0
+						  solving this system of equation (determinant = 2Area(T) != 0 if A,B and C are not inlined)
+						  leads to:
+						  N_A = (xB yC - xC yB + x(yB-yC) +y(xC-xB))/(2*Area(T))
+						  and this gives:
+						  alpha_A = (yB-yC)/(2*Area(T))
+						  beta_A = (xC-xB)/(2*Area(T))
+						  and therefore:
+						  grad N_A = nA / detT
+						  for an interpolation of a solution s:
+						  grad(s) = s * sum_{i=A,B,C} grad(N_i) */
+
+						R2 Grads=(nAB*sC+nBC*sA+nCA*sB)/detT[i];
+
+						//Use Green to compute Hessian Matrix
+
+						// if edge on boundary no contribution  => normal = 0
+						if ( !tBC || !tBC->link ) nBC=O;
+						if ( !tCA || !tCA->link ) nCA=O;
+						if ( !tAB || !tAB->link ) nAB=O;
+
+						// remark we forgot a 1/2 because
+						//       int_{edge} w_i = 1/2 if i is in edge 
+						//                         0  if not
+						// if we don't take the  boundary 
+						dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
+						dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x;
+						dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x;
+
+						//warning optimization (1) the division by 2 is done on the metric construction
+						dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ;
+						dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ;
+						dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ; 
+
+						dydy[iA] += ( nCA.y + nAB.y ) *Grads.y;
+						dydy[iB] += ( nAB.y + nBC.y ) *Grads.y;
+						dydy[iC] += ( nBC.y + nCA.y ) *Grads.y;
+
+					} // for real all triangles 
+				}
+
+				long kk=0;
+				for ( iv=0,k=0 ; iv<nbv; iv++){
+					if(Mmassxx[iv]>0){
+						dxdx[iv] /= 2*Mmassxx[iv];
+						// warning optimization (1) on term dxdy[iv]*ci/2 
+						dxdy[iv] /= 4*Mmassxx[iv];
+						dydy[iv] /= 2*Mmassxx[iv];
+						// Compute the matrix with abs(eigen value)
+						Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
+						EigenMetric Vp(M);
+						Vp.Abs();
+						M = Vp;
+						dxdx[iv] = M.a11;
+						dxdy[iv] = M.a21;
+						dydy[iv] = M.a22;
+					}
+					else kk++;
+				}
+
+				// correction of second derivative
+				// by a laplacien
+				double* d2[3] = {dxdx, dxdy, dydy};
+				double* dd;
+				for (int xy = 0;xy<3;xy++) {
+					dd = d2[xy];
+					// do leat 2 iteration for boundary problem
+					for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++){
+						for (i=0;i<nbt;i++) 
+						 if(triangles[i].link){// the real triangles 
+							 // number of the 3 vertices
+							 iA = GetId(triangles[i][0]);
+							 iB = GetId(triangles[i][1]);
+							 iC = GetId(triangles[i][2]);
+							 double cc=3;
+							 if(ijacobi==0)
+							  cc = Max((double) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.);
+							 workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc;
+						 }
+						for (iv=0;iv<nbv;iv++) workV[iv]=0;
+
+						for (i=0;i<nbt;i++){ 
+							if(triangles[i].link){ // the real triangles 
+								// number of the 3 vertices
+								iA = GetId(triangles[i][0]);
+								iB = GetId(triangles[i][1]);
+								iC = GetId(triangles[i][2]);
+								double cc =  workT[i]*detT[i];
+								workV[iA] += cc;
+								workV[iB] += cc;
+								workV[iC] += cc;
+							}
+						}
+
+						for (iv=0;iv<nbv;iv++){
+							if( ijacobi<NbJacobi || OnBoundary[iv]){
+								dd[iv] = workV[iv]/(Mmass[iv]*6);
+							}
+						}
+					}
+				}
+
+				/*Compute Metric from Hessian*/
+				for ( iv=0;iv<nbv;iv++){
+					vertices[iv].MetricFromHessian(dxdx[iv],dxdy[iv],dydy[iv],smin,smax,ss[iv*nbsol+nusol],bamgopts->err[nusol],bamgopts);
+				}
+
+		}// end for all solution 
+
+		delete [] detT;
+		delete [] Mmass;
+		delete [] dxdx;
+		delete [] dxdy;
+		delete [] dydy;
+		delete []  workT;
+		delete [] workV;
+		delete [] Mmassxx;
+		delete []  OnBoundary;
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::CrackMesh{{{*/
+	void Mesh::CrackMesh(BamgOpts* bamgopts) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/CrackMesh)*/
+
+		/*Intermediary*/
+		int i,j,k,num,count;
+		int i1,i2;
+		int j1,j2;
+
+		/*Options*/
+		int verbose=bamgopts->verbose;
+
+		//  computed the number of cracked edge
+		for (k=i=0;i<nbe;i++){
+			if(edges[i].GeomEdgeHook->Cracked()) k++;
+		}
+
+		//Return if no edge is cracked
+		if(k==0) return;
+		if (verbose>4) _printLine_("      number of Cracked Edges = " << k);
+
+		//Initialize Cracked edge
+		NbCrackedEdges=k;
+		CrackedEdges=new CrackedEdge[k];
+
+		//Compute number of Cracked Vertices
+		k=0;
+		NbCrackedVertices=0;
+
+		int* splitvertex=new int[nbv];
+		for (i=0;i<nbv;i++) splitvertex[i]=0;
+
+		for (i=0;i<nbe;i++){
+			if(edges[i].GeomEdgeHook->Cracked()){
+
+				//Fill edges fields of CrackedEdges
+				CrackedEdges[k  ].E =edges[i].GeomEdgeHook;
+				CrackedEdges[k++].e1=&edges[i];
+
+				//Get number of the two vertices on the edge
+				i1=GetId(edges[i][0]);
+				i2=GetId(edges[i][1]);
+				_assert_(i1>=0 && i1<nbv && i2>=0 && i2<nbv);
+				splitvertex[i1]++;
+				splitvertex[i2]++;
+
+				//If the vertex has already been flagged once, it is a cracked vertex (tip otherwise)
+				if (splitvertex[i1]==2) NbCrackedVertices++;
+				if (splitvertex[i2]==2) NbCrackedVertices++;
+
+				//The vertex cannot be marked more than twice
+				if (splitvertex[i1]==3 || splitvertex[i2]==3){
+					delete [] splitvertex;
+					_error2_("Crossing rifts not supported yet");
+				}
+			}
+		}
+		_assert_(k==NbCrackedEdges);
+
+		//Add new vertices
+		if (verbose>4) _printLine_("      number of Cracked Vertices = " << NbCrackedVertices);
+		if (NbCrackedVertices){
+			CrackedVertices=xNew<long>(2*NbCrackedVertices);
+			num=0;
+			for (i=0;i<nbv;i++){
+				if (splitvertex[i]==2){
+					CrackedVertices[num*2+0]=i;      //index of first vertex
+					CrackedVertices[num*2+1]=nbv+num;//index of new vertex
+					num++;
+				}
+			}
+			_assert_(num==NbCrackedVertices);
+		}
+		delete [] splitvertex;
+
+		//Now, find the triangles that hold a cracked edge
+		CreateSingleVertexToTriangleConnectivity();
+
+		long* Edgeflags=new long[NbCrackedEdges];
+		for(i=0;i<NbCrackedEdges;i++) Edgeflags[i]=0;
+
+		for(i=0;i<NbCrackedEdges;i++){
+			//Get the numbers of the 2 vertices of the crren cracked edge
+			i1=GetId((*CrackedEdges[i].e1)[0]);
+			i2=GetId((*CrackedEdges[i].e1)[1]);
+
+			//find a triangle holding the vertex i1 (first vertex of the ith cracked edge)
+			Triangle* tbegin=vertices[i1].t;
+			k=vertices[i1].IndexInTriangle;//local number of i in triangle tbegin
+			_assert_(GetId((*tbegin)[k])==GetId(vertices[i1]));
+
+			//Now, we are going to go through the adjacent triangle that hold i1 till
+			//we find one that has the cracked edge
+			AdjacentTriangle ta(tbegin,EdgesVertexTriangle[k][0]);
+			count=0;
+			do {
+				for(j=0;j<3;j++){
+					//Find the position of i1 in the triangle index
+					if (GetId((*ta.t)[j])==i1){
+						j1=j;
+						break;
+					}
+				}
+				for(j=0;j<3;j++){
+					//Check wether i2 is also in the triangle index
+					if (GetId((*ta.t)[j])==i2){
+						j2=j;
+						//Invert j1 and j2 if necessary
+						if ((j1+1)%3==j2){
+							int j3=j1;
+							j1=j2;
+							j2=j3;
+						}
+						if (Edgeflags[i]==0){
+							//first element
+							CrackedEdges[i].a=ta.t;
+							CrackedEdges[i].length=Norme2((*ta.t)[j1].r-(*ta.t)[j2].r);
+							CrackedEdges[i].normal=Orthogonal((*ta.t)[j1].r-(*ta.t)[j2].r);
+						}
+						else{
+							//Second element -> to renumber
+							CrackedEdges[i].b=ta.t;
+							CrackedEdges[i].length=Norme2((*ta.t)[j1].r-(*ta.t)[j2].r);
+							CrackedEdges[i].normal=Orthogonal((*ta.t)[j1].r-(*ta.t)[j2].r);
+						}
+						Edgeflags[i]++;
+						break;
+					}
+				}
+				//_printLine_(element_renu[GetId(ta.t)] << " -> " << GetId((*ta.t)[0])+1 << " " << GetId((*ta.t)[1])+1 << " " << GetId((*ta.t)[2])+1 << ", edge [" << i1 << "->" << j1 << " " << i2 << "->" << j2 << "]");
+				ta = Next(ta).Adj(); 
+				if (count++>50) _error2_("Maximum number of iteration exceeded");
+			}while ((tbegin != ta)); 
+		}
+
+		//Check EdgeFlag
+		for(i=0;i<NbCrackedEdges;i++){
+			if (Edgeflags[i]!=2){
+				_error2_("A problem occured: at least one crack edge (number " << i+1 << ") does not belong to 2 elements");
+			}
+		}
+		delete [] Edgeflags;
+
+		//Reset BamgVertex to On
+		SetVertexFieldOn();
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Echo{{{*/
+	void Mesh::Echo(void) {
+
+		int i;
+
+		_printLine_("Mesh Echo:");
+		_printLine_("   nbv = " << nbv);
+		_printLine_("   nbt = " << nbt);
+		_printLine_("   nbe = " << nbe);
+		_printLine_("   nbq = " << nbq);
+		_printLine_("   index:");
+		for (i=0;i<nbt;i++){
+			_printLine_("   " << setw(4) << i+1 << ": [" 
+						<< setw(4) << (((BamgVertex *)triangles[i](0))?GetId(triangles[i][0])+1:0) << " " 
+						<< setw(4) << (((BamgVertex *)triangles[i](0))?GetId(triangles[i][1])+1:0) << " " 
+						<< setw(4) << (((BamgVertex *)triangles[i](0))?GetId(triangles[i][2])+1:0) << "]");
+		}
+		_printLine_("   coordinates:");
+		for (i=0;i<nbv;i++){
+			_printLine_("   " << setw(4) << i+1 << ": [" << vertices[i].r.x << " " << vertices[i].r.y << "]");
+		}
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::ForceBoundary{{{*/
+		void Mesh::ForceBoundary() {
+			/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ForceBoundary)*/
+
+			long int verbose=2;
+			int k=0;
+			int nbfe=0,nbswp=0,Nbswap=0;
+
+			//display
+			if (verbose > 2) _printLine_("   ForceBoundary  nb of edge: " << nbe);
+
+			//check that there is no triangle with 0 determinant
+			for (int t = 0; t < nbt; t++){
+				if (!triangles[t].det) k++;
+			}
+			if (k!=0) {
+				_error2_("there is " << k << " triangles of mes = 0");
+			}
+
+			//Force Edges
+			AdjacentTriangle ta(0,0);
+			for (int i = 0; i < nbe; i++){
+
+				//Force edge i
+				nbswp =  ForceEdge(edges[i][0],edges[i][1],ta);
+				if (nbswp<0) k++;
+				else Nbswap += nbswp;
+
+				if (nbswp) nbfe++;
+				if ( nbswp < 0 && k < 5){
+					_error2_("Missing Edge " << i << ", v0=" << GetId(edges[i][0]) << ",v1=" << GetId(edges[i][1]));
+				}
+			}
+
+			if (k!=0) {
+				_error2_("There are " << k << " lost edges, the boundary might be crossing");
+			}
+			for (int j=0;j<nbv;j++){
+				Nbswap +=  vertices[j].Optim(1,0);
+			}
+			if (verbose > 3) _printLine_("      number of inforced edge = " << nbfe << ", number of swap= " << Nbswap); 
+		}
+	/*}}}*/
+	/*FUNCTION Mesh::FindSubDomain{{{*/
+	void Mesh::FindSubDomain(int OutSide) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FindSubDomain)*/
+
+		long int verbose=0;
+
+		if (verbose >2){
+			if (OutSide) _printLine_("   Find all external sub-domain"); 
+			else _printLine_("   Find all internal sub-domain");
+		  }
+		short * HeapArete = new short[nbt];
+		Triangle  **  HeapTriangle = new Triangle*  [nbt];
+		Triangle *t,*t1;
+		long k,it;
+
+		for (int itt=0;itt<nbt;itt++) 
+		 triangles[itt].link=0; // par defaut pas de couleur
+
+		long  NbSubDomTot =0;
+		for ( it=0;it<nbt;it++)  { 
+			if ( ! triangles[it].link  ) {
+				t = triangles + it;
+				NbSubDomTot++;; // new composante connexe
+				long i = 0; // niveau de la pile 
+				t->link = t ; // sd forme d'un triangle cicular link
+
+				HeapTriangle[i] =t ; 
+				HeapArete[i] = 3;
+
+				while (i >= 0) // boucle sur la pile
+				  { while ( HeapArete[i]--) // boucle sur les 3 aretes 
+					  { 
+						int na =  HeapArete[i];
+						Triangle * tc =  HeapTriangle[i]; // triangle courant
+						if( ! tc->Locked(na)) // arete non frontiere
+						  {
+							Triangle * ta = tc->TriangleAdj(na) ; // næ triangle adjacent
+							if (ta->link == 0 ) // non deja chainer => on enpile
+							  { 
+								i++;
+								ta->link = t->link ;  // on chaine les triangles
+								t->link = ta ;  // d'un meme sous domaine          
+								HeapArete[i] = 3; // pour les 3 triangles adjacents
+								HeapTriangle[i] = ta;
+							  }}
+					  } // deplie fin de boucle sur les 3 adjacences
+					i--;
+				  }          
+			}      
+		}
+
+		// supression de tous les sous domaine infini <=>  contient le sommet NULL
+		it =0;
+		nbtout = 0;
+		while (it<nbt) {
+			if (triangles[it].link) 
+			  { 
+				if (!( triangles[it](0) &&  triangles[it](1) &&  triangles[it](2) )) 
+				  {
+					// infini triangle 
+					NbSubDomTot --;
+					t=&triangles[it];
+					nbtout--;  // on fait un coup de trop. 
+					while  (t){
+						nbtout++;
+						t1=t;
+						t=t->link;
+						t1->link=0;
+					}
+				  }
+			  }   
+			it++;} // end while (it<nbt)
+			if (nbt == nbtout ||  !NbSubDomTot) {
+				delete [] HeapArete;
+				_error2_("The boundary is not close: all triangles are outside");
+			}
+
+			delete [] HeapArete;
+			delete [] HeapTriangle;
+
+
+			if (OutSide|| !Gh.subdomains || !Gh.nbsubdomains ) 
+			  { // No geom sub domain
+				long i;
+				if (subdomains) delete [] subdomains;
+				subdomains = new SubDomain[ NbSubDomTot];
+				nbsubdomains=  NbSubDomTot;
+				for ( i=0;i<nbsubdomains;i++) {
+					subdomains[i].head=NULL;
+					subdomains[i].ReferenceNumber=i+1;
+				}
+				long * mark = new long[nbt];
+				for (it=0;it<nbt;it++)
+				 mark[it]=triangles[it].link ? -1 : -2;
+
+				it =0;
+				k = 0;
+				while (it<nbt) {
+					if (mark[it] == -1) {
+						t1 = & triangles[it];
+						t = t1->link;
+						mark[it]=k;
+						subdomains[k].head = t1;
+						do {
+							mark[GetId(t)]=k;
+							t=t->link;
+						} while (t!=t1);
+						mark[it]=k++;}
+						//    else if(mark[it] == -2 ) triangles[it].Draw(999);
+						it++;} // end white (it<nbt)
+						if (k!=nbsubdomains){
+							delete [] mark;
+							_error2_("k!=nbsubdomains");
+						}
+						if(OutSide) 
+						  {
+							//  to remove all the sub domain by parity adjacents
+							//  because in this case we have only the true boundary edge
+							// so teh boundary is manifold
+							long nbk = nbsubdomains;
+							while (nbk)
+							 for (it=0;it<nbt && nbk ;it++)
+							  for (int na=0;na<3 && nbk ;na++)
+								 {
+								  Triangle *ta = triangles[it].TriangleAdj(na);
+								  long kl = ta ? mark[GetId(ta)] : -2;
+								  long kr = mark[it];
+								  if(kr !=kl) {
+									  if (kl >=0 && subdomains[kl].ReferenceNumber <0 && kr >=0 && subdomains[kr].ReferenceNumber>=0)
+										nbk--,subdomains[kr].ReferenceNumber=subdomains[kl].ReferenceNumber-1;
+									  if (kr >=0 && subdomains[kr].ReferenceNumber <0 && kl >=0 && subdomains[kl].ReferenceNumber>=0)
+										nbk--,subdomains[kl].ReferenceNumber=subdomains[kr].ReferenceNumber-1;
+									  if(kr<0 && kl >=0 && subdomains[kl].ReferenceNumber>=0)
+										nbk--,subdomains[kl].ReferenceNumber=-1;
+									  if(kl<0 && kr >=0 && subdomains[kr].ReferenceNumber>=0)
+										nbk--,subdomains[kr].ReferenceNumber=-1;
+								  }
+								 }
+							long  j=0;
+							for ( i=0;i<nbsubdomains;i++)
+							 if((-subdomains[i].ReferenceNumber) %2) { // good 
+								 if(i != j) 
+								  Exchange(subdomains[i],subdomains[j]);
+								 j++;}
+							 else{ 
+								 t= subdomains[i].head;
+								 while (t){
+									 nbtout++;
+									 t1=t;
+									 t=t->link;
+									 t1->link=0;
+								 }//while (t)
+								}
+							if(verbose>4) _printLine_("      Number of removes subdomains (OutSideMesh) = " << nbsubdomains-j);
+							nbsubdomains=j;
+						  }
+
+						delete []  mark; 
+
+			  }
+			else
+			  { // find the head for all sub domaine
+				if (Gh.nbsubdomains != nbsubdomains && subdomains)
+				 delete [] subdomains, subdomains=0;
+				if (! subdomains  ) 
+				 subdomains = new SubDomain[ Gh.nbsubdomains];
+				nbsubdomains =Gh.nbsubdomains;
+				long err=0;
+				CreateSingleVertexToTriangleConnectivity();
+				long * mark = new long[nbt];
+				Edge **GeomEdgetoEdge = MakeGeomEdgeToEdge();
+
+				for (it=0;it<nbt;it++)
+				 mark[it]=triangles[it].link ? -1 : -2;
+				long inew =0;
+				for (int i=0;i<nbsubdomains;i++) {
+					GeomEdge &eg = *Gh.subdomains[i].edge;
+					subdomains[i].ReferenceNumber = Gh.subdomains[i].ReferenceNumber;
+					int ssdlab = subdomains[i].ReferenceNumber;
+					// by carefull is not easy to find a edge create from a GeomEdge 
+					// see routine MakeGeomEdgeToEdge
+					Edge &e = *GeomEdgetoEdge[Gh.GetId(eg)];
+					_assert_(&e);
+					BamgVertex * v0 =  e(0),*v1 = e(1);
+					Triangle *t  = v0->t;
+					int direction = Gh.subdomains[i].direction;
+					// test if ge and e is in the same direction 
+					if (((eg[0].r-eg[1].r),(e[0].r-e[1].r))<0) direction = -direction ;
+					subdomains[i].direction = direction;
+					subdomains[i].edge = &e;
+					_assert_(t && direction);
+
+					AdjacentTriangle  ta(t,EdgesVertexTriangle[v0->IndexInTriangle][0]);// previous edges
+
+					while (1) {
+						_assert_(v0==ta.EdgeVertex(1));
+						if (ta.EdgeVertex(0) == v1) { // ok we find the edge
+							if (direction>0)  
+							 subdomains[i].head=t=Adj(ta);
+							else 
+							 subdomains[i].head=t=ta;
+							if(t<triangles || t >= triangles+nbt || t->det < 0 || t->link == 0) {
+								_error2_("bad definition of SubSomain " << i);
+							}
+							long it = GetId(t);
+							if (mark[it] >=0) {
+								break;
+							}
+							if(i != inew) 
+							 Exchange(subdomains[i],subdomains[inew]);
+							inew++;
+							Triangle *tt=t;
+							long kkk=0;
+							do 
+							  {
+								kkk++;
+								if (mark[GetId(tt)]>=0){
+									_error2_("mark[GetId(tt)]>=0");
+								}
+								mark[GetId(tt)]=i;
+								tt=tt->link;
+							  } while (tt!=t);
+							break;
+						}
+						ta = Previous(Adj(ta));         
+						if(t == (Triangle *) ta) {
+							_error2_("bad definition of SubSomain " << i);
+						}
+					}
+				}
+
+				if (inew < nbsubdomains) {
+					if (verbose>5) _printLine_("WARNING: " << nbsubdomains-inew << " SubDomains are being removed");
+					nbsubdomains=inew;}
+
+
+					for (it=0;it<nbt;it++)
+					 if ( mark[it] ==-1 ) 
+					  nbtout++,triangles[it].link =0;
+					delete [] GeomEdgetoEdge;
+					delete [] mark;
+
+			  }
+			nbtout=0;
+			for (it=0;it<nbt;it++) 
+			 if(!triangles[it].link)  nbtout++;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const Triangle & t) const{{{*/
+	long Mesh::GetId(const Triangle & t) const  { 
+		return &t - triangles;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const Triangle * t) const{{{*/
+	long Mesh::GetId(const Triangle * t) const  { 
+		return t - triangles;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const BamgVertex & t) const{{{*/
+	long Mesh::GetId(const BamgVertex & t) const  { 
+		return &t - vertices;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const BamgVertex * t) const{{{*/
+	long Mesh::GetId(const BamgVertex * t) const  { 
+		return t - vertices;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const Edge & t) const{{{*/
+	long Mesh::GetId(const Edge & t) const  { 
+		return &t - edges;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::GetId(const Edge * t) const{{{*/
+	long Mesh::GetId(const Edge * t) const  { 
+		return t - edges;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Init{{{*/
+	void Mesh::Init(long maxnbv_in) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/PreInit)*/
+
+		/* initialize random seed: */
+		srand(19999999);
+
+		/*Initialize fields*/
+		NbRef=0;
+		quadtree=NULL;
+		nbv=0;
+		nbt=0;
+		nbe=0;
+		edges=NULL;
+		nbq=0;
+		nbsubdomains=0;
+		subdomains=NULL;
+		maxnbv=maxnbv_in;
+		maxnbt=2 *maxnbv_in-2;
+		NbVertexOnBThVertex=0;
+		VertexOnBThVertex=NULL;
+		NbVertexOnBThEdge=0;
+		VertexOnBThEdge=NULL;
+		NbCrackedVertices=0;
+		CrackedVertices =NULL;
+		NbCrackedEdges =0;
+		CrackedEdges =NULL;
+		NbVerticesOnGeomVertex=0;
+		VerticesOnGeomVertex=NULL;
+		NbVerticesOnGeomEdge=0;
+		VerticesOnGeomEdge=NULL;
+
+		/*Allocate if maxnbv_in>0*/
+		if (maxnbv_in) {
+			vertices=new BamgVertex[maxnbv];
+			_assert_(vertices);
+			orderedvertices=new (BamgVertex* [maxnbv]);
+			_assert_(orderedvertices);
+			triangles=new Triangle[maxnbt];
+			_assert_(triangles);
+		}
+		else {
+			vertices=NULL;
+			orderedvertices=NULL;
+			triangles=NULL;
+			maxnbt=0;
+		} 
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::Insert{{{*/
+	void Mesh::Insert() {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Insert)*/
+
+		/*Insert points in the existing Geometry*/
+
+		//Intermediary
+		int i;
+
+		/*Get options*/
+		long int verbose=2;
+
+		//Display info
+		if (verbose>2) _printLine_("   Insert initial " << nbv << " vertices");
+
+		//Compute integer coordinates for the existing vertices
+		SetIntCoor();
+
+		/*Now we want to build a list (orderedvertices) of the vertices in a random
+		 * order. To do so, we use the following method:
+		 *
+		 * From an initial k0 in [0 nbv[ random (vertex number)
+		 * the next k (vertex number) is computed using a big
+		 * prime number (PN>>nbv) following:
+		 *
+		 * k_{i+1} = k_i + PN  [nbv]
+		 *
+		 * let's show that:
+		 *
+		 *   for all j in [0 nbv[, ∃! i in [0 nbv[ such that k_i=j
+		 *
+		 * Let's assume that there are 2 distinct j1 and j2 such that
+		 * k_j1 = k_j2
+		 *
+		 * This means that
+		 *  
+		 *  k0+j1*PN = k0+j2*PN [nbv]
+		 *  (j1-j2)*PN =0       [nbv]
+		 * since PN is a prime number larger than nbv, and nbv!=1
+		 *  j1-j2=0             [nbv]
+		 * BUT
+		 *  j1 and j2 are in [0 nbv[ which is impossible.
+		 *
+		 *  We hence have built a random list of nbv elements of
+		 *  [0 nbv[ all distincts*/
+
+		//Get Prime number
+		const long PrimeNumber= BigPrimeNumber(nbv);
+		int   k0=rand()%nbv; 
+
+		//Build orderedvertices
+		for (i=0; i<nbv; i++){
+			orderedvertices[i]=&vertices[k0=(k0+PrimeNumber)%nbv];
+		}
+
+		/*Modify orderedvertices such that the first 3 vertices form a triangle*/
+
+		//get first vertex i such that [0,1,i] are not aligned
+		for (i=2; det(orderedvertices[0]->i,orderedvertices[1]->i,orderedvertices[i]->i)==0;){
+			//if i is higher than nbv, it means that all the determinants are 0,
+			//all vertices are aligned!
+			if  (++i>=nbv) _error2_("all the vertices are aligned");
+		}
+		// exchange i et 2 in "orderedvertices" so that
+		// the first 3 vertices are not aligned (real triangle)
+		Exchange(orderedvertices[2], orderedvertices[i]);
+
+		/*Take the first edge formed by the first two vertices and build
+		 * the initial simple mesh from this edge and 2 boundary triangles*/
+
+		BamgVertex *v0=orderedvertices[0], *v1=orderedvertices[1];
+
+		nbt = 2;
+		triangles[0](0) = NULL;//infinite vertex
+		triangles[0](1) = v0;
+		triangles[0](2) = v1;
+		triangles[1](0) = NULL;//infinite vertex
+		triangles[1](2) = v0;
+		triangles[1](1) = v1;
+
+		//Build adjacence
+		const int e0 = OppositeEdge[0];
+		const int e1 = NextEdge[e0];
+		const int e2 = PreviousEdge[e0];
+		triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+		triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+		triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+
+		triangles[0].det = -1;  //boundary triangle: det = -1
+		triangles[1].det = -1;  //boundary triangle: det = -1
+
+		triangles[0].SetSingleVertexToTriangleConnectivity();
+		triangles[1].SetSingleVertexToTriangleConnectivity();
+
+		triangles[0].link=&triangles[1];
+		triangles[1].link=&triangles[0];
+
+		//build quadtree
+		if (!quadtree)  quadtree = new BamgQuadtree(this,0);
+		quadtree->Add(*v0);
+		quadtree->Add(*v1);
+
+		/*Now, add the vertices One by One*/
+		long NbSwap=0;
+		if (verbose>3) _printLine_("   Begining of insertion process...");
+
+		for (int icount=2; icount<nbv; icount++) {
+
+			//Get new vertex
+			BamgVertex *newvertex=orderedvertices[icount];
+
+			//Find the triangle in which newvertex is located
+			Icoor2 det3[3];
+			Triangle* tcvi = TriangleFindFromCoord(newvertex->i,det3); //(newvertex->i = integer coordinates)
+
+			//Add newvertex to the quadtree
+			quadtree->Add(*newvertex); 
+
+			//Add newvertex to the existing mesh
+			AddVertex(*newvertex,tcvi,det3);
+
+			//Make the mesh Delaunay around newvertex by swaping the edges
+			NbSwap += newvertex->Optim(1,0);
+		}
+
+		//Display info
+		if (verbose>3) {
+			_printLine_("      NbSwap of insertion: " << NbSwap);
+			_printLine_("      NbSwap/nbv:          " << NbSwap/nbv);
+		}
+
+#ifdef NBLOOPOPTIM
+
+		k0 = rand()%nbv ; 
+		for (int is4=0; is4<nbv; is4++) 
+		 orderedvertices[is4]= &vertices[k0 = (k0 + PrimeNumber)% nbv];
+
+		for(int Nbloop=0;Nbloop<NBLOOPOPTIM;Nbloop++){
+			long  NbSwap = 0;
+			for (int is1=0; is1<nbv; is1++) 
+			 NbSwap += orderedvertices[is1]->Optim(0,0);
+			if (verbose>3) {
+				_printLine_("      Optim Loop: " << Nbloop);
+				_printLine_("      NbSwap/nbv:          " << NbSwap/nbv);
+			}
+			if(!NbSwap) break;
+		}
+		CreateSingleVertexToTriangleConnectivity(); 
+		// because we break the TriangleContainingTheVertex
+#endif
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::InsertNewPoints{{{*/
+	long Mesh::InsertNewPoints(long nbvold,long & NbTSwap) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/InsertNewPoints)*/
+
+		long int verbose=0;
+		double seuil= 1.414/2 ;// for two close point 
+		long i;
+		long NbSwap=0;
+		Icoor2 det3[3];
+
+		//number of new points
+		const long nbvnew=nbv-nbvold;
+
+		//display info if required
+		if (verbose>5) _printLine_("      Try to Insert " << nbvnew << " new points");
+
+		//return if no new points
+		if (!nbvnew) return 0; 
+
+		/*construction of a random order*/
+		const long PrimeNumber= BigPrimeNumber(nbv)  ;
+		//remainder of the division of rand() by nbvnew
+		long k3 = rand()%nbvnew;
+		//loop over the new points
+		for (int is3=0; is3<nbvnew; is3++){
+			register long j=nbvold +(k3 = (k3+PrimeNumber)%nbvnew);
+			register long i=nbvold+is3; 
+			orderedvertices[i]= vertices + j;
+			orderedvertices[i]->ReferenceNumber=i;
+		}
+
+		// for all the new point
+		long iv=nbvold;
+		for (i=nbvold;i<nbv;i++){
+			BamgVertex &vi=*orderedvertices[i];
+			vi.i=R2ToI2(vi.r);
+			vi.r=I2ToR2(vi.i);
+			double hx,hy;
+			vi.m.Box(hx,hy);
+			Icoor1 hi=(Icoor1) (hx*coefIcoor),hj=(Icoor1) (hy*coefIcoor);
+			if (!quadtree->ToClose(vi,seuil,hi,hj)){
+				// a good new point 
+				BamgVertex &vj = vertices[iv];
+				long  j=vj.ReferenceNumber; 
+				if (&vj!=orderedvertices[j]){
+					_error2_("&vj!= orderedvertices[j]");
+				}
+				if(i!=j){ 
+					Exchange(vi,vj);
+					Exchange(orderedvertices[j],orderedvertices[i]);
+				}
+				vj.ReferenceNumber=0; 
+				Triangle *tcvj=TriangleFindFromCoord(vj.i,det3);
+				if (tcvj && !tcvj->link){
+					tcvj->Echo();
+					_error2_("problem inserting point in InsertNewPoints (tcvj=" << tcvj << " and tcvj->link=" << tcvj->link << ")");
+				}
+				quadtree->Add(vj);
+				AddVertex(vj,tcvj,det3);
+				NbSwap += vj.Optim(1);          
+				iv++;
+			}
+		} 
+		if (verbose>3) {
+			_printLine_("         number of new points: " << iv);
+			_printLine_("         number of to close (?) points: " << nbv-iv);
+			_printLine_("         number of swap after: " << NbSwap);
+		}
+		nbv = iv;
+
+		for (i=nbvold;i<nbv;i++) NbSwap += vertices[i].Optim(1);  
+		if (verbose>3) _printLine_("   NbSwap=" << NbSwap);
+
+		NbTSwap +=  NbSwap ;
+		return nbv-nbvold;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::isCracked{{{*/
+	int Mesh::isCracked() const {
+		return NbCrackedVertices != 0;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MakeGeomEdgeToEdge{{{*/
+	Edge** Mesh::MakeGeomEdgeToEdge() {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MakeGeomEdgeToEdge)*/
+
+		if (!Gh.nbe){
+			_error2_("!Gh.nbe");
+		}
+		Edge **e= new (Edge* [Gh.nbe]);
+
+		long i;
+		for ( i=0;i<Gh.nbe ; i++)
+		 e[i]=NULL;
+		for ( i=0;i<nbe ; i++) 
+		  { 
+			Edge * ei = edges+i;
+			GeomEdge *GeomEdgeHook = ei->GeomEdgeHook; 
+			e[Gh.GetId(GeomEdgeHook)] = ei;    
+		  }
+		for ( i=0;i<nbe ; i++) 
+		 for (int ii=0;ii<2;ii++) { 
+			 Edge * ei = edges+i;
+			 GeomEdge *GeomEdgeHook = ei->GeomEdgeHook;
+			 int j= ii;
+			 while (!(*GeomEdgeHook)[j].Required()) { 
+				 Adj(GeomEdgeHook,j); // next geom edge
+				 j=1-j;
+				 if (e[Gh.GetId(GeomEdgeHook)])  break; // optimisation
+				 e[Gh.GetId(GeomEdgeHook)] = ei; 
+			 }
+		 }
+
+		int kk=0;
+		for ( i=0;i<Gh.nbe ; i++){
+			if (!e[i]){
+				kk++;
+				if(kk<10) _printLine_("BUG: the geometrical edge " << i << " is on no edge curve");
+			}
+		}
+		if(kk) _error2_("See above");
+
+		return e;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MakeQuadrangles{{{*/
+	void Mesh::MakeQuadrangles(double costheta){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MakeQuadrangles)*/
+
+		long int verbose=0;
+
+		if (verbose>2) _printLine_("MakeQuadrangles costheta = " << costheta);
+
+		if (costheta >1) {
+			if (verbose>5) _printLine_("   do nothing: costheta > 1");
+		}
+
+
+			long nbqq = (nbt*3)/2;
+			DoubleAndInt *qq = new DoubleAndInt[nbqq];
+
+			long i,ij;
+			int j;
+			long k=0;
+			for (i=0;i<nbt;i++)
+			 for (j=0;j<3;j++)
+			  if ((qq[k].q=triangles[i].QualityQuad(j))>=costheta)
+				qq[k++].i3j=i*3+j;
+			//  sort  qq
+			HeapSort(qq,k);
+
+			long kk=0;
+			for (ij=0;ij<k;ij++) { 
+				i=qq[ij].i3j/3;
+				j=(int) (qq[ij].i3j%3);
+				// optisamition no float computation  
+				if (triangles[i].QualityQuad(j,0) >=costheta) 
+				 triangles[i].SetHidden(j),kk++;
+			  }
+			nbq = kk;
+			if (verbose>2){
+				_printLine_("   number of quadrilaterals    = " << nbq);
+				_printLine_("   number of triangles         = " << nbt-nbtout- nbq*2);
+				_printLine_("   number of outside triangles = " << nbtout);
+			}
+			delete [] qq;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MakeBamgQuadtree{{{*/
+	void Mesh::MakeBamgQuadtree() {  
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MakeBamgQuadtree)*/
+
+		long int verbose=0;
+		if (  !quadtree )  quadtree = new BamgQuadtree(this);
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MaxinalHmax{{{*/
+	double Mesh::MaximalHmax() {
+		return Max(pmax.x-pmin.x,pmax.y-pmin.y);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MaxSubDivision{{{*/
+	void  Mesh::MaxSubDivision(double maxsubdiv) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/MaxSubDivision)*/
+
+		long int verbose=0;
+
+		const  double maxsubdiv2 = maxsubdiv*maxsubdiv;
+		if(verbose>1) _printLine_("   Limit the subdivision of a edges in the new mesh by " << maxsubdiv);
+		// for all the edges 
+		// if the len of the edge is to long 
+		long it,nbchange=0;    
+		double lmax=0;
+		for (it=0;it<nbt;it++){
+			Triangle &t=triangles[it];
+			for (int j=0;j<3;j++){
+				Triangle &tt = *t.TriangleAdj(j);
+				if ( ! &tt ||  it < GetId(tt) && ( tt.link || t.link)){
+					BamgVertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+					BamgVertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+					R2 AB= (R2) v1-(R2) v0;
+					Metric M = v0;
+					double l = M(AB,AB);
+					lmax = Max(lmax,l);
+					if(l> maxsubdiv2){
+					  R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+						double lc = M(AC,AC);
+						D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+						D2xD2 Rt1(Rt.inv());
+						D2xD2 D(maxsubdiv2,0,0,lc);
+						D2xD2 MM = Rt1*D*Rt1.t();
+						v0.m =  M = Metric(MM.x.x,MM.y.x,MM.y.y);
+						nbchange++;
+					}
+					M = v1;
+					l = M(AB,AB);
+					lmax = Max(lmax,l);
+					if(l> maxsubdiv2){
+					  R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+						double lc = M(AC,AC);
+						D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+						D2xD2 Rt1(Rt.inv());
+						D2xD2 D(maxsubdiv2,0,0,lc);
+						D2xD2  MM = Rt1*D*Rt1.t();
+						v1.m =  M = Metric(MM.x.x,MM.y.x,MM.y.y);
+						nbchange++;
+					}
+				}
+			}
+		}
+		if(verbose>3){
+			_printLine_("      number of metric changes = " << nbchange << ", maximum number of subdivision of a edges before change = " << pow(lmax,0.5));
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MetricAt{{{*/
+	Metric Mesh::MetricAt(const R2 & A) const { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/MetricAt)*/
+
+		I2 a = R2ToI2(A);
+		Icoor2 deta[3];
+		Triangle * t =TriangleFindFromCoord(a,deta);
+		if (t->det <0) { // outside
+			double ba,bb;
+			AdjacentTriangle edge= CloseBoundaryEdge(a,t,ba,bb) ;
+			return Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));}
+		else { // inside
+			double   aa[3];
+			double s = deta[0]+deta[1]+deta[2];
+			aa[0]=deta[0]/s;
+			aa[1]=deta[1]/s;
+			aa[2]=deta[2]/s;
+			return Metric(aa,(*t)[0],(*t)[1],(*t)[2]);
+		}
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::MininalHmin{{{*/
+	double Mesh::MinimalHmin() {
+		return 2.0/coefIcoor;
+	}
+	/*}}}*/
+/*FUNCTION Mesh::NearestVertex{{{*/
+BamgVertex* Mesh::NearestVertex(Icoor1 i,Icoor1 j) {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NearestVertex)*/
+	return  quadtree->NearestVertex(i,j); 
+} 
+/*}}}*/
+	/*FUNCTION Mesh::NewPoints{{{*/
+	void  Mesh::NewPoints(Mesh & Bh,BamgOpts* bamgopts,int KeepVertices){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/NewPoints)*/
+
+		int i,j,k;
+		long NbTSwap=0;
+		long nbtold=nbt;
+		long nbvold=nbv;
+		long Headt=0;
+		long next_t;
+		long* first_np_or_next_t=new long[maxnbt];
+		Triangle* t=NULL;
+
+		/*Recover options*/
+		int verbose=bamgopts->verbose;
+
+		/*First, insert old points if requested*/
+		if (KeepVertices && (&Bh != this) && (nbv+Bh.nbv< maxnbv)){
+			if (verbose>5) _printLine_("         Inserting initial mesh points");
+			for (i=0;i<Bh.nbv;i++){ 
+				BamgVertex &bv=Bh[i];
+				if (!bv.GeomEdgeHook){
+					vertices[nbv].r   = bv.r;
+					vertices[nbv++].m = bv.m;
+				}
+			}
+			Bh.CreateSingleVertexToTriangleConnectivity();     
+			InsertNewPoints(nbvold,NbTSwap)   ;            
+		}  
+		else Bh.CreateSingleVertexToTriangleConnectivity();     
+
+		// generation of the list of next Triangle 
+		for(i=0;i<nbt;i++) first_np_or_next_t[i]=-(i+1);
+		// the next traingle of i is -first_np_or_next_t[i]
+
+		// Big loop (most time consuming)
+		int iter=0;
+		if (verbose>5) _printLine_("         Big loop");
+		do {
+			/*Update variables*/
+			iter++;
+			nbtold=nbt;
+			nbvold=nbv;
+
+			/*We test all triangles*/
+			i=Headt;
+			next_t=-first_np_or_next_t[i];
+			for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]){
+
+				//check i
+				if (i<0 || i>=nbt ){
+					_error2_("Index problem in NewPoints (i=" << i << " not in [0 " << nbt-1 << "])");
+				}
+				//change first_np_or_next_t[i]
+				first_np_or_next_t[i] = iter; 
+
+				//Loop over the edges of t
+				for(j=0;j<3;j++){
+					AdjacentTriangle tj(t,j);
+					BamgVertex &vA = *tj.EdgeVertex(0);
+					BamgVertex &vB = *tj.EdgeVertex(1);
+
+					//if t is a boundary triangle, or tj locked, continue
+					if (!t->link)     continue;
+					if (t->det <0)    continue;
+					if (t->Locked(j)) continue;
+
+					AdjacentTriangle tadjj = t->Adj(j);	  
+					Triangle* ta=tadjj;
+
+					//if the adjacent triangle is a boundary triangle, continur
+					if (ta->det<0) continue;	  
+
+					R2 A=vA;
+					R2 B=vB;
+					k=GetId(ta);
+
+					//if this edge has already been done, go to next edge of triangle
+					if(first_np_or_next_t[k]==iter) continue;
+
+					lIntTria.SplitEdge(Bh,A,B);
+					lIntTria.NewPoints(vertices,nbv,maxnbv);
+				  } // end loop for each edge 
+			  }// for triangle   
+
+			if (!InsertNewPoints(nbvold,NbTSwap)) break;
+			for (i=nbtold;i<nbt;i++) first_np_or_next_t[i]=iter;
+			Headt = nbt; // empty list 
+
+			// for all the triangle containing the vertex i
+			for (i=nbvold;i<nbv;i++){ 
+				BamgVertex*          s  = vertices + i;
+				AdjacentTriangle ta(s->t, EdgesVertexTriangle[s->IndexInTriangle][1]);
+				Triangle*        tbegin= (Triangle*) ta;
+				long kt;
+				do { 
+					kt = GetId((Triangle*) ta);
+					if (first_np_or_next_t[kt]>0){
+						first_np_or_next_t[kt]=-Headt;
+						Headt=kt;
+					}
+					if (ta.EdgeVertex(0)!=s){
+						_error2_("ta.EdgeVertex(0)!=s");
+					}
+					ta = Next(Adj(ta));
+				} while ( (tbegin != (Triangle*) ta)); 
+			}
+
+		} while (nbv!=nbvold);
+
+		delete []  first_np_or_next_t;
+
+		long NbSwapf =0,NbSwp;
+
+		NbSwp = NbSwapf;
+		for (i=0;i<nbv;i++)
+		 NbSwapf += vertices[i].Optim(0);
+		NbTSwap +=  NbSwapf ;
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::ProjectOnCurve{{{*/
+	GeomEdge*   Mesh::ProjectOnCurve( Edge & BhAB, BamgVertex &  vA, BamgVertex & vB,
+				double theta,BamgVertex & R,VertexOnEdge &  BR,VertexOnGeom & GR) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshQuad.cpp/ProjectOnCurve)*/
+
+		void *pA=0,*pB=0;
+		double tA=0,tB=0;
+		R2 A=vA,B=vB;
+		BamgVertex * pvA=&vA, * pvB=&vB;
+		if (vA.IndexInTriangle == IsVertexOnVertex){
+			pA=vA.BackgroundVertexHook;
+		}
+		else if (vA.IndexInTriangle == IsVertexOnEdge){
+			pA=vA.BackgroundEdgeHook->be;
+			tA=vA.BackgroundEdgeHook->abcisse;
+		}
+		else {
+			_error2_("ProjectOnCurve On BamgVertex " << BTh.GetId(vA) << " forget call to SetVertexFieldOnBTh");
+		} 
+
+		if (vB.IndexInTriangle == IsVertexOnVertex){
+			pB=vB.BackgroundVertexHook;
+		}
+		else if(vB.IndexInTriangle == IsVertexOnEdge){
+			pB=vB.BackgroundEdgeHook->be;
+			tB=vB.BackgroundEdgeHook->abcisse;
+		}
+		else {
+			_error2_("ProjectOnCurve On BamgVertex " << BTh.GetId(vB) << " forget call to SetVertexFieldOnBTh");
+		} 
+		Edge * e = &BhAB;
+		if (!pA || !pB || !e){
+			_error2_("!pA || !pB || !e");
+		}
+		// be carefull the back ground edge e is on same geom edge 
+		// of the initiale edge def by the 2 vertex A B;
+		//check Is a background Mesh;   
+		if (e<BTh.edges || e>=BTh.edges+BTh.nbe){
+			_error2_("e<BTh.edges || e>=BTh.edges+BTh.nbe");
+		}
+		// walk on BTh edge 
+		//not finish ProjectOnCurve with BackGround Mesh);
+		// 1 first find a back ground edge contening the vertex A
+		// 2 walk n back gound boundary to find the final vertex B
+
+		if( vA.IndexInTriangle == IsVertexOnEdge) 
+		  { // find the start edge 
+			e = vA.BackgroundEdgeHook->be;	 
+
+		  } 
+		else if (vB.IndexInTriangle == IsVertexOnEdge) 
+		  {
+			theta = 1-theta;
+			Exchange(tA,tB);
+			Exchange(pA,pB);
+			Exchange(pvA,pvB);
+			Exchange(A,B);
+			e =  vB.BackgroundEdgeHook->be;
+
+		  } 
+		else{ // do the search by walking 
+			_error2_("case not supported yet");
+		  }
+
+		// find the direction of walking with direction of edge and pA,PB;
+		R2 AB=B-A;
+
+		double cosE01AB = (( (R2) (*e)[1] - (R2) (*e)[0] ) , AB);
+		int kkk=0;
+		int direction = (cosE01AB>0) ? 1 : 0;
+
+		//   double l=0; // length of the edge AB
+		double abscisse = -1;
+
+		for (int step=0;step<2;step++){
+			// 2 times algo:
+			//    1 for computing the length l
+			//    2 for find the vertex 
+			int  iii;
+			BamgVertex  *v0=pvA,*v1; 
+			Edge *neee,*eee;
+			double lg =0; // length of the curve 
+			double te0;
+			// we suppose take the curve's abcisse 
+			for ( eee=e,iii=direction,te0=tA;
+						eee && ((( void*) eee) != pB) && (( void*) (v1=&((*eee)[iii]))) != pB ;
+						neee = eee->adj[iii],iii = 1-neee->Intersection(*eee),eee = neee,v0=v1,te0=1-iii ) { 
+
+				kkk=kkk+1;
+				_assert_(kkk<100);
+				_assert_(eee);
+				double lg0 = lg;
+				double dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+				lg += dp;
+				if (step && abscisse <= lg) { // ok we find the geom edge 
+					double sss  =   (abscisse-lg0)/dp;
+					double thetab = te0*(1-sss)+ sss*iii;
+					_assert_(thetab>=0 && thetab<=1);
+					BR = VertexOnEdge(&R,eee,thetab);
+					return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+				  }
+			  }
+			// we find the end 
+			if (v1 != pvB){
+				if (( void*) v1 == pB)
+				 tB = iii;
+
+				double lg0 = lg;
+				_assert_(eee);
+				v1 = pvB;
+				double dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+				lg += dp;	
+				abscisse = lg*theta;
+				if (abscisse <= lg && abscisse >= lg0 ) // small optimisation we know the lenght because end
+				  { // ok we find the geom edge 
+					double sss  =   (abscisse-lg0)/dp;
+					double thetab = te0*(1-sss)+ sss*tB;
+					_assert_(thetab>=0 && thetab<=1);
+					BR = VertexOnEdge(&R,eee,thetab);
+					return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+				  }
+			  }
+			abscisse = lg*theta;
+
+		  }
+		_error2_("Big bug...");
+		return 0; // just for the compiler 
+	}                  
+	/*}}}*/
+/*FUNCTION Mesh::ReconstructExistingMesh{{{*/
+void Mesh::ReconstructExistingMesh(){
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FillHoleInMesh)*/
+
+	/*This routine reconstruct an existing mesh to make it CONVEX:
+	 * -all the holes are filled
+	 * -concave boundaries are filled
+	 * A convex mesh is required for a lot of operations. This is why every mesh
+	 * goes through this process.
+	 * This routine also generates mesh properties such as adjencies,...
+	 */
+
+	/*Intermediary*/
+	int verbose=0;
+
+	// generation of the integer coordinate
+
+	// find extrema coordinates of vertices pmin,pmax
+	long i;
+	if(verbose>2) _printLine_("      Reconstruct mesh of " << nbv << " vertices"); 
+
+	//initialize orderedvertices
+	_assert_(orderedvertices);
+	for (i=0;i<nbv;i++) orderedvertices[i]=0;
+
+	//Initialize nbsubdomains
+	nbsubdomains =0;
+
+	/* generation of triangles adjacency*/
+
+	//First add existing edges
+	long kk =0;
+	SetOfEdges4* edge4= new SetOfEdges4(nbt*3,nbv);
+	for (i=0;i<nbe;i++){
+		kk=kk+(i==edge4->SortAndAdd(GetId(edges[i][0]),GetId(edges[i][1])));
+	}
+	if (kk != nbe){ 
+		_error2_("There are " << kk-nbe << " double edges in the mesh");
+	}
+
+	//Add edges of all triangles in existing mesh
+	long* st = new long[nbt*3];
+	for (i=0;i<nbt*3;i++) st[i]=-1;
+	for (i=0;i<nbt;i++){
+		for (int j=0;j<3;j++){
+
+			//Add current triangle edge to edge4
+			long k =edge4->SortAndAdd(GetId(triangles[i][VerticesOfTriangularEdge[j][0]]),GetId(triangles[i][VerticesOfTriangularEdge[j][1]]));
+
+			long invisible=triangles[i].Hidden(j);
+
+			//If the edge has not been added to st, add it
+			if(st[k]==-1) st[k]=3*i+j;
+
+			//If the edge already exists, add adjacency
+			else if(st[k]>=0) {
+				_assert_(!triangles[i].TriangleAdj(j));
+				_assert_(!triangles[st[k]/3].TriangleAdj((int) (st[k]%3)));
+
+				triangles[i].SetAdj2(j,triangles+st[k]/3,(int)(st[k]%3));
+				if (invisible) triangles[i].SetHidden(j);
+				if (k<nbe)     triangles[i].SetLocked(j);
+
+				//Make st[k] negative so that it will throw an error message if it is found again
+				st[k]=-2-st[k]; 
+			}
+
+			//An edge belongs to 2 triangles
+			else {
+				_error2_("The edge (" << GetId(triangles[i][VerticesOfTriangularEdge[j][0]]) << " , " << GetId(triangles[i][VerticesOfTriangularEdge[j][1]]) << ") belongs to more than 2 triangles");
+			}
+		}
+	}
+
+	//Display info if required
+	if(verbose>5) {
+		_printLine_("         info of Mesh:");
+		_printLine_("            - number of vertices    = " << nbv << " "); 
+		_printLine_("            - number of triangles   = " << nbt << " "); 
+		_printLine_("            - number of given edges = " << nbe << " "); 
+		_printLine_("            - number of all edges   = " << edge4->nb()); 
+		_printLine_("            - Euler number 1 - nb of holes = " << nbt-edge4->nb()+nbv); 
+	}
+
+	//check the consistency of edge[].adj and the geometrical required vertex
+	long k=0;
+	for (i=0;i<edge4->nb();i++){
+		if (st[i]>=0){ // edge alone 
+			if (i<nbe){
+				long i0=edge4->i(i);
+				orderedvertices[i0] = vertices+i0;
+				long i1=edge4->j(i);
+				orderedvertices[i1] = vertices+i1;
+			}
+			else {
+				k=k+1;
+				if (k<10) {
+					//print only 10 edges
+					_printLine_("Lost boundary edges " << i << " : " << edge4->i(i) << " " << edge4->j(i));
+				}
+				else if (k==10){
+					_printLine_("Other lost boundary edges not shown...");
+				}
+			}
+		}
+	}
+	if(k) {
+		_error2_(k << " boundary edges (from the geometry) are not defined as mesh edges");
+	}
+
+	/* mesh generation with boundary points*/
+	long nbvb=0;
+	for (i=0;i<nbv;i++){ 
+		vertices[i].t=0;
+		vertices[i].IndexInTriangle=0;
+		if (orderedvertices[i]) orderedvertices[nbvb++]=orderedvertices[i];
+	}
+
+	Triangle* savetriangles=triangles;
+	long savenbt=nbt;
+	long savemaxnbt=maxnbt;
+	SubDomain* savesubdomains=subdomains;
+	subdomains=0;
+
+	long  Nbtriafillhole=2*nbvb;
+	Triangle* triafillhole=new Triangle[Nbtriafillhole];
+	triangles = triafillhole;
+
+	nbt=2;
+	maxnbt= Nbtriafillhole;
+
+	//Find a vertex that is not aligned with vertices 0 and 1
+	for (i=2;det(orderedvertices[0]->i,orderedvertices[1]->i,orderedvertices[i]->i)==0;) 
+	 if  (++i>=nbvb) {
+		 _error2_("ReconstructExistingMesh: All the vertices are aligned");
+	 }
+	//Move this vertex (i) to the 2d position in orderedvertices
+	Exchange(orderedvertices[2], orderedvertices[i]);
+
+	/*Reconstruct mesh beginning with 2 triangles*/
+	BamgVertex *  v0=orderedvertices[0], *v1=orderedvertices[1];
+
+	triangles[0](0) = NULL; // Infinite vertex
+	triangles[0](1) = v0;
+	triangles[0](2) = v1;
+
+	triangles[1](0) = NULL;// Infinite vertex
+	triangles[1](2) = v0;
+	triangles[1](1) = v1;
+	const int e0 = OppositeEdge[0];
+	const int e1 = NextEdge[e0];
+	const int e2 = PreviousEdge[e0];
+	triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+	triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+	triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+
+	triangles[0].det = -1;  // boundary triangles
+	triangles[1].det = -1;  // boundary triangles
+
+	triangles[0].SetSingleVertexToTriangleConnectivity();
+	triangles[1].SetSingleVertexToTriangleConnectivity();
+
+	triangles[0].link=&triangles[1];
+	triangles[1].link=&triangles[0];
+
+	if (!quadtree) delete quadtree; //ReInitialise;
+	quadtree = new BamgQuadtree(this,0);
+	quadtree->Add(*v0);
+	quadtree->Add(*v1);
+
+	// vertices are added one by one
+	long NbSwap=0;
+	for (int icount=2; icount<nbvb; icount++) {
+		BamgVertex *vi  = orderedvertices[icount];
+		Icoor2 det3[3];
+		Triangle *tcvi = TriangleFindFromCoord(vi->i,det3);
+		quadtree->Add(*vi); 
+		AddVertex(*vi,tcvi,det3);
+		NbSwap += vi->Optim(1,1);
+	}
+
+	//enforce the boundary 
+	AdjacentTriangle ta(0,0);
+	long nbloss = 0,knbe=0;
+	for ( i = 0; i < nbe; i++){
+		if (st[i] >=0){ //edge alone => on border
+			BamgVertex &a=edges[i][0], &b=edges[i][1];
+			if (a.t && b.t){
+				knbe++;
+				if (ForceEdge(a,b,ta)<0) nbloss++;
+			}
+		}
+	}
+	if(nbloss) {
+		_error2_("we lost " << nbloss << " existing edges other " << knbe);
+	}
+
+	FindSubDomain(1);
+	// remove all the hole 
+	// remove all the good sub domain
+	long krm =0;
+	for (i=0;i<nbt;i++){
+		if (triangles[i].link){ // remove triangles
+			krm++;
+			for (int j=0;j<3;j++){
+				AdjacentTriangle ta =  triangles[i].Adj(j);
+				Triangle &tta = *(Triangle*)ta;
+				//if edge between remove and not remove 
+				if(! tta.link){ 
+					// change the link of ta;
+					int ja = ta;
+					BamgVertex *v0= ta.EdgeVertex(0);
+					BamgVertex *v1= ta.EdgeVertex(1);
+					long k =edge4->SortAndAdd(v0?GetId(v0):nbv,v1? GetId(v1):nbv);
+
+					_assert_(st[k]>=0);
+					tta.SetAdj2(ja,savetriangles + st[k] / 3,(int) (st[k]%3));
+					ta.SetLock();
+					st[k]=-2-st[k]; 
+				}
+			}
+		}
+	}
+	long NbTfillHoll =0;
+	for (i=0;i<nbt;i++){
+		if (triangles[i].link) {
+			triangles[i]=Triangle((BamgVertex *) NULL,(BamgVertex *) NULL,(BamgVertex *) NULL);
+			triangles[i].color=-1;
+		}
+		else{
+			triangles[i].color= savenbt+ NbTfillHoll++;
+		}
+	}
+	_assert_(savenbt+NbTfillHoll<=savemaxnbt);
+
+	// copy of the outside triangles in saveMesh 
+	for (i=0;i<nbt;i++){
+		if(triangles[i].color>=0) {
+			savetriangles[savenbt]=triangles[i];
+			savetriangles[savenbt].link=0;
+			savenbt++;
+		}
+	}
+	// gestion of the adj
+	k =0;
+	Triangle * tmax = triangles + nbt;
+	for (i=0;i<savenbt;i++) { 
+		Triangle & ti = savetriangles[i];
+		for (int j=0;j<3;j++){
+			Triangle * ta = ti.TriangleAdj(j);
+			int aa = ti.NuEdgeTriangleAdj(j);
+			int lck = ti.Locked(j);
+			if (!ta) k++; // bug 
+			else if ( ta >= triangles && ta < tmax){
+				ta= savetriangles + ta->color;
+				ti.SetAdj2(j,ta,aa);
+				if(lck) ti.SetLocked(j);
+			}
+		}
+	}
+
+	// restore triangles;
+	nbt=savenbt;
+	maxnbt=savemaxnbt;
+	delete [] triangles;
+	delete [] subdomains;
+	triangles = savetriangles;
+	subdomains = savesubdomains;
+	if (k) {
+		_error2_("number of triangles edges alone = " << k);
+	}
+	FindSubDomain();
+
+	delete edge4;
+	delete [] st;
+	for (i=0;i<nbv;i++) quadtree->Add(vertices[i]);
+
+	SetVertexFieldOn();
+
+	/*Check requirements consistency*/
+	for (i=0;i<nbe;i++){
+ 	/*If the current mesh edge is on Geometry*/
+		if(edges[i].GeomEdgeHook){
+			for(int j=0;j<2;j++){
+				/*Go through the edges adjacent to current edge (if on the same curve)*/
+				if (!edges[i].adj[j]){
+					/*The edge is on Geometry and does not have 2 adjacent edges... (not on a closed curve)*/
+					/*Check that the 2 vertices are on geometry AND required*/
+					if(!edges[i][j].GeomEdgeHook->IsRequiredVertex()){
+						_printLine_("ReconstructExistingMesh error message: problem with the edge number " << i+1 << ": [" << GetId(edges[i][0])+1 << " " << GetId(edges[i][1])+1 << "]");
+						_printLine_("This edge is on geometrical edge number " << Gh.GetId(edges[i].GeomEdgeHook)+1);
+						if (edges[i][j].GeomEdgeHook->OnGeomVertex())
+						 _printLine_("the vertex number " << GetId(edges[i][j])+1 << " of this edge is a geometric BamgVertex number " << Gh.GetId(edges[i][j].GeomEdgeHook->gv)+1);
+						else if (edges[i][j].GeomEdgeHook->OnGeomEdge())
+						 _printLine_("the vertex number " << GetId(edges[i][j])+1 << " of this edge is a geometric Edge number " << Gh.GetId(edges[i][j].GeomEdgeHook->ge)+1);
+						else
+						 _printLine_("Its pointer is " << edges[i][j].GeomEdgeHook);
+
+						_printLine_("This edge is on geometry and has no adjacent edge (open curve) and one of the tip is not required");
+						_error2_("See above (might be cryptic...)");
+					}
+				}
+			}
+		}
+	}
+}
+/*}}}*/
+	/*FUNCTION Mesh::TrianglesRenumberBySubDomain{{{*/
+	void Mesh::TrianglesRenumberBySubDomain(bool justcompress){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ReNumberingTheTriangleBySubDomain)*/
+
+		long int verbose=0;
+		long *renu= new long[nbt];
+		register Triangle *t0,*t,*te=triangles+nbt;
+		register long k=0,it,i,j;
+
+		for ( it=0;it<nbt;it++) 
+		 renu[it]=-1; // outside triangle 
+		for ( i=0;i<nbsubdomains;i++)
+		  { 
+			t=t0=subdomains[i].head;
+			if (!t0){ // not empty sub domain
+				_error2_("!t0");
+			}
+			do { 
+				long kt = GetId(t);
+				if (kt<0 || kt >= nbt ){
+					_error2_("kt<0 || kt >= nbt");
+				}
+				if (renu[kt]!=-1){
+					_error2_("renu[kt]!=-1");
+				}
+				renu[kt]=k++;
+			}
+			while (t0 != (t=t->link));
+		  }
+		// take is same numbering if possible    
+		if(justcompress)
+		 for ( k=0,it=0;it<nbt;it++) 
+		  if(renu[it] >=0 ) 
+			renu[it]=k++;
+
+		// put the outside triangles at the end
+		for ( it=0;it<nbt;it++){
+			if (renu[it]==-1) renu[it]=k++;
+		}
+		if (k != nbt){
+			_error2_("k != nbt");
+		}
+		// do the change on all the pointeur 
+		for ( it=0;it<nbt;it++)
+		 triangles[it].Renumbering(triangles,te,renu);
+
+		for ( i=0;i<nbsubdomains;i++)
+		 subdomains[i].head=triangles+renu[GetId(subdomains[i].head)];
+
+		// move the Triangles  without a copy of the array 
+		// be carefull not trivial code 
+		for ( it=0;it<nbt;it++) // for all sub cycles of the permutation renu
+		 if (renu[it] >= 0) // a new sub cycle
+			{ 
+			 i=it;
+			 Triangle ti=triangles[i],tj;
+			 while ( (j=renu[i]) >= 0) 
+				{ // i is old, and j is new 
+				 renu[i] = -1; // mark 
+				 tj = triangles[j]; // save new
+				 triangles[j]= ti; // new <- old
+				 i=j;     // next 
+				 ti = tj;
+				}  
+			}
+		delete [] renu;
+
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::VerticesRenumber{{{*/
+	void Mesh::VerticesRenumber(long * renu) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ReNumberingVertex)*/
+
+		// warning be carfull because pointer
+		// from on mesh to over mesh 
+		//  --  so do ReNumbering at the beginning
+		BamgVertex * ve = vertices+nbv;
+		long it,ie,i;
+
+		_printLine_("renumbering triangles");
+		for ( it=0;it<nbt;it++) 
+		 triangles[it].Renumbering(vertices,ve,renu);
+
+		_printLine_("renumbering edges");
+		for ( ie=0;ie<nbe;ie++) 
+		 edges[ie].Renumbering(vertices,ve,renu);
+
+		_printLine_("renumbering vertices on geom");
+		for (i=0;i< NbVerticesOnGeomVertex;i++)
+		  {
+			BamgVertex *v = VerticesOnGeomVertex[i].meshvertex;
+			if (v>=vertices && v < ve)
+			 VerticesOnGeomVertex[i].meshvertex=vertices+renu[GetId(v)];
+		  }
+
+		_printLine_("renumbering vertices on edge");
+		for (i=0;i< NbVerticesOnGeomEdge;i++)
+		  {
+			BamgVertex *v =VerticesOnGeomEdge[i].meshvertex;
+			if (v>=vertices && v < ve)
+			 VerticesOnGeomEdge[i].meshvertex=vertices+renu[GetId(v)];
+		  }
+
+		_printLine_("renumbering vertices on Bth vertex");
+		for (i=0;i< NbVertexOnBThVertex;i++)
+		  {
+			BamgVertex *v=VertexOnBThVertex[i].v;
+			if (v>=vertices && v < ve)
+			 VertexOnBThVertex[i].v=vertices+renu[GetId(v)];
+		  }
+
+		for (i=0;i< NbVertexOnBThEdge;i++)
+		  {
+			BamgVertex *v=VertexOnBThEdge[i].v;
+			if (v>=vertices && v < ve)
+			 VertexOnBThEdge[i].v=vertices+renu[GetId(v)];
+		  }
+
+		// move the Vertices without a copy of the array 
+		// be carefull not trivial code 
+		long j;
+		for ( it=0;it<nbv;it++) // for all sub cycles of the permutation renu
+		 if (renu[it] >= 0) // a new sub cycle
+			{ 
+			 i=it;
+			 BamgVertex ti=vertices[i],tj;
+			 while ( (j=renu[i]) >= 0){
+				 // i is old, and j is new 
+				 renu[i] = -1-renu[i]; // mark 
+				 tj = vertices[j];     // save new
+				 vertices[j]= ti;      // new <- old
+				 i=j;     // next 
+				 ti = tj;
+				}  
+			}
+		if (quadtree){
+			delete quadtree;
+			quadtree = new BamgQuadtree(this);
+		}
+
+		for ( it=0;it<nbv;it++) renu[i]= -renu[i]-1;
+	}
+	/*}}}*/
+/*FUNCTION Mesh::SetIntCoor{{{*/
+void Mesh::SetIntCoor(const char * strfrom) {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SetIntCoor)*/
+
+	/*Set integer coordinate for existing vertices*/
+
+	//Get extrema coordinates of the existing vertices
+	pmin =  vertices[0].r;
+	pmax =  vertices[0].r;
+	long i;
+	for (i=0;i<nbv;i++) {
+		pmin.x = Min(pmin.x,vertices[i].r.x);
+		pmin.y = Min(pmin.y,vertices[i].r.y);
+		pmax.x = Max(pmax.x,vertices[i].r.x);
+		pmax.y = Max(pmax.y,vertices[i].r.y);
+	}
+	R2 DD = (pmax-pmin)*0.05;
+	pmin = pmin-DD;
+	pmax = pmax+DD; 
+
+	//Compute coefIcoor
+	coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+	if (coefIcoor<=0){
+		_error2_("coefIcoor should be positive, a problem in the geometry is likely");
+	}
+
+	// generation of integer coord  
+	for (i=0;i<nbv;i++) {
+		vertices[i].i = R2ToI2(vertices[i].r);    
+	}
+
+	// computation of the det 
+	int number_of_errors=0;
+	for (i=0;i<nbt;i++) {
+		BamgVertex & v0 = triangles[i][0];
+		BamgVertex & v1 = triangles[i][1];
+		BamgVertex & v2 = triangles[i][2];
+
+		//If this is not a boundary triangle
+		if ( &v0 && &v1 &&  &v2 ){
+
+			/*Compute determinant*/
+			triangles[i].det= det(v0,v1,v2);
+
+			/*Check that determinant is positive*/
+			if (triangles[i].det <=0){
+
+				/*increase number_of_errors and print error only for the first 20 triangles*/
+				number_of_errors++;
+				if (number_of_errors<20){
+					_printLine_("Area of Triangle " << i+1 << " < 0 (det=" << triangles[i].det << ")");
+				}
+			}
+		}
+
+		//else, set as -1
+		else triangles[i].det=-1;
+	}
+
+	if (number_of_errors) _error2_("Fatal error: some triangles have negative areas, see above");
+}
+/*}}}*/
+/*FUNCTION Mesh::ShowRegulaty{{{*/
+void  Mesh::ShowRegulaty() const {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr>*/
+
+	const  double  sqrt32=sqrt(3.)*0.5; 
+	const double  aireKh=sqrt32*0.5;
+	D2  Beq(1,0),Heq(0.5,sqrt32);
+	D2xD2 Br(D2xD2(Beq,Heq).t());
+	D2xD2 B1r(Br.inv());
+	double gammamn=1e100,hmin=1e100;
+	double gammamx=0,hmax=0;
+	double beta=1e100;
+	double beta0=0;
+	double  alpha2=0;
+	double area=0,Marea=0;
+	// double cf= double(coefIcoor);
+	// double cf2= 6.*cf*cf;
+	int nt=0;
+	for (int it=0;it<nbt;it++)
+	 if ( triangles[it].link){
+		 Triangle &K=triangles[it];
+		 double  area3= Area2((R2) K[0],(R2) K[1],(R2) K[2])/6.;
+		 area+= area3;
+		 D2xD2 B_Kt(K[0],K[1],K[2]);
+		 D2xD2 B_K(B_Kt.t());
+		 D2xD2 B1K = Br*B_K.inv();
+		 D2xD2 BK =  B_K*B1r;
+		 D2xD2 B1B1 = B1K.t()*B1K;
+		 Metric MK(B1B1.x.x,B1B1.x.y,B1B1.y.y);
+		 EigenMetric VMK(MK);
+		 alpha2 = Max(alpha2,Max(VMK.lambda1/VMK.lambda2,VMK.lambda2/VMK.lambda1));
+		 double betaK=0;
+
+		 for (int j=0;j<3;j++)
+			{
+			 double he= Norme2(R2(K[j],K[(j+1)%3]));
+			 hmin=Min(hmin,he);
+			 hmax=Max(hmax,he);
+			 BamgVertex & v=K[j];
+			 D2xD2 M((Metric)v);
+			 betaK += sqrt(M.det());
+
+			 D2xD2 BMB = BK.t()*M*BK;
+			 Metric M1(BMB.x.x,BMB.x.y,BMB.y.y);
+			 EigenMetric VM1(M1);
+			 gammamn=Min3(gammamn,VM1.lambda1,VM1.lambda2);
+			 gammamx=Max3(gammamx,VM1.lambda1,VM1.lambda2);		
+			}
+		 betaK *= area3;//  1/2 (somme sqrt(det))* area(K)
+		 Marea+= betaK;
+		 beta=min(beta,betaK);
+		 beta0=max(beta0,betaK);
+		}   
+	area*=3; 
+	gammamn=sqrt(gammamn);
+	gammamx=sqrt(gammamx);    
+	_printLine_("   Adaptmesh info:");
+	_printLine_("      number of triangles = " << nt);
+	_printLine_("      hmin = " << hmin << ", hmax=" << hmax);
+	_printLine_("      area = " << area << ", M area = " << Marea << ", M area/( |Khat| nt) = " <<  Marea/(aireKh*nt));
+	_printLine_("      infinite-regularity(?): min = " << gammamn << ", max = " << gammamx);
+	_printLine_("      anisomax = " << pow(alpha2,0.5) << ", beta max = " << 1./pow(beta/aireKh,0.5) << ", min = " << 1./pow(beta0/aireKh,0.5));
+}
+/*}}}*/
+/*FUNCTION Mesh::ShowHistogram{{{*/
+void  Mesh::ShowHistogram() const {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ShowHistogram)*/
+
+	const long kmax=10;
+	const double llmin = 0.5,llmax=2;
+	const double lmin=log(llmin),lmax=log(llmax),delta= kmax/(lmax-lmin);
+	long histo[kmax+1];
+	long i,it,k, nbedges =0;
+	for (i=0;i<=kmax;i++) histo[i]=0;
+	for (it=0;it<nbt;it++)
+	 if ( triangles[it].link) 
+		{
+
+		 for (int j=0;j<3;j++)
+			{
+			 Triangle *ta = triangles[it].TriangleAdj(j);
+			 if ( !ta || !ta->link || GetId(ta) >= it) 
+				{ 
+				 BamgVertex & vP = triangles[it][VerticesOfTriangularEdge[j][0]];
+				 BamgVertex & vQ = triangles[it][VerticesOfTriangularEdge[j][1]];
+				 if ( !& vP || !&vQ) continue;
+				 R2 PQ = vQ.r - vP.r;
+				 double l = log(LengthInterpole(vP,vQ,PQ));
+				 nbedges++;
+				 k = (int) ((l - lmin)*delta);
+				 k = Min(Max(k,0L),kmax);
+				 histo[k]++;
+				}
+			}
+		}  
+	_printLine_(" --- Histogram of the unit mesh,  nb of edges = " << nbedges);
+	_printLine_("      length of edge in   | %% of edge  | Nb of edges "); 
+	_printLine_("      --------------------+-------------+-------------"); 
+	for   (i=0;i<=kmax;i++){ 
+		if (i==0) _printString_( "      " << setw(10) << 0.);
+		else      _printString_( "      " << setw(10) << exp(lmin+i/delta));
+		if (i==kmax) _printString_("          +inf   ");
+		else      _printString_( "      " << setw(10) << exp(lmin+(i+1)/delta));
+		_printLine_("|  " << setw(10) << (long((10000. * histo[i])/ nbedges)/100.) << " |");
+		_printLine_("  " << histo[i]);
+	}
+	_printLine_("      --------------------+-------------+-------------"); 
+}
+/*}}}*/
+/*FUNCTION Mesh::SmoothingVertex{{{*/
+void Mesh::SmoothingVertex(int nbiter,double omega ) { 
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SmoothingVertex)*/
+
+	long int verbose=0;
+	//  if quatree exist remove it end reconstruct
+	if (quadtree) delete quadtree;
+	quadtree=0;
+	CreateSingleVertexToTriangleConnectivity();
+	Triangle vide; // a triangle to mark the boundary vertex
+	Triangle   ** tstart= new Triangle* [nbv];
+	long i,j,k;
+	//   attention si Background == Triangle alors on ne peut pas utiliser la rechech rapide 
+	if ( this == & BTh)
+	 for ( i=0;i<nbv;i++)
+	  tstart[i]=vertices[i].t;     
+	else 
+	 for ( i=0;i<nbv;i++)
+	  tstart[i]=0;
+	for ( j=0;j<NbVerticesOnGeomVertex;j++ ) 
+	 tstart[ GetId(VerticesOnGeomVertex[j].meshvertex)]=&vide;
+	for ( k=0;k<NbVerticesOnGeomEdge;k++ ) 
+	 tstart[ GetId(VerticesOnGeomEdge[k].meshvertex)]=&vide;
+	if(verbose>2) _printLine_("   SmoothingVertex: nb Iteration = " << nbiter << ", Omega=" << omega);
+	for (k=0;k<nbiter;k++)
+	  {
+		long i,NbSwap =0;
+		double delta =0;
+		for ( i=0;i<nbv;i++)
+		 if (tstart[i] != &vide) // not a boundary vertex 
+		  delta=Max(delta,vertices[i].Smoothing(*this,BTh,tstart[i],omega));
+		if (!nbq)
+		 for ( i=0;i<nbv;i++)
+		  if (tstart[i] != &vide) // not a boundary vertex 
+			NbSwap += vertices[i].Optim(1);
+		if (verbose>3) _printLine_("      move max = " << pow(delta,0.5) << ", iteration = " << k << ", nb of swap = " << NbSwap);
+	  }
+
+	delete [] tstart;
+	if (quadtree) quadtree= new BamgQuadtree(this);
+}
+/*}}}*/
+/*FUNCTION Mesh::SmoothMetric{{{*/
+void Mesh::SmoothMetric(double raisonmax) { 
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/SmoothMetric)*/
+
+	long int verbose=0;
+
+	if(raisonmax<1.1) return;
+	if(verbose > 1) _printLine_("   Mesh::SmoothMetric raisonmax = " << raisonmax);
+	CreateSingleVertexToTriangleConnectivity();
+	long i,j,kch,kk,ip;
+	long *first_np_or_next_t0 = new long[nbv];
+	long *first_np_or_next_t1 = new long[nbv];
+	long Head0 =0,Head1=-1;
+	double logseuil= log(raisonmax);
+
+	for(i=0;i<nbv-1;i++)
+	 first_np_or_next_t0[i]=i+1; 
+	first_np_or_next_t0[nbv-1]=-1;// end;
+	for(i=0;i<nbv;i++)
+	 first_np_or_next_t1[i]=-1;
+	kk=0;
+	while (Head0>=0&& kk++<100) {
+		kch=0;
+		for (i=Head0;i>=0;i=first_np_or_next_t0[ip=i],first_np_or_next_t0[ip]=-1) {
+			//  pour tous les triangles autour du sommet s
+			register Triangle* t= vertices[i].t;
+			if (!t){
+				_error2_("!t");
+			}
+			BamgVertex & vi = vertices[i];
+			AdjacentTriangle ta(t,EdgesVertexTriangle[vertices[i].IndexInTriangle][0]);
+			BamgVertex *pvj0 = ta.EdgeVertex(0);
+			while (1) {
+				ta=Previous(Adj(ta));
+				if (vertices+i != ta.EdgeVertex(1)){
+					_error2_("vertices+i != ta.EdgeVertex(1)");
+				}
+				BamgVertex & vj = *(ta.EdgeVertex(0));
+				if ( &vj ) {
+					j= &vj-vertices;
+					if (j<0 || j >= nbv){
+						_error2_("j<0 || j >= nbv");
+					}
+					R2 Aij = (R2) vj - (R2) vi;
+					double ll =  Norme2(Aij);
+					if (0) {  
+						double hi = ll/vi.m(Aij);
+						double hj = ll/vj.m(Aij);
+						if(hi < hj)
+						  {
+							double dh=(hj-hi)/ll;
+							if (dh>logseuil) {
+								vj.m.IntersectWith(vi.m/(1 +logseuil*ll/hi));
+								if(first_np_or_next_t1[j]<0)
+								 kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+							}
+						  }
+					} 
+					else
+					  {
+						double li = vi.m(Aij);
+						if( vj.m.IntersectWith(vi.m/(1 +logseuil*li)) )
+						 if(first_np_or_next_t1[j]<0) // if the metrix change 
+						  kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+					  }
+				}
+				if  ( &vj ==  pvj0 ) break;
+			}
+		}
+		Head0 = Head1;
+		Head1 = -1;
+		Exchange(first_np_or_next_t0,first_np_or_next_t1);
+	}
+	if(verbose>2) _printLine_("      number of iterations = " << kch); 
+	delete [] first_np_or_next_t0;
+	delete [] first_np_or_next_t1;
+}
+/*}}}*/
+	/*FUNCTION Mesh::SplitElement{{{*/
+	int  Mesh::SplitElement(int choice){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, MeshQuad.cpp/SplitElement)*/
+
+		long int verbose=0;
+
+		Direction NoDirOfSearch;
+		const  int withBackground = &BTh != this && &BTh;
+
+		TrianglesRenumberBySubDomain();
+		//int nswap =0;
+		const long nfortria( choice ? 4 : 6);
+		if(withBackground) 
+		  {
+			BTh.SetVertexFieldOn();
+			SetVertexFieldOnBTh();
+		  }
+		else
+		 BTh.SetVertexFieldOn();
+
+		long newnbt=0,newnbv=0;
+		long * kedge = 0;
+		long newnbq=nbq;
+		long * ksplit= 0, * ksplitarray=0;
+		long kkk=0;
+		int ret =0;
+		if (maxnbv<nbv+nbe) return 1;//   
+		// 1) create  the new points by spliting the internal edges 
+		// set the 
+		long nbvold = nbv;
+		long nbtold = nbt;
+		long nbtoutold  = nbtout;
+		long  NbEdgeOnGeom=0;
+		long i;
+
+		nbt = nbt - nbtout; // remove all the  the ouside triangles 
+		long nbtsave = nbt;
+		Triangle * lastT = triangles + nbt;
+		for (i=0;i<nbe;i++)
+		 if(edges[i].GeomEdgeHook) NbEdgeOnGeom++;
+		long newnbe=nbe+nbe;
+		//  long newNbVerticesOnGeomVertex=NbVerticesOnGeomVertex;
+		long newNbVerticesOnGeomEdge=NbVerticesOnGeomEdge+NbEdgeOnGeom;
+		// long newNbVertexOnBThVertex=NbVertexOnBThVertex;
+		long newNbVertexOnBThEdge=withBackground ? NbVertexOnBThEdge+NbEdgeOnGeom:0;
+
+		// do allocation for pointeur to the geometry and background
+		VertexOnGeom * newVerticesOnGeomEdge = new VertexOnGeom[newNbVerticesOnGeomEdge];
+		VertexOnEdge *newVertexOnBThEdge = newNbVertexOnBThEdge ?  new VertexOnEdge[newNbVertexOnBThEdge]:0;
+		if (NbVerticesOnGeomEdge)
+		 memcpy(newVerticesOnGeomEdge,VerticesOnGeomEdge,sizeof(VertexOnGeom)*NbVerticesOnGeomEdge);
+		if (NbVertexOnBThEdge)
+		 memcpy(newVertexOnBThEdge,VertexOnBThEdge,sizeof(VertexOnEdge)*NbVertexOnBThEdge);
+		Edge *newedges = new Edge [newnbe];
+		//  memcpy(newedges,edges,sizeof(Edge)*nbe);
+		SetOfEdges4 * edge4= new SetOfEdges4(nbe,nbv);
+		long k=nbv;
+		long kk=0;
+		long kvb = NbVertexOnBThEdge;
+		long kvg = NbVerticesOnGeomEdge;
+		long ie =0;
+		Edge ** edgesGtoB=0;
+		if (withBackground)
+		 edgesGtoB= BTh.MakeGeomEdgeToEdge();
+		long ferr=0;
+		for (i=0;i<nbe;i++)
+		 newedges[ie].GeomEdgeHook=0;
+
+		for (i=0;i<nbe;i++)
+		  {
+			GeomEdge *ong =  edges[i].GeomEdgeHook;
+
+			newedges[ie]=edges[i];
+			newedges[ie].adj[0]=newedges+(edges[i].adj[0]-edges) ;
+			newedges[ie].adj[1]=newedges + ie +1;
+			R2 A = edges[i][0],B = edges[i][1];
+
+
+			kk += (i == edge4->SortAndAdd(GetId(edges[i][0]),GetId(edges[i][1])));
+			if (ong) // a geometrical edges 
+			  { 
+				if (withBackground){
+					// walk on back ground mesh 
+					//  newVertexOnBThEdge[ibe++] = VertexOnEdge(vertices[k],bedge,absicsseonBedge); 
+					// a faire -- difficile 
+					// the first PB is to now a background edge between the 2 vertices
+					if (!edgesGtoB){
+						_error2_("!edgesGtoB");
+					}
+					ong= ProjectOnCurve(*edgesGtoB[Gh.GetId(edges[i].GeomEdgeHook)],
+								edges[i][0],edges[i][1],0.5,vertices[k],
+								newVertexOnBThEdge[kvb],
+								newVerticesOnGeomEdge[kvg++]);
+					vertices[k].ReferenceNumber= edges[i].ReferenceNumber;
+					vertices[k].DirOfSearch =   NoDirOfSearch;        
+					;
+					// get the Info on background mesh 
+					double s =        newVertexOnBThEdge[kvb];
+					BamgVertex &  bv0  = newVertexOnBThEdge[kvb][0];
+					BamgVertex &  bv1  = newVertexOnBThEdge[kvb][1];
+					// compute the metrix of the new points 
+					vertices[k].m =  Metric(1-s,bv0,s,bv1); 
+					kvb++;
+				  }
+				else 
+				  {
+					ong=Gh.ProjectOnCurve(edges[i],
+								0.5,vertices[k],newVerticesOnGeomEdge[kvg++]);
+					// vertices[k].i = R2ToI2( vertices[k].r);
+					vertices[k].ReferenceNumber = edges[i].ReferenceNumber;
+					vertices[k].DirOfSearch = NoDirOfSearch;
+					vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);	      
+				  }  
+			  }
+			else // straigth line edge ---
+			  { 
+				vertices[k].r = ((R2) edges[i][0] + (R2)  edges[i][1] )*0.5;
+				vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);
+				vertices[k].GeomEdgeHook = 0;
+			  }
+			//vertices[k].i = R2ToI2( vertices[k].r);
+			R2 AB =  vertices[k].r;
+			R2 AA = (A+AB)*0.5;
+			R2 BB = (AB+B)*0.5;
+			vertices[k].ReferenceNumber = edges[i].ReferenceNumber;
+			vertices[k].DirOfSearch = NoDirOfSearch;
+
+			newedges[ie].GeomEdgeHook = Gh.Containing(AA,ong);
+			newedges[ie++].v[1]=vertices+k;
+
+			newedges[ie]=edges[i];
+			newedges[ie].adj[0]=newedges + ie -1;
+			newedges[ie].adj[1]=newedges+(edges[i].adj[1]-edges) ;
+			newedges[ie].GeomEdgeHook =  Gh.Containing(BB,ong);
+			newedges[ie++].v[0]=vertices+k;
+			k++;
+		  }
+		if (edgesGtoB) delete [] edgesGtoB;
+		edgesGtoB=0;
+
+		newnbv=k;
+		newNbVerticesOnGeomEdge=kvg;
+		if (newnbv> maxnbv) goto Error;// bug 
+
+		nbv = k;
+
+
+		kedge = new long[3*nbt+1];
+		ksplitarray = new long[nbt+1];
+		ksplit = ksplitarray +1; // because ksplit[-1] == ksplitarray[0]
+
+		for (i=0;i<3*nbt;i++)
+		 kedge[i]=-1;
+
+		//  
+
+		for (i=0;i<nbt;i++) {
+			Triangle & t = triangles[i];
+			if (!t.link){
+				_error2_("!t.link");
+			}
+			for(int j=0;j<3;j++)
+			  {
+				const AdjacentTriangle ta = t.Adj(j);
+				const Triangle & tt = ta;
+				if (&tt >= lastT)
+				 t.SetAdj2(j,0,0);// unset adj
+				const BamgVertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+				const BamgVertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+				long  ke =edge4->SortAndFind(GetId(v0),GetId(v1));
+				if (ke>0) 
+				  {
+					long ii = GetId(tt);
+					int  jj = ta;
+					long ks = ke + nbvold;
+					kedge[3*i+j] = ks;
+					if (ii<nbt) // good triangle
+					 kedge[3*ii+jj] = ks;
+					BamgVertex &A=vertices[ks];
+					double aa,bb,cc,dd;
+					if ((dd=Area2(v0.r,v1.r,A.r)) >=0){
+						// warning PB roundoff error 
+						if (t.link && ( (aa=Area2( A.r    , t[1].r , t[2].r )) < 0.0 
+										||   (bb=Area2( t[0].r , A.r    , t[2].r )) < 0.0  
+										||   (cc=Area2( t[0].r , t[1].r , A.r    )) < 0.0)){
+							_printLine_(ke + nbvold << " not in triangle " << i << " In= " << !!t.link << " " << aa << " " << bb << " " << cc << " " << dd);
+							_error2_("Number of triangles with P2 interpolation Problem");
+						}
+					}
+					else {
+						if (tt.link && ( (aa=Area2( A.r     , tt[1].r , tt[2].r )) < 0 
+										||   (bb=Area2( tt[0].r , A.r     , tt[2].r )) < 0 
+										||   (cc=Area2( tt[0].r , tt[1].r , A.r     )) < 0)){
+							_printLine_(ke + nbvold << " not in triangle " << ii << " In= " << !!tt.link << " " << aa << " " << bb << " " << cc << " " << dd);
+							_error2_("Number of triangles with P2 interpolation Problem");
+						}
+					} 
+				  }
+			  }
+		}
+
+		for (i=0;i<nbt;i++){
+			ksplit[i]=1; // no split by default
+			const Triangle & t = triangles[ i];
+			int nbsplitedge =0;
+			int nbinvisible =0;
+			int invisibleedge=0;
+			int kkk[3];      
+			for (int j=0;j<3;j++)
+			  {
+				if (t.Hidden(j)) invisibleedge=j,nbinvisible++;
+
+				const AdjacentTriangle ta = t.Adj(j);
+				const Triangle & tt = ta;
+
+
+				const BamgVertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+				const BamgVertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+				if ( kedge[3*i+j] < 0) 
+				  {
+					long  ke =edge4->SortAndFind(GetId(v0),GetId(v1));
+					if (ke<0) // new 
+					  {
+						if (&tt) // internal triangles all the boundary 
+						  { // new internal edges 
+							long ii = GetId(tt);
+							int  jj = ta;
+
+							kedge[3*i+j]=k;// save the vertex number 
+							kedge[3*ii+jj]=k;
+							if (k<maxnbv) 
+							  {
+								vertices[k].r = ((R2) v0+(R2) v1 )/2;
+								//vertices[k].i = R2ToI2( vertices[k].r);
+								vertices[k].ReferenceNumber=0;
+								vertices[k].DirOfSearch =NoDirOfSearch;
+								vertices[k].m =  Metric(0.5,v0,0.5,v1);
+							  }
+							k++;
+							kkk[nbsplitedge++]=j;		      
+						  } // tt 
+						else
+						 _error2_("Bug...");
+					  } // ke<0	       
+					else
+					  { // ke >=0
+						kedge[3*i+j]=nbvold+ke;
+						kkk[nbsplitedge++]=j;// previously splited
+					  }
+				  }
+				else 
+				 kkk[nbsplitedge++]=j;// previously splited
+
+			  } 
+			if (nbinvisible>=2){
+				_error2_("nbinvisible>=2");
+			}
+			switch (nbsplitedge) {
+				case 0: ksplit[i]=10; newnbt++; break;   // nosplit
+				case 1: ksplit[i]=20+kkk[0];newnbt += 2; break; // split in 2 
+				case 2: ksplit[i]=30+3-kkk[0]-kkk[1];newnbt += 3; break; // split in 3 
+				case 3:
+						  if (nbinvisible) ksplit[i]=40+invisibleedge,newnbt += 4;
+						  else   ksplit[i]=10*nfortria,newnbt+=nfortria;
+						  break;
+			} 
+			if (ksplit[i]<40){
+				_error2_("ksplit[i]<40");
+			}
+		  }
+		//  now do the element split
+		newnbq = 4*nbq;
+		nbv = k;
+		kkk = nbt;
+		ksplit[-1] = nbt;
+		// look on  old true  triangles 
+
+		for (i=0;i<nbtsave;i++){
+			int  nbmkadj=0;
+			long mkadj [100];
+			mkadj[0]=i;
+			long kk=ksplit[i]/10;
+			int  ke=(int) (ksplit[i]%10);
+			if (kk>=7 || kk<=0){
+				_error2_("kk>=7 || kk<=0");
+			}
+
+			// def the numbering   k (edge) i vertex 
+			int k0 = ke;
+			int k1 = NextEdge[k0];
+			int k2 = PreviousEdge[k0];
+			int i0 = OppositeVertex[k0];
+			int i1 = OppositeVertex[k1];
+			int i2 = OppositeVertex[k2];
+
+			Triangle &t0=triangles[i];
+			BamgVertex * v0=t0(i0);           
+			BamgVertex * v1=t0(i1);           
+			BamgVertex * v2=t0(i2);
+
+			if (nbmkadj>=10){
+				_error2_("nbmkadj>=10");
+			}
+			// --------------------------
+			AdjacentTriangle ta0(t0.Adj(i0)),ta1(t0.Adj(i1)),ta2(t0.Adj(i2));
+			// save the flag Hidden
+			int hid[]={t0.Hidden(0),t0.Hidden(1),t0.Hidden(2)};
+			// un set all adj -- save Hidden flag --
+			t0.SetAdj2(0,0,hid[0]);
+			t0.SetAdj2(1,0,hid[1]);
+			t0.SetAdj2(2,0,hid[2]);
+			// --  remake 
+			switch  (kk) {
+				case 1: break;// nothing 
+				case 2: // 
+						  {
+							Triangle &t1=triangles[kkk++];
+							t1=t0;
+							if (kedge[3*i+i0]<0){
+								_error2_("kedge[3*i+i0]<0");
+							}
+							BamgVertex * v3 = vertices + kedge[3*i+k0];
+
+							t0(i2) = v3;
+							t1(i1) = v3;
+							t0.SetAllFlag(k2,0);
+							t1.SetAllFlag(k1,0);
+						  } 
+						break; 
+				case 3: //
+						  {
+							Triangle &t1=triangles[kkk++];
+							Triangle &t2=triangles[kkk++];
+							t2=t1=t0;
+							if (kedge[3*i+k1]<0){
+								_error2_("kedge[3*i+k1]<0");
+							}
+							if (kedge[3*i+k2]<0){
+								_error2_("kedge[3*i+k2]<0");
+							}
+
+							BamgVertex * v01 = vertices + kedge[3*i+k2];
+							BamgVertex * v02 = vertices + kedge[3*i+k1]; 
+							t0(i1) = v01; 
+							t0(i2) = v02; 
+							t1(i2) = v02;
+							t1(i0) = v01; 
+							t2(i0) = v02; 
+							t0.SetAllFlag(k0,0);
+							t1.SetAllFlag(k1,0);
+							t1.SetAllFlag(k0,0);
+							t2.SetAllFlag(k2,0);
+						  } 
+						break;
+				case 4: // 
+				case 6: // split in 4 
+						  {
+							Triangle &t1=triangles[kkk++];
+							Triangle &t2=triangles[kkk++];
+							Triangle &t3=triangles[kkk++];
+							t3=t2=t1=t0;
+							if (kedge[3*i+k0] <0 || kedge[3*i+k1]<0 || kedge[3*i+k2]<0){
+								_error2_("kedge[3*i+k0] <0 || kedge[3*i+k1]<0 || kedge[3*i+k2]<0");
+							}
+							BamgVertex * v12 = vertices + kedge[3*i+k0];
+							BamgVertex * v02 = vertices + kedge[3*i+k1]; 
+							BamgVertex * v01 = vertices + kedge[3*i+k2];
+							t0(i1) = v01;
+							t0(i2) = v02;
+							t0.SetAllFlag(k0,hid[k0]);
+
+							t1(i0) = v01;
+							t1(i2) = v12;
+							t0.SetAllFlag(k1,hid[k1]);
+
+							t2(i0) = v02;
+							t2(i1) = v12;
+							t2.SetAllFlag(k2,hid[k2]);
+
+							t3(i0) = v12;
+							t3(i1) = v02;
+							t3(i2) = v01;
+
+							t3.SetAllFlag(0,hid[0]);	   
+							t3.SetAllFlag(1,hid[1]);	   
+							t3.SetAllFlag(2,hid[2]);
+
+							if ( kk == 6)
+							  {
+
+								Triangle &t4=triangles[kkk++];
+								Triangle &t5=triangles[kkk++];
+
+								t4 = t3;
+								t5 = t3;
+
+								t0.SetHidden(k0);
+								t1.SetHidden(k1);
+								t2.SetHidden(k2);
+								t3.SetHidden(0);
+								t4.SetHidden(1);
+								t5.SetHidden(2);
+
+								if (nbv < maxnbv ) 
+								  {
+									vertices[nbv].r = ((R2) *v01 + (R2) *v12  + (R2) *v02 ) / 3.0;
+									vertices[nbv].ReferenceNumber =0;
+									vertices[nbv].DirOfSearch =NoDirOfSearch;
+									//vertices[nbv].i = R2ToI2(vertices[nbv].r);
+									double a3[]={1./3.,1./3.,1./3.};
+									vertices[nbv].m = Metric(a3,v0->m,v1->m,v2->m);
+									BamgVertex * vc =  vertices +nbv++;
+									t3(i0) = vc;
+									t4(i1) = vc;
+									t5(i2) = vc;
+
+								  }
+								else
+								 goto Error; 
+							  }
+
+						  } 
+						break;         
+			}
+
+			// save all the new triangles
+			mkadj[nbmkadj++]=i;
+			long jj;
+			if (t0.link) 
+			 for (jj=nbt;jj<kkk;jj++)
+				{
+				 triangles[jj].link=t0.link;
+				 t0.link= triangles+jj;
+				 mkadj[nbmkadj++]=jj;
+				}
+			if (nbmkadj>13){// 13 = 6 + 4 +
+				_error2_("nbmkadj>13");
+			}
+
+			if (kk==6)  newnbq+=3;
+			for (jj=ksplit[i-1];jj<kkk;jj++) nbt = kkk;
+			ksplit[i]= nbt; // save last adresse of the new triangles
+			kkk = nbt;
+		  }
+
+		for (i=0;i<nbv;i++) vertices[i].m = vertices[i].m*2.;
+
+		if(withBackground)
+		 for (i=0;i<BTh.nbv;i++)
+		  BTh.vertices[i].m =  BTh.vertices[i].m*2.;
+
+
+		ret = 2;
+		if (nbt>= maxnbt) goto Error; // bug 
+		if (nbv>= maxnbv) goto Error; // bug 
+		// generation of the new triangles 
+
+		SetIntCoor("In SplitElement"); 
+
+		CreateSingleVertexToTriangleConnectivity();
+		if(withBackground)
+		 BTh.CreateSingleVertexToTriangleConnectivity();
+
+		delete [] edges;
+		edges = newedges;
+		nbe = newnbe;
+		nbq = newnbq;
+
+		for (i=0;i<nbsubdomains;i++)
+		  { 
+			long k = subdomains[i].edge- edges;
+			subdomains[i].edge =  edges+2*k; // spilt all edge in 2 
+		  }
+
+		if (ksplitarray) delete [] ksplitarray;
+		if (kedge) delete [] kedge;
+		if (edge4) delete edge4;
+		if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
+		VerticesOnGeomEdge= newVerticesOnGeomEdge;
+		if(VertexOnBThEdge) delete []  VertexOnBThEdge;
+		VertexOnBThEdge = newVertexOnBThEdge;
+		NbVerticesOnGeomEdge = newNbVerticesOnGeomEdge;
+		NbVertexOnBThEdge=newNbVertexOnBThEdge;
+		//  CreateSingleVertexToTriangleConnectivity();
+
+		ReconstructExistingMesh();
+
+		if (verbose>2){
+			_printLine_("   number of quadrilaterals    = " << nbq);
+			_printLine_("   number of triangles         = " << nbt-nbtout- nbq*2);
+			_printLine_("   number of outside triangles = " << nbtout);
+		}
+
+		return 0; //ok
+
+Error:
+		nbv = nbvold;
+		nbt = nbtold;
+		nbtout = nbtoutold;
+		// cleaning memory ---
+		delete [] newedges;
+		if (ksplitarray) delete [] ksplitarray;
+		if (kedge) delete [] kedge;
+		if (newVerticesOnGeomEdge) delete [] newVerticesOnGeomEdge;
+		if (edge4) delete edge4;
+		if(newVertexOnBThEdge) delete []  newVertexOnBThEdge;
+
+		return ret; // ok 
+	}
+	/*}}}*/
+/*FUNCTION Mesh::SplitInternalEdgeWithBorderVertices{{{*/
+long  Mesh::SplitInternalEdgeWithBorderVertices(){
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SplitInternalEdgeWithBorderVertices)*/
+
+	long NbSplitEdge=0;
+	SetVertexFieldOn();  
+	long it;
+	long nbvold=nbv;
+	long int verbose=2;
+	for (it=0;it<nbt;it++){
+		Triangle &t=triangles[it];
+		if (t.link)
+		 for (int j=0;j<3;j++)
+		  if(!t.Locked(j) && !t.Hidden(j)){
+			  Triangle &tt = *t.TriangleAdj(j);
+			  if ( &tt && tt.link && it < GetId(tt)) 
+				 { // an internal edge 
+				  BamgVertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+				  BamgVertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+				  if (v0.GeomEdgeHook && v1.GeomEdgeHook){
+					  R2 P= ((R2) v0 + (R2) v1)*0.5;
+					  if ( nbv<maxnbv) {
+						  vertices[nbv].r = P;
+						  vertices[nbv++].m = Metric(0.5,v0.m,0.5,v1.m);
+						  vertices[nbv].ReferenceNumber=0;
+						  vertices[nbv].DirOfSearch = NoDirOfSearch ;
+					  }
+					  NbSplitEdge++;
+				  }
+				 }
+		  }
+	}
+	CreateSingleVertexToTriangleConnectivity();    
+	if (nbvold!=nbv){
+		long  iv = nbvold;
+		long NbSwap = 0;
+		Icoor2 det3[3];  
+		for (int i=nbvold;i<nbv;i++) {// for all the new point
+			BamgVertex & vi = vertices[i];
+			vi.i = R2ToI2(vi.r);
+			vi.r = I2ToR2(vi.i);
+
+			// a good new point 
+			vi.ReferenceNumber=0; 
+			vi.DirOfSearch =NoDirOfSearch;
+			Triangle *tcvi = TriangleFindFromCoord(vi.i,det3);
+			if (tcvi && !tcvi->link) {
+				_printLine_("problem inserting point in SplitInternalEdgeWithBorderVertices (tcvj && !tcvj->link)");
+			}
+
+			quadtree->Add(vi);
+			if (!tcvi || tcvi->det<0){// internal
+				_error2_("!tcvi || tcvi->det < 0");
+			}
+			AddVertex(vi,tcvi,det3);
+			NbSwap += vi.Optim(1);          
+			iv++;
+			//      }
+	}
+	if (verbose>3) {
+		_printLine_("   number of points: " << iv);
+		_printLine_("   number of swap to  split internal edges with border vertices: " << NbSwap);
+		nbv = iv;
+	}
+}
+if (NbSplitEdge>nbv-nbvold) _printLine_("WARNING: not enough vertices  to split all internal edges, we lost " << NbSplitEdge - ( nbv-nbvold) << " edges...");
+if (verbose>2) _printLine_("SplitInternalEdgeWithBorderVertices: Number of splited edge " << NbSplitEdge);
+
+return  NbSplitEdge;
+}
+/*}}}*/
+/*FUNCTION Mesh::ToI2{{{*/
+I2 Mesh::R2ToI2(const R2 & P) const {
+	return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x)),(Icoor1) (coefIcoor*(P.y-pmin.y)) );
+}
+/*}}}*/
+/*FUNCTION Mesh::ToR2{{{*/
+R2 Mesh::I2ToR2(const I2 & P) const {
+	return  R2( (double) P.x/coefIcoor+pmin.x, (double) P.y/coefIcoor+pmin.y);
+}
+/*}}}*/
+/*FUNCTION Mesh::TriangleFindFromCoord{{{*/
+Triangle * Mesh::TriangleFindFromCoord(const I2 & B,Icoor2 det3[3], Triangle *tstart) const {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FindTriangleContening)*/
+
+	Triangle * t=0;	
+	int j,jp,jn,jj;
+	int counter;
+
+	/*Get starting triangle. Take tsart if provided*/
+	if (tstart) t=tstart;
+
+	/*Else find the closest Triangle using the quadtree*/
+	else {
+
+		/*Check that the quadtree does exist*/
+		if (!quadtree) _error2_("no starting triangle provided and no quadtree available");
+
+		/*Call NearestVertex*/
+		BamgVertex *a = quadtree->NearestVertex(B.x,B.y) ;
+
+		/*Check output (Vertex a)*/
+		if (!a)    _error2_("problem while trying to find nearest vertex from a given point. No output found");
+		if (!a->t) _error2_("no triangle is associated to vertex number " << GetId(a)+1 << " (orphan?)");
+		_assert_(a>=vertices && a<vertices+nbv);
+
+		/*Get starting triangle*/
+		t = a->t;
+		_assert_(t>=triangles && t<triangles+nbt);
+	}
+
+	Icoor2  detop ;
+
+	/*initialize number of test triangle*/
+	counter=0; 
+
+	/*The initial triangle might be outside*/
+	while (t->det < 0){ 
+
+		/*Get a real vertex from this triangle (k0)*/
+		int k0=(*t)(0)?(((*t)(1)?((*t)(2)?-1:2):1)):0;
+		_assert_(k0>=0);// k0 the NULL vertex
+		int k1=NextVertex[k0],k2=PreviousVertex[k0];
+		det3[k0]=det(B,(*t)[k1],(*t)[k2]);
+		det3[k1]=det3[k2]=-1;     
+		if (det3[k0] > 0) // outside B 
+		 return t; 
+		t = t->TriangleAdj(OppositeEdge[k0]);
+		counter++;
+		_assert_(counter<2);
+	}
+
+	jj=0;
+	detop = det(*(*t)(VerticesOfTriangularEdge[jj][0]),*(*t)(VerticesOfTriangularEdge[jj][1]),B);
+
+	while(t->det>0) { 
+
+		/*Increase counter*/
+		if (++counter>=10000) _error2_("Maximum number of iteration reached (threshold = " << counter << ").");
+
+		j= OppositeVertex[jj];
+		det3[j] = detop;  //det(*b,*s1,*s2);
+		jn = NextVertex[j];
+		jp = PreviousVertex[j];
+		det3[jp]= det(*(*t)(j),*(*t)(jn),B);
+		det3[jn] = t->det-det3[j] -det3[jp];
+
+		// count the number k of  det3 <0
+		int k=0,ii[3];
+		if (det3[0] < 0 ) ii[k++]=0; 
+		if (det3[1] < 0 ) ii[k++]=1;
+		if (det3[2] < 0 ) ii[k++]=2;
+		// 0 => ok
+		// 1 => go in way 1
+		// 2 => two way go in way 1 or 2 randomly
+
+		if (k==0) break;
+		if (k==2 && BinaryRand()) Exchange(ii[0],ii[1]);
+		_assert_(k<3);
+		AdjacentTriangle t1 = t->Adj(jj=ii[0]);
+		if ((t1.det() < 0 ) && (k == 2))
+		 t1 = t->Adj(jj=ii[1]);
+		t=t1;
+		j=t1;// for optimisation we now the -det[OppositeVertex[j]];
+		detop = -det3[OppositeVertex[jj]];
+		jj = j;
+	}
+
+	if (t->det<0) // outside triangle 
+	 det3[0]=det3[1]=det3[2]=-1,det3[OppositeVertex[jj]]=detop;
+	return t;
+}
+/*}}}*/
+/*FUNCTION Mesh::TriangleIntNumbering{{{*/
+void Mesh::TriangleIntNumbering(long* renumbering){
+
+	long num=0;
+	for (int i=0;i<nbt;i++){
+		if (triangles[i].det>0) renumbering[i]=num++;
+		else renumbering[i]=-1;
+	}
+	return;   
+}
+/*}}}*/
+/*FUNCTION Mesh::TriangleReferenceList{{{*/
+long  Mesh::TriangleReferenceList(long* reft) const {
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ConsRefTriangle)*/
+
+	long int verbose=0;
+	register Triangle *t0,*t;
+	register long k=0, num;   
+
+	//initialize all triangles as -1 (outside)
+	for (int it=0;it<nbt;it++) reft[it]=-1;
+
+	//loop over all subdomains
+	for (int i=0;i<nbsubdomains;i++){ 
+
+		//first triangle of the subdomain i
+		t=t0=subdomains[i].head;
+
+		//check that the subdomain is not empty
+		if (!t0){ _error2_("At least one subdomain is empty");}
+
+		//loop
+		do{
+			k++;
+
+			//get current triangle number
+			num = GetId(t);
+
+			//check that num is in [0 nbt[
+			_assert_(num>=0 && num<nbt);
+
+			//reft of this triangle is the subdomain number
+			reft[num]=i;
+
+		} while (t0 != (t=t->link));
+		//stop when all triangles of subdomains have been tagged
+
+	}
+	return k;   
+}
+/*}}}*/
+/*FUNCTION Mesh::Triangulate{{{*/
+void Mesh::Triangulate(double* x,double* y,int nods){
+
+	int verbose=0;
+	int i;
+	Metric M1(1);
+
+	/*Initialize mesh*/
+	Init(nods);//this resets nbv to 0
+	nbv=nods;
+
+	//Vertices
+	if(verbose) _printLine_("Reading vertices (" << nbv << ")");
+	for (i=0;i<nbv;i++){
+		vertices[i].r.x=x[i];
+		vertices[i].r.y=y[i];
+		vertices[i].ReferenceNumber=1;
+		vertices[i].DirOfSearch =NoDirOfSearch;
+		vertices[i].m=M1;
+		vertices[i].color=0;
+	}
+	maxnbt=2*maxnbv-2; // for filling The Holes and quadrilaterals 
+
+	/*Insert Vertices*/
+	Insert();
+}
+/*}}}*/
+	/*FUNCTION Mesh::TriangulateFromGeom0{{{*/
+	void Mesh::TriangulateFromGeom0(BamgOpts* bamgopts){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/GeomToTriangles0)*/
+		/*Generate mesh from geometry*/
+
+		/*Intermediaries*/
+		int                i,j,k;
+		int                nbcurves    = 0;
+		int                NbNewPoints,NbEdgeCurve;
+		double             lcurve,lstep,s;
+		const int          MaxSubEdge  = 10;
+
+		R2          AB;
+		GeomVertex *a, *b;
+		BamgVertex *va,*vb;
+		GeomEdge   *e;
+
+		// add a ref to GH to make sure that it is not destroyed by mistake
+		Gh.NbRef++;
+
+		/*Get options*/
+		int verbose=bamgopts->verbose;
+
+		//build background mesh flag (1 if background, else 0)
+		bool background=(&BTh != this);
+
+		/*Build VerticesOnGeomVertex*/
+
+		//Compute the number of geometrical vertices that we are going to use to mesh
+		for (i=0;i<Gh.nbv;i++){
+			if (Gh[i].Required()) NbVerticesOnGeomVertex++;
+		}
+		//allocate
+		VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];  
+		if(NbVerticesOnGeomVertex >= maxnbv) _error2_("too many vertices on geometry: " << NbVerticesOnGeomVertex << " >= " << maxnbv);
+		_assert_(nbv==0);
+		//Build VerticesOnGeomVertex
+		for (i=0;i<Gh.nbv;i++){
+			/* Add vertex only if required*/
+			if (Gh[i].Required()) {//Gh  vertices Required
+
+				//Add the vertex
+				_assert_(nbv<maxnbv);
+				vertices[nbv]=Gh[i];
+				
+				//Add pointer from geometry (Gh) to vertex from mesh (Th)
+				Gh[i].MeshVertexHook=vertices+nbv;
+
+				//Build VerticesOnGeomVertex for current point
+				VerticesOnGeomVertex[nbv]=VertexOnGeom(*Gh[i].MeshVertexHook,Gh[i]);
+
+				//nbv increment
+				nbv++;
+			}
+		}
+
+		/*Build VerticesOnGeomEdge*/
+
+		//check that edges is still empty (Init)
+		_assert_(!edges);
+
+		/* Now we are going to create the first edges corresponding
+		 * to the one present in the geometry provided.
+		 * We proceed in 2 steps
+		 *  -step 0: we count all the edges
+		 *           we allocate the number of edges at the end of step 0
+		 *  -step 1: the edges are created */
+		for (int step=0;step<2;step++){
+
+			//initialize number of edges and number of edges max
+			long nbex=0;
+			nbe=0;
+			long NbVerticesOnGeomEdge0=NbVerticesOnGeomEdge;
+			Gh.UnMarkEdges();	
+			nbcurves=0;
+
+			//go through the edges of the geometry
+			for (i=0;i<Gh.nbe;i++){
+
+				//ei = current Geometrical edge
+				GeomEdge &ei=Gh.edges[i];   
+
+				//loop over the two vertices of the edge ei
+				for(int j=0;j<2;j++) {
+
+					/*Take only required vertices (corner->beginning of a new curve)*/
+					if (!ei.Mark() && ei[j].Required()){ 
+
+						long  nbvend=0;
+						Edge* PreviousNewEdge=NULL;
+						lstep = -1;
+
+						/*If Edge is required (do that only once for the 2 vertices)*/
+						if(ei.Required()){
+							if (j==0){
+								//do not create internal points if required (take it as is)
+								if(step==0) nbe++;
+								else{ 
+									e=&ei;
+									a=ei(0);
+									b=ei(1);
+
+									//check that edges has been allocated
+									_assert_(edges);
+									edges[nbe].v[0]=a->MeshVertexHook;
+									edges[nbe].v[1]=b->MeshVertexHook;;
+									edges[nbe].ReferenceNumber = e->ReferenceNumber;
+									edges[nbe].GeomEdgeHook = e;
+									edges[nbe].adj[0] = 0;
+									edges[nbe].adj[1] = 0;
+									nbe++;
+								}
+							}
+						}
+
+						/*If Edge is not required: we are on a curve*/
+						else {
+							for (int kstep=0;kstep<=step;kstep++){
+								//kstep=0, compute number of edges (discretize curve)
+								//kstep=1  create the points and edge
+								PreviousNewEdge=0;
+								NbNewPoints=0;
+								NbEdgeCurve=0;
+								if (nbvend>=maxnbv) _error2_("maximum number of vertices too low! Check the domain outline or increase maxnbv");
+								lcurve =0;
+								s = lstep; //-1 initially, then length of each sub edge
+
+								/*reminder: i = edge number, j=[0;1] vertex index in edge*/
+								k=j;            // k = vertex index in edge (0 or 1)
+								e=&ei;          // e = reference of current edge
+								a=ei(k);        // a = pointer toward the kth vertex of the current edge
+								va = a->MeshVertexHook; // va = pointer toward mesh vertex associated
+								e->SetMark();   // Mark edge
+
+								/*Loop until we reach the end of the curve*/
+								for(;;){ 
+									k = 1-k;            // other vertx index of the curve
+									b = (*e)(k);        // b = pointer toward the other vertex of the current edge
+									AB= b->r - a->r;   // AB = vector of the current edge
+									Metric MA = background ? BTh.MetricAt(a->r) :a->m ;  //Get metric associated to A
+									Metric MB = background ? BTh.MetricAt(b->r) :b->m ;  //Get metric associated to B
+									double ledge = (MA(AB) + MB(AB))/2;                  //Get edge length in metric
+
+									/* We are now creating the mesh edges from the geometrical edge selected above.
+									 * The edge will be divided according to the metric previously computed and cannot
+									 * be divided more than 10 times (MaxSubEdge). */
+
+									//By default, there is only one subedge that is the geometrical edge itself
+									int NbSubEdge = 1;
+
+									//initialize lSubEdge, holding the length of each subedge (cannot be higher than 10)
+									double lSubEdge[MaxSubEdge];
+
+									//Build Subedges according to the edge length
+									if (ledge < 1.5){
+										//if ledge < 1.5 (between one and 2), take the edge as is
+										lSubEdge[0] = ledge;
+									}
+									//else, divide the edge
+									else {
+										//compute number of subedges (division of the edge), Maximum is 10
+										NbSubEdge = Min( MaxSubEdge, (int) (ledge +0.5));
+										/*Now, we are going to divide the edge according to the metric.
+										 * Get segment by sement along the edge.
+										 * Build lSubEdge, which holds the distance between the first vertex
+										 * of the edge and the next point on the edge according to the 
+										 * discretization (each SubEdge is AB)*/
+										R2 A,B;
+										A=a->r;
+										Metric MAs=MA,MBs;
+										ledge=0; 
+										double x =0, xstep= 1./NbSubEdge;
+										for (int kk=0; kk < NbSubEdge; kk++,A=B,MAs=MBs ) {
+											x += xstep;
+											B =  e->F(k ? x : 1-x);
+											MBs= background ? BTh.MetricAt(B) : Metric(1-x,MA,x,MB);
+											AB = A-B;
+											lSubEdge[kk]=(ledge+=(MAs(AB)+MBs(AB))/2);
+										}
+									}
+
+									double lcurveb = lcurve+ledge;
+
+									/*Now, create corresponding points*/
+									while(s>=lcurve && s<=lcurveb && nbv<nbvend){
+
+										/*Schematic of current curve
+										 *
+										 *  a                   vb                  b          // vertex
+										 *  0              ll0     ll1              ledge      // length from a
+										 *  + --- + - ... - + --S-- + --- + - ... - +          // where is S
+										 *  0              kk0     kk1              NbSubEdge  // Sub edge index
+										 *
+										 */
+
+										double ss = s-lcurve;
+
+										/*Find the SubEdge containing ss using Dichotomy*/
+										int kk0=-1,kk1=NbSubEdge-1,kkk;
+										double ll0=0,ll1=ledge,llk;
+										while (kk1-kk0>1){
+											if (ss < (llk=lSubEdge[kkk=(kk0+kk1)/2]))
+											 kk1=kkk,ll1=llk;
+											else
+											 kk0=kkk,ll0=llk;
+										}
+										_assert_(kk1!=kk0);
+
+										/*Curvilinear coordinate in [0 1] of ss in current edge*/
+										// WARNING: This is what we would do
+										// ssa = (ss-ll0)/(ll1-ll0);
+										// aa = (kk0+ssa)/NbSubEdge
+										// This is what Bamg does:
+										double sbb = (ss-ll0)/(ll1-ll0);
+										/*Curvilinear coordinate in [0 1] of ss in current curve*/
+										double bb = (kk1+sbb)/NbSubEdge;
+										double aa = 1-bb;
+
+										// new vertex on edge
+										vb = &vertices[nbv++];
+										vb->m = Metric(aa,a->m,bb,b->m);
+										vb->ReferenceNumber = e->ReferenceNumber;
+										vb->DirOfSearch =NoDirOfSearch;
+										double abcisse = k ? bb : aa;
+										vb->r =  e->F(abcisse);
+										VerticesOnGeomEdge[NbVerticesOnGeomEdge++]= VertexOnGeom(*vb,*e,abcisse);        
+
+										// to take into account the direction of the edge
+										s += lstep;
+										edges[nbe].v[0]=va;
+										edges[nbe].v[1]=vb;
+										edges[nbe].ReferenceNumber =e->ReferenceNumber;
+										edges[nbe].GeomEdgeHook = e;
+										edges[nbe].adj[0] = PreviousNewEdge;
+										if(PreviousNewEdge) PreviousNewEdge->adj[1]=&edges[nbe];
+										PreviousNewEdge=edges+nbe;
+										nbe++;
+										va = vb;
+									}
+									
+									/*We just added one edge to the curve: Go to the next one*/
+									lcurve = lcurveb;
+									e->SetMark();
+									a=b;
+
+									/*If b is required, we are on a new curve->break*/
+									if (b->Required()) break;
+									int kprev=k;
+									k = e->AdjVertexIndex[kprev];// next vertices
+									e = e->Adj[kprev];
+									_assert_(e);
+								}// for(;;)
+								vb = b->MeshVertexHook;
+
+								/*Number of edges in the last disretized curve*/
+								NbEdgeCurve = Max((long) (lcurve +0.5), (long) 1);
+								/*Number of internal vertices in the last disretized curve*/
+								NbNewPoints = NbEdgeCurve-1;
+								if(!kstep){
+									NbVerticesOnGeomEdge0 += NbNewPoints;
+									nbcurves++;
+								}
+								nbvend=nbv+NbNewPoints; 
+								lstep = lcurve / NbEdgeCurve; //approximately one
+							}// end of curve --
+							if (edges) { // last edges of the curves 
+								edges[nbe].v[0]=va;
+								edges[nbe].v[1]=vb;
+								edges[nbe].ReferenceNumber = e->ReferenceNumber;
+								edges[nbe].GeomEdgeHook = e;
+								edges[nbe].adj[0] = PreviousNewEdge;
+								edges[nbe].adj[1] = 0;
+								if(PreviousNewEdge) PreviousNewEdge->adj[1] = & edges[nbe];
+								nbe++;
+							}
+							else nbe += NbEdgeCurve;
+						} // end on  curve ---
+					}
+				}
+			} // for (i=0;i<nbe;i++)
+			if(!step) {
+				_assert_(!edges);
+				_assert_(!VerticesOnGeomEdge);
+
+				edges = new Edge[nbex=nbe];
+				if(NbVerticesOnGeomEdge0) VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge0];
+
+				// do the vertex on a geometrical vertex
+				_assert_(VerticesOnGeomEdge || NbVerticesOnGeomEdge0==0);
+				NbVerticesOnGeomEdge0 = NbVerticesOnGeomEdge;       
+			}
+			else{
+				_assert_(NbVerticesOnGeomEdge==NbVerticesOnGeomEdge0);
+			}
+		}
+
+		//Insert points inside existing triangles
+		if (verbose>4) _printLine_("      -- current number of vertices = " << nbv);
+		if (verbose>3) _printLine_("      Creating initial Constrained Delaunay Triangulation...");
+		if (verbose>3) _printLine_("         Inserting boundary points");
+		Insert();
+
+		//Force the boundary
+		if (verbose>3) _printLine_("         Forcing boundaries");
+		ForceBoundary();
+
+		//Extract SubDomains
+		if (verbose>3) _printLine_("         Extracting subdomains");
+		FindSubDomain();
+
+		if (verbose>3) _printLine_("      Inserting internal points");
+		NewPoints(*this,bamgopts,0) ;
+		if (verbose>4) _printLine_("      -- current number of vertices = " << nbv);
+	}
+	/*}}}*/
+	/*FUNCTION Mesh::TriangulateFromGeom1{{{*/
+	void Mesh::TriangulateFromGeom1(BamgOpts* bamgopts,int KeepVertices){ 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/GeomToTriangles1)*/
+
+		/*Get options*/
+		int verbose=bamgopts->verbose;
+
+		Gh.NbRef++;// add a ref to Gh
+
+		/************************************************************************* 
+		 * method in 2 steps
+		 * 1 - compute the number of new edges to allocate
+		 * 2 - construct the edges
+		 * remark:
+		 * in this part we suppose to have a background mesh with the same geometry 
+		 * 
+		 * To construct the discretization of the new mesh we have to 
+		 * rediscretize the boundary of background Mesh 
+		 * because we have only the pointeur from the background mesh to the geometry.
+		 * We need the abcisse of the background mesh vertices on geometry
+		 * so a vertex is 
+		 * 0 on GeomVertex ;
+		 * 1 on GeomEdge + abcisse
+		 * 2 internal 
+		 *************************************************************************/
+
+		//Check that background mesh and current mesh do have the same geometry
+		_assert_(&BTh.Gh==&Gh);
+		BTh.NbRef++; // add a ref to BackGround Mesh
+
+		//Initialize new mesh
+		BTh.SetVertexFieldOn();
+		int* bcurve = new int[Gh.nbcurves]; // 
+
+		/* There are 2 ways to make the loop 
+		* 1) on the geometry 
+		* 2) on the background mesh
+		*  if you do the loop on geometry, we don't have the pointeur on background,
+		*  and if you do the loop in background we have the pointeur on geometry
+		* so do the walk on  background */
+
+		NbVerticesOnGeomVertex=0;
+		NbVerticesOnGeomEdge=0;
+
+		/*STEP 1 copy of Required vertices*/
+
+		int i; 
+		for (i=0;i<Gh.nbv;i++) if (Gh[i].Required()) NbVerticesOnGeomVertex++;
+		printf("\n");
+		if(NbVerticesOnGeomVertex >= maxnbv){
+			_error2_("too many vertices on geometry: " << NbVerticesOnGeomVertex << " >= " << maxnbv);
+		}
+
+		VerticesOnGeomVertex = new VertexOnGeom[  NbVerticesOnGeomVertex];
+		VertexOnBThVertex    = new VertexOnVertex[NbVerticesOnGeomVertex];
+
+		//At this point there is NO vertex but vertices should have been allocated by Init
+		_assert_(vertices);
+		for (i=0;i<Gh.nbv;i++){
+			if (Gh[i].Required()) {//Gh vertices Required
+				vertices[nbv]  =Gh[i];
+				vertices[nbv].i=I2(0,0);
+				Gh[i].MeshVertexHook = vertices + nbv;// save Geom -> Th
+				VerticesOnGeomVertex[nbv]= VertexOnGeom(vertices[nbv],Gh[i]);
+				nbv++;
+			}
+			else Gh[i].MeshVertexHook=0;
+		} 
+		for (i=0;i<BTh.NbVerticesOnGeomVertex;i++){ 
+			VertexOnGeom &vog=BTh.VerticesOnGeomVertex[i];
+			if (vog.IsRequiredVertex()){
+				GeomVertex* gv=vog;
+				BamgVertex *bv = vog;
+				_assert_(gv->MeshVertexHook); // use of Geom -> Th
+				VertexOnBThVertex[NbVertexOnBThVertex++]=VertexOnVertex(gv->MeshVertexHook,bv);
+				gv->MeshVertexHook->m = bv->m; // for taking the metric of the background mesh
+			}
+		}
+		_assert_(NbVertexOnBThVertex==NbVerticesOnGeomVertex); /*This might be due to MaxCornerAngle too small*/
+
+		/*STEP 2: reseed boundary edges*/
+
+		//  find the begining of the curve in BTh
+		Gh.UnMarkEdges();	
+		int bfind=0;
+		for (int i=0;i<Gh.nbcurves;i++) bcurve[i]=-1; 
+
+		/*Loop over the backgrounf mesh BTh edges*/
+		for (int iedge=0;iedge<BTh.nbe;iedge++){      
+			Edge &ei = BTh.edges[iedge];
+
+			/*Loop over the 2 vertices of the current edge*/
+			for(int je=0;je<2;je++){
+
+				/* If one of the vertex is required we are in a new curve*/
+				if (ei[je].GeomEdgeHook->IsRequiredVertex()){ 
+
+					/*Get curve number*/
+					int nc=ei.GeomEdgeHook->CurveNumber;
+					
+					//_printLine_("Dealing with curve number " << nc);
+					//_printLine_("edge on geometry is same as GhCurve? " << (ei.GeomEdgeHook==Gh.curves[nc].FirstEdge || ei.GeomEdgeHook==Gh.curves[nc].LastEdge)?"yes":"no");
+					//if(ei.GeomEdgeHook==Gh.curves[nc].FirstEdge || ei.GeomEdgeHook==Gh.curves[nc].LastEdge){
+					//	_printLine_("Do we have the right extremity? curve first vertex -> " << ((GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].FirstEdge)[Gh.curves[nc].FirstVertexIndex])?"yes":"no");
+					//	_printLine_("Do we have the right extremity? curve last  vertex -> " << ((GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].LastEdge)[Gh.curves[nc].LastVertexIndex])?"yes":"no");
+					//}
+					//BUG FIX from original bamg
+					/*Check that we are on the same edge and right vertex (0 or 1) */
+					if(ei.GeomEdgeHook==Gh.curves[nc].FirstEdge  && (GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].FirstEdge)[Gh.curves[nc].FirstVertexIndex]){
+						bcurve[nc]=iedge*2+je;
+						bfind++;	
+					}
+					else if ((ei.GeomEdgeHook==Gh.curves[nc].LastEdge  && (GeomVertex *)*ei[je].GeomEdgeHook==&(*Gh.curves[nc].LastEdge)[Gh.curves[nc].LastVertexIndex]) && bcurve[nc]==-1){
+						bcurve[nc]=iedge*2+je;
+						bfind++;	
+					}
+				}
+			}
+		} 
+		if (bfind!=Gh.nbcurves){
+			delete [] bcurve;
+			_error2_("problem generating number of curves (" << Gh.nbcurves << " found in the geometry but " << bfind << " curve found in the mesh)");
+		}
+
+		// method in 2 + 1 step 
+		//  0.0) compute the length and the number of vertex to do allocation
+		//  1.0) recompute the length
+		//  1.1) compute the  vertex 
+
+		long nbex=0,NbVerticesOnGeomEdgex=0;
+		for (int step=0; step <2;step++){
+
+			long NbOfNewPoints=0;
+			long NbOfNewEdge=0;
+			long iedge;
+			Gh.UnMarkEdges();	
+			double L=0;
+
+			/*Go through all geometrical curve*/
+			for (int icurve=0;icurve<Gh.nbcurves;icurve++){ 
+
+				/*Get edge and vertex (index) of background mesh on this curve*/
+				iedge=bcurve[icurve]/2;
+				int jedge=bcurve[icurve]%2;
+
+				/*Get edge of Bth with index iedge*/
+				Edge &ei = BTh.edges[iedge];
+			
+				/*Initialize variables*/
+				double Lstep=0,Lcurve=0;    // step between two points   (phase==1) 
+				long NbCreatePointOnCurve=0;// Nb of new points on curve (phase==1) 
+
+				/*Do phase 0 to step*/
+				for(int phase=0;phase<=step;phase++){
+
+					/*Current curve pointer*/
+					Curve *curve= Gh.curves+icurve;
+
+					/*Get index of current curve*/
+					int icurveequi= Gh.GetId(curve);
+
+					/*For phase 0, check that we are at the begining of the curve only*/
+					if(phase==0 &&  icurveequi!=icurve)  continue;
+
+					int   k0=jedge,k1;
+					Edge* pe=  BTh.edges+iedge;
+					int   iedgeequi=bcurve[icurveequi]/2;
+					int   jedgeequi=bcurve[icurveequi]%2;
+
+					int k0equi=jedgeequi,k1equi;		  
+					Edge * peequi= BTh.edges+iedgeequi;
+					GeomEdge *ongequi = peequi->GeomEdgeHook;
+
+					double sNew=Lstep;// abscisse of the new points (phase==1) 
+					L=0;// length of the curve
+					long i=0;// index of new points on the curve
+					register GeomVertex * GA0 = *(*peequi)[k0equi].GeomEdgeHook;
+					BamgVertex *A0;
+					A0 = GA0->MeshVertexHook;  // the vertex in new mesh
+					BamgVertex *A1;
+					VertexOnGeom *GA1;
+					Edge* PreviousNewEdge = 0;
+
+					// New Curve phase 
+					_assert_(A0-vertices>=0 && A0-vertices<nbv);
+					if(ongequi->Required()){
+						GeomVertex *GA1 = *(*peequi)[1-k0equi].GeomEdgeHook;
+						A1 = GA1->MeshVertexHook;  //
+					}       
+					else {
+						for(;;){
+							Edge &ee=*pe; 
+							Edge &eeequi=*peequi; 
+							k1 = 1-k0; // next vertex of the edge 
+							k1equi= 1 - k0equi;
+							_assert_(pe && ee.GeomEdgeHook);
+							ee.GeomEdgeHook->SetMark();
+							BamgVertex & v0=ee[0], & v1=ee[1];
+							R2 AB=(R2)v1-(R2)v0;
+							double L0=L,LAB;
+							LAB=LengthInterpole(v0.m,v1.m,AB);
+							L+= LAB;
+
+							if (phase){
+								// computation of the new points for the given curve
+								while ((i!=NbCreatePointOnCurve) && sNew<=L) { 
+
+									//some checks
+									_assert_(sNew>=L0);
+									_assert_(LAB);
+									_assert_(vertices && nbv<maxnbv);
+									_assert_(edges && nbe<nbex);
+									_assert_(VerticesOnGeomEdge && NbVerticesOnGeomEdge<NbVerticesOnGeomEdgex);
+
+									// new vertex on edge
+									A1=vertices+nbv++;
+									GA1=VerticesOnGeomEdge+NbVerticesOnGeomEdge;
+									Edge* e = edges + nbe++;
+									double se= (sNew-L0)/LAB;
+									if (se<0 || se>=1.000000001){
+										_error2_("Problem creating point on a boundary: se=" << se << " should be in [0 1]");
+									}
+									se = abscisseInterpole(v0.m,v1.m,AB,se,1);
+									if (se<0 || se>1){
+										_error2_("Problem creating point on a boundary: se=" << se << " should be in [0 1]");
+									}
+									se = k1         ? se : 1. - se;
+									se = k1==k1equi ? se : 1. - se;
+									VertexOnBThEdge[NbVerticesOnGeomEdge++] = VertexOnEdge(A1,&eeequi,se); // save 
+									ongequi=Gh.ProjectOnCurve(eeequi,se,*A1,*GA1); 
+									A1->ReferenceNumber = eeequi.ReferenceNumber;
+									A1->DirOfSearch =NoDirOfSearch;
+									e->GeomEdgeHook = ongequi;
+									e->v[0]=A0;
+									e->v[1]=A1;
+									e->ReferenceNumber = eeequi.ReferenceNumber;
+									e->adj[0]=PreviousNewEdge;
+
+									if (PreviousNewEdge) PreviousNewEdge->adj[1]=e;
+									PreviousNewEdge=e;
+									A0=A1;
+									sNew += Lstep;
+									if (++i== NbCreatePointOnCurve) break;
+								}
+							}
+
+							//some checks
+							_assert_(ee.GeomEdgeHook->CurveNumber==ei.GeomEdgeHook->CurveNumber);
+							if (ee[k1].GeomEdgeHook->IsRequiredVertex()) {
+								_assert_(eeequi[k1equi].GeomEdgeHook->IsRequiredVertex());
+								register GeomVertex * GA1 = *eeequi[k1equi].GeomEdgeHook;
+								A1=GA1->MeshVertexHook;// the vertex in new mesh
+								_assert_(A1-vertices>=0 && A1-vertices<nbv);
+								break;
+							}
+							if (!ee.adj[k1]) {
+								_error2_("adj edge " << BTh.GetId(ee) << ", nbe=" << nbe << ", Gh.vertices=" << Gh.vertices);
+							}
+							pe = ee.adj[k1]; // next edge
+							k0 = pe->Intersection(ee); 
+							peequi= eeequi.adj[k1equi];  // next edge
+							k0equi=peequi->Intersection(eeequi);            
+						}// for(;;) end of the curve
+					}
+
+
+					if (phase){ // construction of the last edge
+						Edge* e=edges + nbe++;
+						e->GeomEdgeHook  = ongequi;
+						e->v[0]=A0;
+						e->v[1]=A1;
+						e->ReferenceNumber = peequi->ReferenceNumber;
+						e->adj[0]=PreviousNewEdge;
+						e->adj[1]=0;
+						if (PreviousNewEdge) PreviousNewEdge->adj[1]=e;
+						PreviousNewEdge = e;
+
+						_assert_(i==NbCreatePointOnCurve);
+					}
+
+					if (!phase)  { // 
+						long NbSegOnCurve = Max((long)(L+0.5),(long) 1);// nb of seg
+						Lstep = L/NbSegOnCurve; 
+						Lcurve = L;
+						NbCreatePointOnCurve = NbSegOnCurve-1;
+						NbOfNewEdge += NbSegOnCurve;
+						NbOfNewPoints += NbCreatePointOnCurve;
+					}
+				}
+			}//  end of curve loop 
+
+			//Allocate memory
+			if(step==0){
+				if(nbv+NbOfNewPoints > maxnbv) {
+					_error2_("too many vertices on geometry: " << nbv+NbOfNewPoints << " >= " << maxnbv);
+				}
+				edges = new Edge[NbOfNewEdge];
+				nbex = NbOfNewEdge;
+				if(NbOfNewPoints) {
+					VerticesOnGeomEdge    = new VertexOnGeom[NbOfNewPoints];
+					NbVertexOnBThEdge     = NbOfNewPoints;
+					VertexOnBThEdge       = new  VertexOnEdge[NbOfNewPoints];
+					NbVerticesOnGeomEdgex = NbOfNewPoints;
+				}
+				NbOfNewPoints =0;
+				NbOfNewEdge = 0;
+			}
+		}
+		_assert_(nbe!=0);
+		delete [] bcurve;
+
+		//Insert points inside existing triangles
+		if (verbose>4) _printLine_("      -- current number of vertices = " << nbv);
+		if (verbose>3) _printLine_("      Creating initial Constrained Delaunay Triangulation...");
+		if (verbose>3) _printLine_("         Inserting boundary points");
+		Insert();
+
+		//Force the boundary
+		if (verbose>3) _printLine_("         Forcing boundaries");
+		ForceBoundary();
+
+		//Extract SubDomains
+		if (verbose>3) _printLine_("         Extracting subdomains");
+		FindSubDomain();
+
+		if (verbose>3) _printLine_("      Inserting internal points");
+		NewPoints(BTh,bamgopts,KeepVertices) ;
+		if (verbose>4) _printLine_("      -- current number of vertices = " << nbv);
+	}
+	/*}}}*/
+
+	/*Intermediary*/
+	/*FUNCTION CloseBoundaryEdge{{{*/
+	AdjacentTriangle CloseBoundaryEdge(I2 A,Triangle *t, double &a,double &b) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/CloseBoundaryEdge)*/
+
+		int k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+		int dir=0;
+		if (k<0){
+			_error2_("k<0");
+		}
+		int kkk=0;  
+		Icoor2 IJ_IA,IJ_AJ;
+		AdjacentTriangle edge(t,OppositeEdge[k]);          
+		for (;;edge = dir >0 ? Next(Adj(Next(edge))) : Previous(Adj(Previous(edge)))) {  
+			kkk++;
+			if (kkk>=1000){
+				_error2_("kkk>=1000");
+			}
+			BamgVertex  &vI =  *edge.EdgeVertex(0);
+			BamgVertex  &vJ =  *edge.EdgeVertex(1);
+			I2 I=vI, J=vJ, IJ= J-I;
+			IJ_IA = (IJ ,(A-I));
+			if (IJ_IA<0) {
+				if (dir>0) {a=1;b=0;return edge;}// change of signe => I
+				else {dir=-1;
+					continue;}};// go in direction i 
+					IJ_AJ = (IJ ,(J-A));
+					if (IJ_AJ<0) {
+						if(dir<0)  {a=0;b=1;return edge;}            
+						else {dir = 1;
+							continue;}}// go in direction j
+							double IJ2 = IJ_IA + IJ_AJ;
+							if (IJ2==0){
+								_error2_("IJ2==0");
+							}
+							a= IJ_AJ/IJ2;
+							b= IJ_IA/IJ2;
+							return edge;
+		  } 
+	}
+	/*}}}*/
+	/*FUNCTION CloseBoundaryEdgeV2{{{*/
+	AdjacentTriangle CloseBoundaryEdgeV2(I2 C,Triangle *t, double &a,double &b) { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/CloseBoundaryEdgeV2)*/
+		// walk around the vertex 
+		// version 2 for remove the probleme if we fill the hole
+		//int bug=1;
+		//  Triangle *torigine = t;
+		// restart:
+		//   int dir=0;
+		if (t->link != 0){
+			_error2_("t->link != 0");
+		}
+		// to have a starting edges 
+		// try the 3 edge bourna-- in case of internal hole 
+		// and choice  the best 
+		// 
+		// the probleme is in case of  the fine and long internal hole
+		// for exemple neart the training edge of a wing
+		BamgVertex * s=0,*s1=0, *s0=0;
+		Icoor2 imax = MaxICoor22;
+		Icoor2 l0 = imax,l1 = imax;
+		double dd2 =  imax;// infinity
+		AdjacentTriangle er; 
+		int  cas=-2;
+		for (int j=0;j<3;j++)
+		  { 
+			AdjacentTriangle ta=t->FindBoundaryEdge(j);
+			if  (! (Triangle *) ta) continue;
+			s0 = ta.EdgeVertex(0);
+			s1 = ta.EdgeVertex(1);
+			I2 A = * s0;
+			I2 B = *ta.EdgeVertex(1);
+			I2 AB = B-A,AC=C-A,BC=B-C;
+			Icoor2  ACAC = (AC,AC), BCBC = (BC,BC);
+			Icoor2  AB2  =   Norme2_2(AB); //  ||AB||^2
+			Icoor2  ABAC  =   (AB,AC);         //  AB.AC|
+
+			double d2;
+			if ( ABAC < 0 )   // DIST A
+			  {
+				if ( (d2=(double) ACAC)  <  dd2) 
+				  {
+					er = ta;
+					l0 = ACAC;
+					l1 = BCBC;
+					cas = 0;
+					s = s0;
+				  }
+			  }
+			else if (ABAC > AB2)  // DIST B
+			  {
+				if ( (d2=(double) BCBC)  <  dd2) 
+				  {
+					dd2 = d2;
+					er = Adj(ta); // other direction
+					l0 = BCBC;
+					l1 = ACAC;
+					cas = 1;
+					s = s1;
+				  }
+			  }
+			else  // DIST AB
+			  { 
+
+				double det_2 =  (double) Det(AB,AC); 
+				det_2 *= det_2; // square of area*2 of triangle ABC
+				d2 = det_2/ (double) AB2; // hauteur^2 in C of of triangle ABC      
+
+				if (d2 < dd2) 
+				  {
+					dd2 = d2;
+					er = ta;
+					l0 = (AC,AC);
+					l1 = (BC,BC);
+					s = 0;
+					cas = -1;
+					b = ((double) ABAC/(double) AB2);
+					a = 1 - b;
+				  }
+			  }
+		  }
+		if (cas ==-2){
+			_error2_("cas==-2");
+		}
+		// l1 = ||C s1||  , l0 = ||C s0||
+		// where s0,s1 are the vertex of the edge er
+
+		if ( s) 
+		  { 
+			t=er;
+			AdjacentTriangle edge(er); 
+
+			int kkk=0;  
+			int linkp = t->link == 0;
+
+			Triangle * tt=t=edge=Adj(Previous(edge));
+			do  {  // loop over vertex s
+				kkk++;
+				if (edge.EdgeVertex(0)!=s && kkk>=10000){
+					_error2_("edge.EdgeVertex(0)!=s && kkk>=10000");
+				}
+
+				int link = tt->link == 0;
+				if ((link + linkp) == 1) 
+				  { // a boundary edge 
+					BamgVertex * st = edge.EdgeVertex(1);
+					I2 I=*st;
+					Icoor2  ll = Norme2_2 (C-I);
+					if (ll < l1) {  // the other vertex is neart 
+						s1=st;
+						l1=ll;
+						er = edge;
+						if(ll<l0) { // change of direction --
+							s1=s;
+							l1=l0;
+							s=st;
+							l0=ll;
+							t=tt;
+							edge=Adj(edge);
+							link=linkp;
+							er = edge;
+						}
+					}
+				  }
+
+				linkp=link;
+				edge=Adj(Previous(edge));
+				tt = edge;
+			} while (t!=tt);
+
+			if (!(Triangle *) er){
+				_error2_("!(Triangle *) er");
+			}
+			I2 A((I2)*er.EdgeVertex(0));
+			I2 B((I2)*er.EdgeVertex(1));
+			I2 AB=B-A,AC=C-A,CB=B-C;
+			double aa =  (double) (AB,AC);
+			double bb =  (double) (AB,CB);
+			if (aa<0)       a=1,b=0;
+			else if(bb<0)   a=0,b=1;
+			else  
+			  {
+				a  = bb/(aa+bb);
+				b  = aa/(aa+bb);
+			  }
+		  }
+		return er;
+	} 
+	/*}}}*/
+/*FUNCTION ForceEdge{{{*/
+int ForceEdge(BamgVertex &a, BamgVertex & b,AdjacentTriangle & taret)  { 
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/ForceEdge)*/
+
+	int NbSwap =0;
+	if (!a.t || !b.t){ // the 2 vertex is in a mesh
+		_error2_("!a.t || !b.t");
+	}
+	int k=0;
+	taret=AdjacentTriangle(0,0); // erreur 
+
+	AdjacentTriangle tta(a.t,EdgesVertexTriangle[a.IndexInTriangle][0]);
+	BamgVertex   *v1, *v2 = tta.EdgeVertex(0),*vbegin =v2;
+	// we turn around a in the  direct direction  
+
+	Icoor2 det2 = v2 ? det(*v2,a,b): -1 , det1;
+	if(v2) // normal case 
+	 det2 = det(*v2,a,b);
+	else { // no chance infini vertex try the next
+		tta= Previous(Adj(tta));
+		v2 = tta.EdgeVertex(0);
+		vbegin =v2;
+		if (!v2){
+			_error2_("!v2");
+		}
+		det2 = det(*v2,a,b);
+	}
+
+	while (v2 != &b) {
+		AdjacentTriangle tc = Previous(Adj(tta));    
+		v1 = v2; 
+		v2 = tc.EdgeVertex(0);
+		det1 = det2;
+		det2 =  v2 ? det(*v2,a,b): det2; 
+
+		if((det1 < 0) && (det2 >0)) { 
+			// try to force the edge 
+			BamgVertex * va = &a, *vb = &b;
+			tc = Previous(tc);
+			if (!v1 || !v2){
+				_error2_("!v1 || !v2");
+			}
+			Icoor2 detss = 0,l=0,ks;
+			while ((ks=SwapForForcingEdge(  va,  vb, tc, detss, det1,det2,NbSwap)))
+			 if(l++ > 10000000) {
+				 _error2_("Loop in forcing Egde, nb de swap=" << NbSwap << ", nb of try swap (" << l << ") too big");
+			 }
+			BamgVertex *aa = tc.EdgeVertex(0), *bb = tc.EdgeVertex(1);
+			if (( aa == &a ) && (bb == &b) ||  (bb ==  &a ) && (aa == &b)) {
+				tc.SetLock();
+				a.Optim(1,0);
+				b.Optim(1,0);
+				taret = tc;
+				return NbSwap;
+			}
+			else 
+			  {
+				taret = tc;
+				return -2; // error  boundary is crossing
+			  }
+		}
+		tta = tc;
+		k++;
+		if (k>=2000){
+			_error2_("k>=2000");
+		}
+		if ( vbegin == v2 ) return -1;// error 
+	}
+
+	tta.SetLock();
+	taret=tta;
+	a.Optim(1,0);
+	b.Optim(1,0);
+	return NbSwap; 
+}
+/*}}}*/
+/*FUNCTION swap{{{*/
+void  swap(Triangle *t1,short a1, Triangle *t2,short a2, BamgVertex *s1,BamgVertex *s2,Icoor2 det1,Icoor2 det2){ 
+	/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/swap)*/
+	// --------------------------------------------------------------
+	// short a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+	//                               
+	//               sb                     sb    
+	//             / | \                   /   \                      !
+	//         as1/  |  \                 /a2   \                     !
+	//           /   |   \               /    t2 \                    !
+	//       s1 /t1  | t2 \s2  -->   s1 /___as2___\s2                 !
+	//          \  a1|a2  /             \   as1   /  
+	//           \   |   /               \ t1    /   
+	//            \  |  / as2             \   a1/    
+	//             \ | /                   \   /     
+	//              sa                       sa   
+	//  -------------------------------------------------------------
+	int as1 = NextEdge[a1];
+	int as2 = NextEdge[a2];
+	int ap1 = PreviousEdge[a1];
+	int ap2 = PreviousEdge[a2];
+	(*t1)(VerticesOfTriangularEdge[a1][1]) = s2 ; // avant sb
+	(*t2)(VerticesOfTriangularEdge[a2][1]) = s1  ; // avant sa
+	// mise a jour des 2 adjacences externes 
+	AdjacentTriangle taas1 = t1->Adj(as1),
+						  taas2 = t2->Adj(as2),
+						  tas1(t1,as1), tas2(t2,as2),
+						  ta1(t1,a1),ta2(t2,a2);
+	// externe haut gauche
+	taas1.SetAdj2(ta2, taas1.GetAllFlag_UnSwap());
+	// externe bas droite
+	taas2.SetAdj2(ta1, taas2.GetAllFlag_UnSwap());
+	// remove the Mark  UnMarkSwap 
+	t1->SetUnMarkUnSwap(ap1);
+	t2->SetUnMarkUnSwap(ap2);
+	// interne 
+	tas1.SetAdj2(tas2);
+
+	t1->det = det1;
+	t2->det = det2;
+
+	t1->SetSingleVertexToTriangleConnectivity();
+	t2->SetSingleVertexToTriangleConnectivity();
+} // end swap 
+/*}}}*/
+	/*FUNCTION SwapForForcingEdge{{{*/
+	int SwapForForcingEdge(BamgVertex   *  & pva ,BamgVertex  * &   pvb ,AdjacentTriangle & tt1,Icoor2 & dets1, Icoor2 & detsa,Icoor2 & detsb, int & NbSwap) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/SwapForForcingEdge)*/
+		// l'arete ta coupe l'arete pva pvb
+		// de cas apres le swap sa coupe toujours
+		// on cherche l'arete suivante 
+		// on suppose que detsa >0 et detsb <0
+		// attention la routine echange pva et pvb 
+
+		if(tt1.Locked()) return 0; // frontiere croise 
+
+		AdjacentTriangle tt2 = Adj(tt1);
+		Triangle *t1=tt1,*t2=tt2;// les 2 triangles adjacent
+		short a1=tt1,a2=tt2;// les 2 numero de l arete dans les 2 triangles
+		if ( a1<0 || a1>=3 ){
+			_error2_("a1<0 || a1>=3");
+		}
+
+		BamgVertex & sa= (* t1)[VerticesOfTriangularEdge[a1][0]];
+		BamgVertex & s1= (*t1)[OppositeVertex[a1]];
+		BamgVertex & s2= (*t2)[OppositeVertex[a2]];
+
+
+		Icoor2 dets2 = det(*pva,*pvb,s2);
+		Icoor2 det1=t1->det , det2=t2->det ;
+		Icoor2 detT = det1+det2;
+		if ((det1<=0 ) || (det2<=0)){
+			_error2_("(det1<=0 ) || (det2<=0)");
+		}
+		if ( (detsa>=0) || (detsb<=0) ){ // [a,b] cut infinite line va,bb
+			_error2_("(detsa>=0) || (detsb<=0)");
+		}
+		Icoor2 ndet1 = bamg::det(s1,sa,s2);
+		Icoor2 ndet2 = detT - ndet1;
+
+		int ToSwap =0; //pas de swap
+		if ((ndet1 >0) && (ndet2 >0)) 
+		  { // on peut swaper  
+			if ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0))
+			 ToSwap =1; 
+			else // swap alleatoire 
+			 if (BinaryRand()) 
+			  ToSwap =2; 
+		  }
+		if (ToSwap) NbSwap++,
+		 bamg::swap(t1,a1,t2,a2,&s1,&s2,ndet1,ndet2);
+
+		int ret=1;
+
+		if (dets2 < 0) {// haut
+			dets1 = ToSwap ? dets1 : detsa ;
+			detsa = dets2; 
+			tt1 =  Previous(tt2) ;}
+		else if (dets2 > 0){// bas 
+			dets1 = ToSwap ? dets1 : detsb ;
+			detsb = dets2;
+			//xxxx tt1 = ToSwap ? tt1 : Next(tt2);
+			if(!ToSwap) tt1 =  Next(tt2);
+		}
+		else { // changement de direction 
+			ret = -1;
+			Exchange(pva,pvb);
+			Exchange(detsa,detsb);
+			Exchange(dets1,dets2);
+			Exchange(tt1,tt2);
+			dets1=-dets1;
+			dets2=-dets2;
+			detsa=-detsa;
+			detsb=-detsb;
+
+			if (ToSwap) 
+			 if (dets2 < 0) {// haut
+				 dets1 = (ToSwap ? dets1 : detsa) ;
+				 detsa = dets2; 
+				 tt1 =  Previous(tt2) ;}
+			 else if (dets2 > 0){// bas 
+				 dets1 = (ToSwap ? dets1 : detsb) ;
+				 detsb =  dets2;
+				 if(!ToSwap) tt1 =  Next(tt2);
+			 }
+			 else {// on a fin ???
+				 tt1 = Next(tt2);
+				 ret =0;}
+
+		}
+		return ret;
+	}
+	/*}}}*/
+
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/Mesh.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Mesh.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Mesh.h	(revision 12821)
@@ -0,0 +1,194 @@
+#ifndef _MESH_H_
+#define _MESH_H_
+
+#include "./include.h"
+#include "./BamgOpts.h"
+#include "./BamgMesh.h"
+#include "./BamgGeom.h"
+#include "./Triangle.h"
+#include "./VertexOnGeom.h"
+#include "./VertexOnVertex.h"
+#include "./VertexOnEdge.h"
+#include "./ListofIntersectionTriangles.h"
+
+namespace bamg {
+
+	//classes
+	class Geometry;
+	class CrackedEdge;
+	class BamgQuadtree;
+	class SubDomain;
+
+	class Mesh {
+
+		public:
+
+			Geometry                    & Gh;                    // Geometry
+			Mesh                        & BTh;                   // Background Mesh Bth== *this =>no background
+			BamgVertex                   *vertices;
+			Triangle                     *triangles;
+			Edge                         *edges;
+			BamgQuadtree                 *quadtree;
+			BamgVertex                  **orderedvertices;
+			SubDomain                    *subdomains;
+			long                          NbRef;                 // counter of ref on the this class if 0 we can delete
+			long                          maxnbv,maxnbt;         // nombre max de sommets , de triangles
+			long                          nbv,nbt,nbe,nbq;       // nb of vertices, of triangles, of edges and quadrilaterals
+			long                          nbsubdomains;
+			long                          nbtout;                // Nb of oudeside triangle
+
+			R2                            pmin,pmax;             // extrema
+			double                        coefIcoor;             // coef to integer Icoor1;
+			ListofIntersectionTriangles   lIntTria;
+
+			long                          NbVerticesOnGeomVertex;
+			VertexOnGeom                 *VerticesOnGeomVertex;
+			long                          NbVerticesOnGeomEdge;
+			VertexOnGeom                 *VerticesOnGeomEdge;
+			long                          NbVertexOnBThVertex;
+			VertexOnVertex               *VertexOnBThVertex;
+			long                          NbVertexOnBThEdge;
+			VertexOnEdge                 *VertexOnBThEdge;
+			long                          NbCrackedVertices;
+			long                         *CrackedVertices;
+			long                          NbCrackedEdges;
+			CrackedEdge                  *CrackedEdges;
+
+			//Constructors/Destructors
+			Mesh(BamgGeom* bamggeom,BamgMesh* bamgmesh,BamgOpts* bamgopts);
+			Mesh(int* index,double* x,double* y,int nods,int nels);/*MeshConvert*/
+			Mesh(double* x,double* y,int nods); /*BamgTriangulate*/
+			Mesh(Mesh &,Geometry * pGh=0,Mesh* pBTh=0,long maxnbv_in=0 ); //copy operator
+			Mesh(const Mesh &,const int *flag,const int *bb,BamgOpts* bamgopts); // truncature
+			Mesh(long maxnbv,Mesh & BT,BamgOpts* bamgopts,int keepBackVertices=1);
+			Mesh(long maxnbv,Geometry & G,BamgOpts* bamgopts);
+			~Mesh(); 
+
+			//Operators
+			const BamgVertex &operator[](long i) const { return vertices[i];  };
+			BamgVertex       &operator[](long i) { return vertices[i];        };
+			const Triangle   &operator()(long i) const { return triangles[i]; };
+			Triangle         &operator()(long  i) { return triangles[i];             };
+
+			//Methods
+			void SetIntCoor(const char * from =0);
+			double MinimalHmin();
+			double MaximalHmax();
+			I2 R2ToI2(const R2 & P) const;
+			R2 I2ToR2(const I2 & P) const;
+			void AddVertex(BamgVertex & s,Triangle * t,Icoor2 *  =0) ;
+			void Insert();
+			void Echo(void);
+			void ForceBoundary();
+			void FindSubDomain(int OutSide=0);
+			long TriangleReferenceList(long*) const;
+			void TriangleIntNumbering(long* renumbering);
+			void ShowHistogram() const;
+			void CrackMesh(BamgOpts* bamgopts);
+			void ShowRegulaty() const;
+			void SmoothMetric(double raisonmax) ;
+			void BoundAnisotropy(double anisomax,double hminaniso= 1e-100) ;
+			void MaxSubDivision(double maxsubdiv);
+			Edge** MakeGeomEdgeToEdge();
+			long SplitInternalEdgeWithBorderVertices();
+			void MakeQuadrangles(double costheta);
+			int  SplitElement(int choice);
+			void MakeBamgQuadtree();
+			void NewPoints(Mesh &,BamgOpts* bamgopts,int KeepVertices=1);
+			long InsertNewPoints(long nbvold,long & NbTSwap) ; 
+			void TrianglesRenumberBySubDomain(bool justcompress=false);
+			void VerticesRenumber(long * renu);
+			void SmoothingVertex(int =3,double=0.3);
+			Metric MetricAt (const R2 &) const;
+			GeomEdge* ProjectOnCurve( Edge & AB, BamgVertex &  A, BamgVertex & B,double theta, BamgVertex & R,VertexOnEdge & BR,VertexOnGeom & GR);
+			long GetId(const Triangle & t) const;
+			long GetId(const Triangle * t) const;
+			long GetId(const BamgVertex & t) const;
+			long GetId(const BamgVertex * t) const;
+			long GetId(const Edge & t) const;
+			long GetId(const Edge * t) const;
+			BamgVertex* NearestVertex(Icoor1 i,Icoor1 j) ;
+			Triangle* TriangleFindFromCoord(const I2 & ,Icoor2 [3],Triangle *tstart=0) const;
+			void ReadMesh(int* index,double* x,double* y,int nods,int nels);
+			void ReadMesh(BamgMesh* bamgmesh, BamgOpts* bamgopts);
+			void WriteMesh(BamgMesh* bamgmesh,BamgOpts* bamgopts);
+			void ReadMetric(const BamgOpts* bamgopts);
+			void WriteMetric(BamgOpts* bamgopts);
+			void WriteIndex(int** pindex,int* pnels);
+			void AddMetric(BamgOpts* bamgopts);
+			void BuildMetric0(BamgOpts* bamgopts);
+			void BuildMetric1(BamgOpts* bamgopts);
+			void AddGeometryMetric(BamgOpts* bamgopts);
+			int  isCracked() const;
+			void BuildGeometryFromMesh(BamgOpts* bamgopts=NULL);
+			void ReconstructExistingMesh();
+
+			//Inline methods
+			inline  void CreateSingleVertexToTriangleConnectivity(){
+				for (int i=0;i<nbv;i++) vertices[i].IndexInTriangle=0, vertices[i].t=NULL;
+				for (int i=0;i<nbt;i++) triangles[i].SetSingleVertexToTriangleConnectivity();
+			}
+			inline  void  UnMarkUnSwapTriangle(){
+				for (int i=0;i<nbt;i++)
+				 for(int j=0;j<3;j++)
+				  triangles[i].SetUnMarkUnSwap(j);
+			  }
+			inline  void  SetVertexFieldOn(){
+				for (int i=0;i<nbv;i++)                    vertices[i].GeomEdgeHook=NULL;
+				for (int j=0;j<NbVerticesOnGeomVertex;j++) VerticesOnGeomVertex[j].SetOn();
+				for (int k=0;k<NbVerticesOnGeomEdge;k++ )  VerticesOnGeomEdge[k].SetOn();
+			}	       
+			inline  void   SetVertexFieldOnBTh(){
+				for (int i=0;i<nbv;i++)                 vertices[i].GeomEdgeHook=NULL;
+				for (int j=0;j<NbVertexOnBThVertex;j++) VertexOnBThVertex[j].SetOnBTh();
+				for (int k=0;k<NbVertexOnBThEdge;k++ )  VertexOnBThEdge[k].SetOnBTh();
+			}
+
+		private:
+			void TriangulateFromGeom1(BamgOpts* bamgopts,int KeepVertices=1);// the real constructor mesh adaption
+			void TriangulateFromGeom0(BamgOpts* bamgopts);// the real constructor mesh generator
+			void Triangulate(double* x,double* y,int nods);
+			void Init(long);
+	};
+
+	/*Intermediary*/
+	AdjacentTriangle CloseBoundaryEdge(I2 ,Triangle *, double &,double &) ;
+	AdjacentTriangle CloseBoundaryEdgeV2(I2 A,Triangle *t, double &a,double &b);
+	void  swap(Triangle *t1,short a1,
+				Triangle *t2,short a2,
+				BamgVertex *s1,BamgVertex *s2,Icoor2 det1,Icoor2 det2);
+	int SwapForForcingEdge(BamgVertex   *  & pva ,BamgVertex  * &   pvb ,
+				AdjacentTriangle & tt1,Icoor2 & dets1,
+				Icoor2 & detsa,Icoor2 & detsb, int & nbswap);
+	int ForceEdge(BamgVertex &a, BamgVertex & b,AdjacentTriangle & taret) ;
+	inline AdjacentTriangle Previous(const AdjacentTriangle & ta){
+		return AdjacentTriangle(ta.t,PreviousEdge[ta.a]);
+	}
+	inline AdjacentTriangle Next(const AdjacentTriangle & ta){
+		return AdjacentTriangle(ta.t,NextEdge[ta.a]);
+	}
+	inline  AdjacentTriangle Adj(const AdjacentTriangle & a){
+		return  a.Adj();
+	}
+	inline void Adj(GeomEdge * & on,int &i){
+		int j=i;i=on->AdjVertexIndex[i];on=on->Adj[j];
+	}
+	inline double qualite(const BamgVertex &va,const BamgVertex &vb,const BamgVertex &vc){
+		double ret; 
+		I2 ia=va,ib=vb,ic=vc;
+		I2 ab=ib-ia,bc=ic-ib,ac=ic-ia;
+		Icoor2 deta=Det(ab,ac);
+		if (deta <=0) ret = -1;
+		else {
+			double a = sqrt((double) (ac,ac)),
+					 b = sqrt((double) (bc,bc)),
+					 c = sqrt((double) (ab,ab)),
+					 p = a+b+c;
+			double h= Max(Max(a,b),c),ro=deta/p;
+			ret = ro/h;
+		}
+		return ret;
+	}
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Metric.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Metric.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Metric.cpp	(revision 12821)
@@ -0,0 +1,353 @@
+#include <cstdio>
+#include <string.h>
+#include <cmath>
+
+#include "Metric.h"
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+
+using namespace std;
+
+namespace bamg {
+
+	SaveMetricInterpole  LastMetricInterpole;
+
+	/*Constructor/Destructor*/
+	/*FUNCTION Metric::Metric(double a){{{*/
+	Metric::Metric(double a): a11(1/(a*a)),a21(0),a22(1/(a*a)){
+	
+	}/*}}}*/
+	/*FUNCTION Metric::Metric(double a,double b,double c){{{*/
+	Metric::Metric(double a,double b,double c) :a11(a),a21(b),a22(c){
+	
+	}/*}}}*/
+	/*FUNCTION Metric::Metric(const double  a[3],const  Metric& m0, const  Metric& m1,const  Metric&  m2 ){{{*/ 
+	Metric::Metric(const double  a[3],const  Metric& m0, const  Metric& m1,const  Metric& m2 ){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/Metric)*/
+
+		Metric mab(a[0]*m0.a11 + a[1]*m1.a11 + a[2]*m2.a11,
+					a[0]*m0.a21 + a[1]*m1.a21 + a[2]*m2.a21,
+					a[0]*m0.a22 + a[1]*m1.a22 + a[2]*m2.a22);
+
+		EigenMetric vab(mab);
+
+		R2 v1(vab.v.x,vab.v.y);
+		R2 v2(-v1.y,v1.x);
+
+		double h1 = a[0] / m0(v1) + a[1] / m1(v1) + a[2] / m2(v1);
+		double h2 = a[0] / m0(v2) + a[1] / m1(v2) + a[2] / m2(v2);
+
+		vab.lambda1 =  1 / (h1*h1);
+		vab.lambda2 =  1 / (h2*h2);
+		*this = vab;
+	}
+	/*}}}*/
+	/*FUNCTION Metric::Metric(double  a,const  Metric& ma, double  b,const  Metric& mb){{{*/
+	Metric::Metric(double  a,const  Metric& ma, double  b,const  Metric& mb) { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/EigenMetric)*/
+
+		/*Compute metric (linear combination of ma and mb)*/
+		Metric mab(a*ma.a11+b*mb.a11,a*ma.a21+b*mb.a21,a*ma.a22+b*mb.a22);
+
+		/*Get Eigen values and vectors*/
+		EigenMetric vab(mab);
+		R2 v1(vab.v.x,vab.v.y);
+		R2 v2(-v1.y,v1.x);
+
+		/*Modify eigen values (a+b=1)*/
+		double h1 = a/ma(v1) + b/mb(v1);
+		double h2 = a/ma(v2) + b/mb(v2);
+		vab.lambda1 =  1/(h1*h1);
+		vab.lambda2 =  1/(h2*h2);
+		*this=vab;
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Metric::det{{{*/
+	double Metric::det() const {
+		return a11*a22-a21*a21;
+	}  /*}}}*/
+	/*FUNCTION Metric::Echo {{{*/
+	void Metric::Echo(void){
+
+		_printLine_("Metric:");
+		_printLine_("   [a11 a21 a22]: [" << a11 << " " << a21 << " " << a22 << "]");
+
+		return;
+	}
+	/*}}}*/
+	/*FUNCTION Metric::IntersectWith{{{*/
+	int Metric::IntersectWith(const Metric& M2) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/IntersectWith)*/
+
+		/*Get a new metric from an existing metric (M1=this)
+		 * and a new metric given in input M2 using a 
+		 * Simultaneous Matrix Reduction:
+		 * If M1 and M2 are 2 metrics, we must build N=M1^-1 M2 (Alauzet2003 p16) 
+		 * the eigen vectors of N form a matrix P
+		 * The new metric M = M1 inter M2 is then given by:
+		 *
+		 *      -T [ max(lambda1, mu1)          0         ]  -1				 
+		 * M = P   [                                      ] P		 
+		 *         [        0            max(lambda2, mu2)] 
+		 *
+		 * where lambdai and mui can be computed using Rayleigh formula: 
+		 *    lambdai = vi' M1 vi
+		 * with vi eigen vectors of N (columns of P)
+		 */
+
+		int         change=0;
+		Metric &M1=*this;
+		D2xD2       P;
+
+		//Get P, eigen vectors of N=inv(M1) M2
+		SimultaneousMatrixReduction(*this,M2,P);
+
+		//extract the eigen vectors of P (columns)
+		R2 v1(P.x.x,P.y.x);
+		R2 v2(P.x.y,P.y.y);
+
+		//compute lambdai mui
+		double lambda1=M1(v1,v1);
+		double lambda2=M1(v2,v2);
+		double mu1=M2(v1,v1);
+		double mu2=M2(v2,v2);
+
+		//check where any change needs to be done on M1
+		if ( lambda1 < mu1 )  change=1,lambda1=mu1;
+		if ( lambda2 < mu2 )  change=1,lambda2=mu2; 
+
+		//update M1 if necessary
+		if (change) {
+			D2xD2 invP(P.inv());
+			D2xD2 D(lambda1,0,0,lambda2); 
+			D2xD2 M(invP.t()*D*invP);
+			a11=M.x.x;
+			a21=0.5*(M.x.y+M.y.x);
+			a22=M.y.y;
+		}
+		return change;
+	}
+	/*}}}*/
+	/*FUNCTION Metric::mul{{{*/
+	R2     Metric::mul(const R2 x)const {
+		return R2(a11*x.x+a21*x.y,a21*x.x+a22*x.y);
+	}/*}}}*/
+
+	/*Intermediary*/
+	/*FUNCTION LengthInterpole{{{*/
+	double LengthInterpole(const Metric& Ma,const  Metric& Mb, R2 AB) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/LengthInterpole)*/
+
+		double k=1./2.;
+		int level=0;
+		static int kkk=0;
+		static  Metric Ms1[32],Ms2[32];
+		static double lMs1[32],lMs2[32];
+		static double K[32];
+		double l=0,sss=0;
+		Ms1[level]=Ma;
+		Ms2[level]=Mb;
+		double sa =  Ma(AB);
+		double sb =  Mb(AB);
+		lMs1[level]=sa;
+		lMs2[level]=sb;
+		K[level]=k;
+		level++;
+		int i=0;
+		double * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+		double  sstop = 0.1; // Max(0.6,(sa+sb)/5000);
+		while (level) {
+			level--;
+			Metric M1=Ms1[level];
+			Metric M2=Ms2[level];
+			k=K[level];
+			double s1=  lMs1[level];
+			double s2=  lMs2[level];
+
+			double s= (s1+s2)*k;
+			if( s > sstop   && level < 30 && i < 500-level ) {
+				Metric Mi(0.5,M1,0.5,M2);
+				double si = Mi(AB);
+				if( Abs((s1+s2)-(si+si)) > s1*0.001) 
+				  {
+					k=k/2;
+					// we begin by the end to walk in the correct direction from a to b
+					// due to the stack 
+					Ms1[level]=Mi;
+					Ms2[level]=M2;
+					lMs1[level]=si;
+					lMs2[level]=s2;
+					K[level]=k;
+					level++;
+					Ms1[level]=M1;
+					Ms2[level]=Mi;
+					lMs1[level]=s1;
+					lMs2[level]=si;
+					K[level]=k;
+					level++;
+				  }
+				else
+				 L[i]= l += s,S[i]=sss+=k,i++;
+			}
+			else 
+			 L[i]= l += s,S[i]=sss+=k,i++;
+		}
+		// warning for optimisation S is in [0:0.5] not in [0:1]
+		if (i>=512){
+			_error2_("i>=512");
+		}
+		LastMetricInterpole.lab=l;
+		LastMetricInterpole.opt=i;
+		if (i>200 && kkk++<10) _printLine_("WARNING: LengthInterpole: ( i=" << i << " l=" << l << " sss=" << sss << " ) " << sstop); 
+		return l;
+	}
+	/*}}}*/
+	/*FUNCTION SimultaneousMatrixReduction{{{*/
+	void SimultaneousMatrixReduction( Metric M1,  Metric M2, D2xD2 &V) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/ReductionSimultanee)*/
+
+		/*In this routine we must return a matrix V that is composed of the 
+		 * eigen vectors of N=inv(M1) M2.
+		 * Instead of looking at N directly, we are going to use the fact that
+		 * M1 and M2 are symmetrical, positive definite. 
+		 * The eigen values of N are given by solving
+		 *    inv(M1) M2 V = lambda V
+		 * which is equivalent to
+		 *    M2 V = lambda M1 V
+		 * and we will hence solve
+		 *    (M2 - lambda M1) V = 0
+		 */
+
+		//M1 and M2 components
+		double a11=M1.a11,a21=M1.a21,a22=M1.a22;
+		double b11=M2.a11,b21=M2.a21,b22=M2.a22;
+
+		/*To get the eigen values, we solve the following problem:
+		 *    det(M2-lambda M1) = 0
+		 *    (b11 - lambda a11)(b22-lambda a22) - (b21-lambda a21)^2
+		 * and we have the following trinome:
+		 *    a lambda^2 + b lambda + c =0
+		 * with:
+		 *    a = a11 a22 - a21 a21 (=det(M1))
+		 *    b = -a11 b22 -b11 a22 + 2 b21 a21
+		 *    c = b11 b22 - b21 b21 (=det(M2))
+		 *    */
+		const double a= a11*a22  - a21*a21;
+		const double b=-a11*b22 - b11*a22+2*b21*a21;
+		const double c=-b21*b21 + b11*b22;
+		const double bb=b*b,ac=a*c;
+		const double delta= bb-4*ac;
+
+		// first, case of a double root if:
+		//  - all the terms are very small (a??)
+		//  - or : delta is very small
+		if ( (bb + Abs(ac) < 1.0e-34 ) ||  (delta < 1.0e-6*bb) ){
+			//all vectors are eigen vectors -> choose 1,0 and 0,1
+			V= D2xD2(1,0,0,1);
+		}
+
+		//general case: two distinct roots: lambda1 and lambda2
+		else {
+
+			/*Compute eigen values*/
+			const double delta2 = sqrt(delta);
+			double lambda[2];
+			lambda[0]= (-b - delta2)/(2*a);
+			lambda[1]= (-b + delta2)/(2*a);
+
+			/*compute eigen vectors*/
+			double vp[2][2];
+			double v0,v1,v2;
+			double s0,s1;
+
+			for(int i=0;i<2;i++){
+				/*Now, one must find the eigen vectors. For that we use the 
+				 * following property of the inner product
+				 *    (Ax,b) = transp(b) Ax = transp(x) transp(A) b
+				 *           = (transp(A) b ,x)
+				 * Here we are dealing with A= M2 - lambda M1 which is symmetrical:
+				 *    for all (x,y) in R2 
+				 *       ((M2 - lambda M1)x,y)=((M2 - lambda M1)y,x)
+				 * If y is in Ker(M2 - lambda M1):
+				 *    for all x in R2
+				 *       ((M2 - lambda M1)y,x)=0
+				 * This shows that:
+				 *    Ker(M2 - lambda M1) is orthogonal to Im(M2 - lambda M1)
+				 * To find the eigen vectors, we only have to find two vectors
+				 * of the image and take their perpendicular as long as they are
+				 * not 0.
+				 * To do that, we take (1,0) and (0,1) and take the larger norm*/
+
+				//compute V = M2 - lambdai M1
+				v0 = b11 - lambda[i]*a11;
+				v1 = b21 - lambda[i]*a21;
+				v2 = b22 - lambda[i]*a22;
+
+				// compute s1=norm(V(1,0)) and s0=norm(V(0,1))
+				s0 = v0*v0 + v1*v1;
+				s1 = v1*v1 + v2*v2;
+
+				//compute vp1 = (vp1x,vp1y)
+				if(s1 < s0){
+					s0=sqrt(s0);
+					vp[0][i]=   v1/s0;
+					vp[1][i]= - v0/s0;
+				}
+				else{
+					s1=sqrt(s1);
+					vp[0][i]=   v2/s1;
+					vp[1][i]= - v1/s1;
+				}
+			}
+
+			//compute V from vp
+			V=D2xD2(vp[0][0],vp[0][1],vp[1][0],vp[1][1]);
+		}
+	}
+	/*}}}*/
+	/*FUNCTION abscisseInterpole{{{*/
+	double abscisseInterpole(const Metric& Ma,const  Metric& Mb, R2 AB,double s,int optim) { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Metric.cpp/abscisseInterpole)*/
+
+		if(!optim)  LengthInterpole(Ma,Mb,AB);
+		double l  = s* LastMetricInterpole.lab,r;
+		int j=LastMetricInterpole.opt-1;
+
+		double * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+		// warning for optimisation S is the abcisse in [0:0.5]
+		// and L is le lenght 
+		if(l<=L[0]){
+			r=2*S[0]*l/L[0];
+		}
+		else if (l>=L[j]){
+			r=1;
+		}
+		else{
+			int i=0;
+			while (j-i>1){
+				int k;
+				k= (i+j)/2;
+				if(l<=L[k]){
+					j=k;// l<=L[j] 
+				}
+				else{
+					i=k; //  L[i]<l
+				}
+			};
+			if (i==j){
+				r = 2*S[i];
+			}
+			else{
+				r =  2*(S[i]*(L[j]-l)+ S[j]*(l-L[i]))/(L[j]-L[i]);
+			}
+		}
+		if (r>1 || r<0){
+			_error2_("r>1 || r<0");
+		}
+		return r ;
+	}
+	/*}}}*/
+
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/Metric.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Metric.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Metric.h	(revision 12821)
@@ -0,0 +1,138 @@
+#ifndef _METRIC_H
+#define _METRIC_H
+
+#include "./include.h"
+#include "../../shared/Bamg/shared.h"
+#include "R2.h"
+#include <math.h>
+
+namespace bamg {
+
+	typedef P2<double,double>    D2;
+	typedef P2xP2<double,double> D2xD2;
+
+	class Metric;
+	class EigenMetric;
+
+	class Metric{
+
+		public:
+
+			//fields
+			double a11,a21,a22;
+
+			//friends
+			friend class EigenMetric;
+
+			//functions
+			Metric():a11(0),a21(0),a22(0){};
+			Metric(const EigenMetric&);
+			Metric(double a);
+			Metric(double a,double b,double c);
+			Metric( double  a,const  Metric& ma, double  b,const  Metric& mb);
+			Metric(const double  a[3],const  Metric& m0,const  Metric& m1,const  Metric& m2 );
+			void        Echo();
+			R2          mul(const R2 x)const;
+			double      det() const;
+			int         IntersectWith(const  Metric& M2);
+			inline void Box(double &hx,double &hy) const;
+
+			/*The following functions must remain the the header file because it is called before Metric
+			 * is compiled by other classes*/
+			R2 Orthogonal(const R2 x){ return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y); }
+			R2 Orthogonal(const I2 x){ return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y); }
+
+			//operators
+			Metric operator*(double c) const {double c2=c*c;return  Metric(a11*c2,a21*c2,a22*c2);} 
+			Metric operator/(double c) const {double c2=1/(c*c);return  Metric(a11*c2,a21*c2,a22*c2);} 
+			operator D2xD2(){ return D2xD2(a11,a21,a21,a22);}
+			double  operator()(R2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};        // length of x in metric sqrt(<Mx,x>)
+			double  operator()(R2 x,R2 y) const { return x.x*y.x*a11+(x.x*x.y+x.y*y.x)*a21+x.y*y.y*a22;};
+
+	};
+
+	class EigenMetric{
+		public:
+
+			//fields
+			double lambda1,lambda2;
+			D2     v;
+
+			//friends
+			friend  class Metric;
+
+			//functions
+			EigenMetric(const Metric& );
+			EigenMetric(double r1,double r2,const D2& vp1);
+			void   Echo();
+			void   Abs();
+			void   pow(double  p);
+			void   Min(double  a);
+			void   Max(double  a);
+			void   Minh(double h);
+			void   Maxh(double h);
+			void   Isotrope();
+			double hmin()   const;
+			double hmax()   const;
+			double lmax()   const;
+			double lmin()   const;
+			double Aniso2() const;
+			double Aniso()  const;
+			void   BoundAniso(const  double c);
+			inline void BoundAniso2(const double coef);
+
+			//operators
+			void operator *=(double coef){ lambda1*=coef;lambda2*=coef;}
+	};
+
+	class SaveMetricInterpole {
+		friend double LengthInterpole(const Metric& Ma,const  Metric& Mb, R2 AB);
+		friend double abscisseInterpole(const Metric& Ma ,const  Metric& Mb, R2 ,double s,int optim);
+		public:
+		int opt;
+		double lab;
+		double L[1024],S[1024];
+	};
+
+	extern SaveMetricInterpole  LastMetricInterpole; // for optimization 
+	//Functions
+	void  SimultaneousMatrixReduction( Metric M1,  Metric M2,D2xD2 &V);
+	double LengthInterpole(const Metric& Ma,const  Metric& Mb, R2 AB);
+	double abscisseInterpole(const Metric& Ma,const  Metric& Mb, R2 AB,double s,int optim=0);
+
+	//inlines
+	inline void  EigenMetric::BoundAniso2(const double coef){
+		if (coef<=1.00000000001){
+			if (lambda1 < lambda2)
+			 lambda1 = bamg::Max(lambda1,lambda2*coef);
+			else
+			 lambda2 = bamg::Max(lambda2,lambda1*coef);
+		}
+		else{  //TO BE CHECKED
+			if (lambda1 > lambda2)
+			 lambda1 = bamg::Min(lambda1,lambda2*coef);
+			else
+			 lambda2 = bamg::Min(lambda2,lambda1*coef);
+		}
+	}
+	inline Metric::Metric(const EigenMetric& M) {
+		double v00=M.v.x*M.v.x;
+		double v11=M.v.y*M.v.y;
+		double v01=M.v.x*M.v.y;
+		a11=v00*M.lambda1+v11*M.lambda2;
+		a21=v01*(M.lambda1-M.lambda2);
+		a22=v00*M.lambda2+v11*M.lambda1;
+	}
+	inline   void  Metric::Box(double &hx,double &hy) const {
+		double d=  a11*a22-a21*a21;
+		hx = sqrt(a22/d);
+		hy = sqrt(a11/d);
+	}
+	inline double LengthInterpole(double la,double lb) {
+		return ( Abs(la - lb) < 1.0e-6*Max3(la,lb,1.0e-20) ) ?  (la+lb)/2  : la*lb*log(la/lb)/(la-lb);
+	}
+	inline double abscisseInterpole(double la,double lb,double lab,double s){
+		return ( Abs(la - lb) <1.0e-6*Max3(la,lb,1.0e-20))  ? s : (exp(s*lab*(la-lb)/(la*lb))-1)*lb/(la-lb);
+	}
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/R2.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/R2.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/R2.h	(revision 12821)
@@ -0,0 +1,105 @@
+/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, R2.h)*/
+#ifndef _R2_H
+#define _R2_H
+
+#include <cstdio>
+
+namespace bamg {
+
+	template <class R,class RR> class P2{
+
+		  public:  
+
+			  //fields
+			  R x,y;
+
+			  //functions
+			  P2 () :x(0),y(0) {};
+			  P2 (R a,R b)  :x(a),y(b)  {}
+			  P2 (P2 A,P2 B) : x(B.x-A.x),y(B.y-A.y) {}
+			  void Echo(){
+				  printf("Member of P2:\n");
+				  printf("   x: %g or %i\n",x,x);
+				  printf("   y: %g or %i\n",y,y);
+			  }
+			  //operators
+			  RR       operator,(const P2<R,RR> & cc) const {return  (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} //scalar product
+			  P2<R,RR> operator+(const P2<R,RR> & cc) const {return P2<R,RR>(x+cc.x,y+cc.y);}
+			  P2<R,RR> operator-(const P2<R,RR> & cc) const {return P2<R,RR>(x-cc.x,y-cc.y);}
+			  P2<R,RR> operator-()  const{return P2<R,RR>(-x,-y);}
+			  P2<R,RR> operator*(R  cc) const {return P2<R,RR>(x*cc,y*cc);}
+			  P2<R,RR> operator/(R  cc) const {return P2<R,RR>(x/cc,y/cc);}
+			  P2<R,RR> operator+=(const  P2<R,RR> & cc) {x += cc.x;y += cc.y;return *this;}
+			  P2<R,RR> operator/=(const  R r) {x /= r;y /= r;return *this;}
+			  P2<R,RR> operator*=(const  R r) {x *= r;y *= r;return *this;}
+			  P2<R,RR> operator-=(const  P2<R,RR> & cc) {x -= cc.x;y -= cc.y;return *this;}
+
+	  };
+
+	template <class R,class RR> class P2xP2{
+
+		  private:
+
+			  friend P2<R,RR> operator*(P2<R,RR> c,P2xP2<R,RR> cc){
+				  return P2<R,RR>(c.x*cc.x.x + c.y*cc.y.x, c.x*cc.x.y + c.y*cc.y.y);
+			  } 
+		  public:
+
+			  //fields
+			  P2<R,RR> x,y; 
+
+			  //functions
+			  P2xP2 (): x(),y()  {}
+			  P2xP2 (P2<R,RR> a,P2<R,RR> b): x(a),y(b) {}
+			  P2xP2 (P2<R,RR> a,P2<R,RR> b,P2<R,RR> c ): x(b-a),y(c-a) {}
+			  P2xP2 (R xx,R xy,R yx,R yy) :x(xx,xy),y(yx,yy) {}
+			  void Echo(){
+				  printf("Member of P2xP2:\n");
+				  printf("   x.x: %g   x.y: %g\n",x.x,x.y);
+				  printf("   y.x: %g   y.x: %g\n",y.x,y.y);
+			  }
+			  RR          det() const {return (RR) x.x* (RR) y.y - (RR) x.y * (RR) y.x;}
+			  P2xP2<R,RR> inv()  const{
+				  RR d = (*this).det(); 
+				  return P2xP2<R,RR>((R)( y.y /d) ,(R)(-x.y/d),(R)( -y.x/d) ,(R)( x.x/d) );
+			  };
+			  P2xP2<R,RR> t()  {return P2xP2<R,RR>(x.x,y.x,x.y,y.y);} //transposer 
+			  P2<R,RR>    tx() {return P2<R,RR>(x.x,y.x);} 
+			  P2<R,RR>    ty() {return P2<R,RR>(x.y,y.y);} 
+			  //Operators
+			  P2<R,RR>     operator*(const P2<R,RR>& c) const {return P2<R,RR>(x.x*c.x + x.y*c.y, y.x*c.x + y.y*c.y);}
+			  P2xP2<R,RR>  operator*(P2xP2<R,RR> c) const{
+				  return  P2xP2<R,RR>(x.x*c.x.x + x.y*c.y.x,
+							  x.x*c.x.y + x.y*c.y.y,
+							  y.x*c.x.x + y.y*c.y.x,
+							  y.x*c.x.y + y.y*c.y.y);
+			  }
+	  };  
+
+	//inline functions
+	template  <class R,class RR>  
+	  inline RR Det(const P2<R,RR> x,const P2<R,RR> y) {
+		  return (RR) x.x * (RR) y.y - (RR) x.y * (RR) y.x ;
+	  } 
+	template  <class R,class RR>  
+	  inline RR Area2 (const P2<R,RR> a,const P2<R,RR> b,const P2<R,RR> c) {
+		  return Det(b-a,c-a) ;
+	  }
+	template  <class R,class RR>  
+	  inline R Norme1 (const P2<R,RR> x) {
+		  return (Abs(x.x)+Abs(x.y)) ;
+	  } 
+	template  <class R,class RR>  
+	  inline RR Norme2_2 (const P2<R,RR> x) {
+		  return (RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y ;
+	  } 
+	template  <class R,class RR>  
+	  inline RR Norme2 (const P2<R,RR> x) {
+		  return sqrt((RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y) ;
+	  } 
+	template  <class R,class RR>  
+	  inline P2<R,RR> Orthogonal (const P2<R,RR> x) {
+		  return  P2<R,RR>(-x.y,x.x);
+	  } 
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.cpp	(revision 12821)
@@ -0,0 +1,120 @@
+#include "../objects.h"
+
+using namespace std;
+namespace bamg {
+
+	/*Constructor*/
+	/*FUNCTION  SetOfEdges4::SetOfEdges4(long mmx,long nnx){{{*/
+	SetOfEdges4::SetOfEdges4(long mmx,long nnx){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, SetOfEdges4.cpp/SetOfEdges4)*/
+
+		/*Intermediary*/
+		int i;
+
+		//initialize fields
+		nx   =nnx;   //number of vertices
+		nbax =mmx;   // 3 * number of triangles
+		NbOfEdges=0;
+		head = new long [nx];
+		Edges= new IntEdge[nbax];
+
+		//initialize head (-1 everywhere)
+		i=nx;
+		while(i--) head[i]=-1;
+	}
+	/*}}}*/
+
+	/*Methods*/ 
+	/*FUNCTION  SetOfEdges4::add{{{*/
+	long SetOfEdges4::add(long ii,long jj) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, SetOfEdges4.cpp/add)*/
+
+		/*Intermediary*/
+		int h,n;
+
+		//get n from h (usually h=ii)
+		_assert_(head);
+		n=head[h=Abs(ii)%nx];
+
+		//go through the existing edges that holds h (=ii) and check that 
+		//the edge ii jj is not already in Edge
+		while (n >= 0){
+
+			//if the edge ii jj is already in Edges, return n
+			if (ii == Edges[n].i && jj == Edges[n].j) return n;
+
+			//else go to next edge that holds ii
+			else n = Edges[n].next;
+		}
+
+		//check that nbax <=NbOfEdges
+		if (nbax <=NbOfEdges ) {
+			_error2_("SetOfEdges4::add overflow: NbOfEdges=" << NbOfEdges << " > nbax=" << nbax);
+		}
+
+		//update chain
+		Edges[NbOfEdges].i=ii;
+		Edges[NbOfEdges].j=jj;
+		Edges[NbOfEdges].next= head[h];
+		head[h] = NbOfEdges;
+		return NbOfEdges ++;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::find {{{*/
+	long SetOfEdges4::find(long ii,long jj) { 
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, SetOfEdges4.cpp/find)*/
+
+		/*Intermediary*/
+		int n;
+
+		//check that head is not empty
+		_assert_(head);
+
+		//get n from h (usually h=ii)
+		n=head[Abs(ii)%nx];
+
+		//go through the existing edges that holds h (=ii) and return position in Edge
+		while (n >= 0){
+
+			//if the edge ii jj is already in Edges, return n
+			if (ii == Edges[n].i && jj == Edges[n].j) return n;
+
+			//else go to next edge that holds ii
+			else n = Edges[n].next;
+		}
+
+		//if we reach this point, the edge does not exist return -1
+		return -1;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::i{{{*/
+	long SetOfEdges4::i(long k){
+		return Edges[k].i;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::j{{{*/
+	long SetOfEdges4::j(long k){
+		return Edges[k].j;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::nb{{{*/
+	long SetOfEdges4::nb(){
+		return NbOfEdges;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::newarete{{{*/
+	long SetOfEdges4::newarete(long k){
+		return NbOfEdges == k+1;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::SortAndAdd{{{*/
+	long SetOfEdges4::SortAndAdd (long ii,long jj) {
+		return ii <=jj ? add (ii,jj)  : add (jj,ii) ;
+	}
+	/*}}}*/
+	/*FUNCTION  SetOfEdges4::SortAndFind{{{*/
+	long SetOfEdges4::SortAndFind (long ii,long jj) {
+		return ii <=jj ? find (ii,jj)  : find (jj,ii) ;
+	}
+	/*}}}*/
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/SetOfE4.h	(revision 12821)
@@ -0,0 +1,42 @@
+#ifndef _SetOfEdge4_h
+#define _SetOfEdge4_h
+
+namespace bamg {
+
+	class SetOfEdges4;
+
+	class IntEdge{
+		friend class SetOfEdges4;
+		public:
+		long i,j;
+		long next; 
+	};
+
+	class SetOfEdges4 {
+
+		private:
+			long nx,nbax,NbOfEdges;
+			long* head; 
+			IntEdge* Edges;
+
+		public:
+
+			// Constructors
+			SetOfEdges4(long ,long);// nb Edges mx , nb de sommet 
+			~SetOfEdges4() {delete [] head; delete [] Edges;}
+
+			//operators
+			IntEdge & operator[](long k){return  Edges[k];}
+
+			//Methods
+			long add (long ii,long jj);
+			long SortAndAdd (long ii,long jj);
+			long nb();
+			long find (long ii,long jj);
+			long SortAndFind (long ii,long jj);
+			long i(long k);
+			long j(long k);
+			long newarete(long k);
+	};
+}
+#endif 
Index: /issm/trunk-jpl/src/c/classes/bamg/SubDomain.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/SubDomain.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/SubDomain.cpp	(revision 12821)
@@ -0,0 +1,28 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "SubDomain.h"
+#include "Mesh.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+
+	/*Methods*/
+	/*FUNCTION SubDomain::Set {{{*/
+	void SubDomain::Set(const Mesh & Th ,long i,Mesh & ThNew){
+		*this = Th.subdomains[i];
+		if ( head-Th.triangles<0 || head-Th.triangles>=Th.nbt){
+			_error2_("head-Th.triangles<0 || head-Th.triangles>=Th.nbt");
+		}
+		head = ThNew.triangles + Th.GetId(head) ; 
+		if (edge-Th.edges<0 || edge-Th.edges>=Th.nbe);{
+			_error2_("edge-Th.edges<0 || edge-Th.edges>=Th.nbe");
+		}
+		edge = ThNew.edges+ Th.GetId(edge);
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/SubDomain.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/SubDomain.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/SubDomain.h	(revision 12821)
@@ -0,0 +1,27 @@
+#ifndef _SUBDOMAIN_H_
+#define _SUBDOMAIN_H_
+
+#include "./include.h"
+#include "./Edge.h"
+
+namespace bamg {
+
+	//classes
+	class Triangle;
+	class Mesh;
+
+	class SubDomain {
+
+		public:
+
+			Triangle *head;
+			long      ReferenceNumber;
+			int       direction;   // -1 or 1
+			Edge     *edge;        // to geometrical
+
+			//Methods
+			void Set(const Mesh &,long,Mesh &);
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/Triangle.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Triangle.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Triangle.cpp	(revision 12821)
@@ -0,0 +1,491 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "../objects.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION Triangle(){{{*/
+	Triangle::Triangle(void){
+
+	}
+	/*}}}*/
+	/*FUNCTION Triangle(Mesh *Th,long i,long j,long k) {{{*/
+	Triangle::Triangle(Mesh *Th,long i,long j,long k) {
+		BamgVertex *v=Th->vertices;
+		long nbv = Th->nbv;
+		if (i<0 || j<0 || k<0){
+			_error2_("i<0 || j<0 || k<0");
+		}
+		if (i>=nbv || j>=nbv || k>=nbv){
+			_error2_("i>=nbv || j>=nbv || k>=nbv");
+		}
+		vertices[0]=v+i;
+		vertices[1]=v+j;
+		vertices[2]=v+k;
+		adj[0]=adj[1]=adj[2]=0;
+		AdjEdgeIndex[0]=AdjEdgeIndex[1]=AdjEdgeIndex[2]=0;
+		det=0;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle(BamgVertex *v0,BamgVertex *v1,BamgVertex *v2) {{{*/
+	Triangle::Triangle(BamgVertex *v0,BamgVertex *v1,BamgVertex *v2){
+		vertices[0]=v0;
+		vertices[1]=v1;
+		vertices[2]=v2;
+		adj[0]=adj[1]=adj[2]=0;
+		AdjEdgeIndex[0]=AdjEdgeIndex[1]=AdjEdgeIndex[2]=0;
+		if (v0) det=0;
+		else {
+			det=-1;
+			link=NULL;};  
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION Triangle::Adj{{{*/
+	AdjacentTriangle Triangle::Adj(int i)  const {
+		return AdjacentTriangle(adj[i],AdjEdgeIndex[i]&3);
+	};/*}}}*/
+	/*FUNCTION Triangle::Anisotropy{{{*/
+	double Triangle::Anisotropy() const{
+
+		double lmin,lmax;
+
+		/*Get three vertices A,B and C*/
+		R2 A=*this->vertices[0];
+		R2 B=*this->vertices[1];
+		R2 C=*this->vertices[2];
+
+		/*Compute edges*/
+		R2 e1=B-A;
+		R2 e2=C-A;
+		R2 e3=B-C;
+
+		/*Compute edge length*/
+		double l1=Norme2(e1);
+		double l2=Norme2(e2);
+		double l3=Norme2(e3);
+
+		lmin=l1;
+		lmin=min(lmin,l2);
+		lmin=min(lmin,l3);
+		lmax=l1;
+		lmax=max(lmax,l2);
+		lmax=max(lmax,l3);
+
+		return lmax/lmin;
+	};/*}}}*/
+	/*FUNCTION Triangle::Length{{{*/
+	double Triangle::Length() const{
+
+		double l;
+
+		/*Get three vertices A,B and C*/
+		R2 A=*this->vertices[0];
+		R2 B=*this->vertices[1];
+		R2 C=*this->vertices[2];
+
+		/*Compute edges*/
+		R2 e1=B-A;
+		R2 e2=C-A;
+		R2 e3=B-C;
+
+		/*Compute edge length*/
+		l=Norme2(e1);
+		l=max(l,Norme2(e2));
+		l=max(l,Norme2(e3));
+
+		return l;
+	};/*}}}*/
+	/*FUNCTION Triangle::Echo {{{*/
+	void Triangle::Echo(void){
+
+		int i;
+
+		_printLine_("Triangle:");
+		_printLine_("   vertices pointer towards three vertices");
+		_printLine_("      vertices[0] vertices[1] vertices[2] = " << vertices[0] << " " << vertices[1] << " " << vertices[2]);
+		_printLine_("   adj pointer towards three adjacent triangles");
+		_printLine_("      adj[0] adj[1] adj[2] = " << adj[0] << " " << adj[1] << " " << adj[2]);
+		_printLine_("   det (integer triangle determinant) = " << det);
+		if (link){
+			_printLine_("   link (pointer toward duplicate triangle)= " << link);
+		}
+		else{
+			_printLine_("   color = " << color);
+		}
+
+		_printLine_("\nThree vertices:");
+		for(i=0;i<3;i++){
+			if (vertices[i]){
+				vertices[i]->Echo();
+			}
+			else{
+				_printLine_("   vertex " << i+1 << " does not exist");
+			}
+		}
+
+		return;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::FindBoundaryEdge{{{*/
+	AdjacentTriangle Triangle::FindBoundaryEdge(int i) const{
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/FindBoundaryEdge)*/
+
+		/*Intermediary*/
+		Triangle* ttc=NULL;
+		int k,j,jc;
+
+		// call current triangle t
+		Triangle* t = (Triangle*)this;
+
+		//is the current triangle inside or outside?
+		int outside=!link  ;
+
+		// EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}};
+		// initialize j as the first vertex of the ith edge
+		j=EdgesVertexTriangle[i][0];
+
+		//Loop over the adjacent triangle of t
+		k=0;
+		do{
+			//keep track of outside
+			int outsidep = outside;
+			//increment k
+			k++;
+			//Get ttc, adjacent triangle of t with respect to vertex j
+			ttc =  t->adj[j];
+			//is the current triangle inside or outside?
+			outside = !ttc->link;
+			//if both previous triangle are outside, return
+			if (outside+outsidep == 1) return AdjacentTriangle(t,j);
+
+			//update t and j
+			t = ttc;
+			//NextEdge[3] = {1,2,0};
+			jc = NextEdge[t->AdjEdgeIndex[j]&3];
+			j = NextEdge[jc];
+
+			//check number of iterations
+			if (k>=2000){
+				_error2_("too many iteration in Triangle::FindBoundaryEdge (k>=2000)");
+			}
+		} while (this!= t);
+		//not found, return empty triangle
+		return AdjacentTriangle(NULL,0);
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::GetAllflag{{{*/
+	int    Triangle::GetAllflag(int a){
+		return AdjEdgeIndex[a] & 1020;
+	}/*}}}*/
+	/*FUNCTION Triangle::Hidden{{{*/
+	int    Triangle::Hidden(int a)const {
+		return AdjEdgeIndex[a]&16;
+	} /*}}}*/
+	/*FUNCTION Triangle::Locked{{{*/
+	int    Triangle::Locked(int a)const {
+		return AdjEdgeIndex[a]&4;
+	} /*}}}*/
+	/*FUNCTION Triangle::NuEdgeTriangleAdj{{{*/
+	short  Triangle::NuEdgeTriangleAdj(int i) const {
+		/*Number of the  adjacent edge in adj tria (make sure it is between 0 and 2*/
+		return AdjEdgeIndex[i&3]&3;
+	}/*}}}*/
+	/*FUNCTION Triangle::Optim{{{*/
+	long  Triangle::Optim(short i,int koption) {
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/Optim)*/
+
+		// turn around (positive direction)
+		Triangle *t=this;
+		long NbSwap =0;
+		int  k = 0;
+		int  j = OppositeEdge[i];
+		int  jp= PreviousEdge[j];
+
+		// initialize tp, jp the previous triangle & edge
+		Triangle *tp=adj[jp];
+		jp = AdjEdgeIndex[jp]&3;
+		do {
+			while (t->swap(j,koption)){
+				if (k>=20000) _error2_("k>=20000");
+				NbSwap++;
+				k++;
+				t=  tp->adj[jp];      // set unchange t qnd j for previous triangles
+				j=  NextEdge[tp->AdjEdgeIndex[jp]&3];
+			}
+			// end on this  Triangle 
+			tp = t;
+			jp = NextEdge[j];
+
+			t=  tp->adj[jp];      // set unchange t qnd j for previous triangles
+			j=  NextEdge[tp->AdjEdgeIndex[jp]&3];
+
+		} while( t != this);
+		return NbSwap;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::Quadrangle {{{*/
+	Triangle* Triangle::Quadrangle(BamgVertex * & v0,BamgVertex * & v1,BamgVertex * & v2,BamgVertex * & v3) const{
+		// return the other triangle of the quad if a quad or 0 if not a quat
+		Triangle * t =0;
+		if (link) {
+			int a=-1;
+			if (AdjEdgeIndex[0] & 16 ) a=0;
+			if (AdjEdgeIndex[1] & 16 ) a=1;
+			if (AdjEdgeIndex[2] & 16 ) a=2;
+			if (a>=0) {
+				t = adj[a];
+				//  if (t-this<0) return 0;
+				v2 = vertices[VerticesOfTriangularEdge[a][0]];
+				v0 = vertices[VerticesOfTriangularEdge[a][1]];
+				v1 = vertices[OppositeEdge[a]];
+				v3 = t->vertices[OppositeEdge[AdjEdgeIndex[a]&3]];
+			}
+		}
+		return t;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::QualityQuad {{{*/
+	double   Triangle::QualityQuad(int a,int option) const{
+		double q;
+		if (!link || AdjEdgeIndex[a] &4)
+		 q=  -1;
+		else {
+			Triangle * t = adj[a];
+			if (t-this<0) q=  -1;// because we do 2 times 
+			else if (!t->link ) q=  -1;
+			else if (AdjEdgeIndex[0] & 16 || AdjEdgeIndex[1] & 16  || AdjEdgeIndex[2] & 16 || t->AdjEdgeIndex[0] & 16 || t->AdjEdgeIndex[1] & 16 || t->AdjEdgeIndex[2] & 16 )
+			 q= -1;
+			else if(option){ 
+				const BamgVertex & v2 = *vertices[VerticesOfTriangularEdge[a][0]];
+				const BamgVertex & v0 = *vertices[VerticesOfTriangularEdge[a][1]];
+				const BamgVertex & v1 = *vertices[OppositeEdge[a]];
+				const BamgVertex & v3 = * t->vertices[OppositeEdge[AdjEdgeIndex[a]&3]];
+				q =  QuadQuality(v0,v1,v2,v3); // do the float part
+			}
+			else q= 1;
+		}
+		return  q;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::Renumbering(Triangle *tb,Triangle *te, long *renu){{{*/
+	void  Triangle::Renumbering(Triangle *tb,Triangle *te, long *renu){
+
+		if (link  >=tb && link  <te) link  = tb + renu[link -tb];
+		if (adj[0] >=tb && adj[0] <te) adj[0] = tb + renu[adj[0]-tb];
+		if (adj[1] >=tb && adj[1] <te) adj[1] = tb + renu[adj[1]-tb];
+		if (adj[2] >=tb && adj[2] <te) adj[2] = tb + renu[adj[2]-tb];    
+	}/*}}}*/
+	/*FUNCTION Triangle::Renumbering(BamgVertex *vb,BamgVertex *ve, long *renu){{{*/
+	void Triangle::Renumbering(BamgVertex *vb,BamgVertex *ve, long *renu){
+		if (vertices[0] >=vb && vertices[0] <ve) vertices[0] = vb + renu[vertices[0]-vb];
+		if (vertices[1] >=vb && vertices[1] <ve) vertices[1] = vb + renu[vertices[1]-vb];
+		if (vertices[2] >=vb && vertices[2] <ve) vertices[2] = vb + renu[vertices[2]-vb];    
+	}/*}}}*/
+	/*FUNCTION Triangle::Set {{{*/
+	void Triangle::Set(const Triangle & rec,const Mesh & Th ,Mesh & ThNew){ 
+		*this = rec;
+		if ( vertices[0] ) vertices[0] = ThNew.vertices +  Th.GetId(vertices[0]);
+		if ( vertices[1] ) vertices[1] = ThNew.vertices +  Th.GetId(vertices[1]);
+		if ( vertices[2] ) vertices[2] = ThNew.vertices +  Th.GetId(vertices[2]);
+		if(adj[0]) adj[0] =  ThNew.triangles + Th.GetId(adj[0]);
+		if(adj[1]) adj[1] =  ThNew.triangles + Th.GetId(adj[1]);
+		if(adj[2]) adj[2] =  ThNew.triangles + Th.GetId(adj[2]);
+		if (link  >= Th.triangles && link  < Th.triangles + Th.nbt)
+		 link = ThNew.triangles + Th.GetId(link);
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::SetAdjAdj{{{*/
+	void Triangle::SetAdjAdj(short a){
+		// Copy all the mark 
+		a &= 3;
+		register Triangle *tt=adj[a];
+		AdjEdgeIndex [a] &= 55; // remove MarkUnSwap
+		register short aatt = AdjEdgeIndex[a] & 3;
+		if(tt){ 
+			tt->adj[aatt]=this;
+			tt->AdjEdgeIndex[aatt]=a + (AdjEdgeIndex[a] & 60 ) ;
+		}
+	}/*}}}*/
+	/*FUNCTION Triangle::SetAdj2{{{*/
+	void Triangle::SetAdj2(short a,Triangle *t,short aat){
+		/*For current triangle:
+		 * - a is the index of the edge were the adjency is set (in [0 2])
+		 * - t is the adjacent triangle
+		 * - aat is the index of the same edge in the adjacent triangle*/
+		adj[a]=t;
+		AdjEdgeIndex[a]=aat;
+		if(t){ //if t!=NULL add adjacent triangle to t (this)
+			t->adj[aat]=this;
+			t->AdjEdgeIndex[aat]=a;
+		}
+	}/*}}}*/
+	/*FUNCTION Triangle::SetAllFlag{{{*/
+	void   Triangle::SetAllFlag(int a,int f){
+		AdjEdgeIndex[a] = (AdjEdgeIndex[a] &3) + (1020 & f);
+	}/*}}}*/
+	/*FUNCTION Triangle::SetDet{{{*/
+	void Triangle::SetDet() {
+		if(vertices[0] && vertices[1] && vertices[2])    det = bamg::det(*vertices[0],*vertices[1],*vertices[2]);
+		else det = -1; 
+	}/*}}}*/
+	/*FUNCTION Triangle::SetHidden{{{*/
+	void Triangle::SetHidden(int a){
+		//Get Adjacent Triangle number a
+		register Triangle* t = adj[a];
+		//if it exist
+		//C|=D -> C=(C|D) bitwise inclusive OR
+		if(t) t->AdjEdgeIndex[AdjEdgeIndex[a] & 3] |=16;
+		AdjEdgeIndex[a] |= 16;
+	}/*}}}*/
+	/*FUNCTION Triangle::SetLocked{{{*/
+	void Triangle::SetLocked(int a){
+		//mark the edge as on Boundary
+		register Triangle * t = adj[a];
+		t->AdjEdgeIndex[AdjEdgeIndex[a] & 3] |=4;
+		AdjEdgeIndex[a] |= 4;
+	}/*}}}*/
+	/*FUNCTION Triangle::SetMarkUnSwap{{{*/
+	void Triangle::SetMarkUnSwap(int a){
+		register Triangle * t = adj[a];
+		t->AdjEdgeIndex[AdjEdgeIndex[a] & 3] |=8;
+		AdjEdgeIndex[a] |=8 ;
+	}/*}}}*/
+	/*FUNCTION Triangle::SetSingleVertexToTriangleConnectivity{{{*/
+	void Triangle::SetSingleVertexToTriangleConnectivity() { 
+		if (vertices[0]) (vertices[0]->t=this,vertices[0]->IndexInTriangle=0);
+		if (vertices[1]) (vertices[1]->t=this,vertices[1]->IndexInTriangle=1);
+		if (vertices[2]) (vertices[2]->t=this,vertices[2]->IndexInTriangle=2);
+	}/*}}}*/
+	/*FUNCTION Triangle::SetUnMarkUnSwap{{{*/
+	void Triangle::SetUnMarkUnSwap(int a){ 
+		register Triangle * t = adj[a];
+		t->AdjEdgeIndex[AdjEdgeIndex[a] & 3] &=55; // 23 + 32 
+		AdjEdgeIndex[a] &=55 ;
+	}/*}}}*/
+	/*FUNCTION Triangle::swap{{{*/
+	int Triangle::swap(short a,int koption){
+		/*Original code from Frederic Hecht <hecht@ann.jussieu.fr> (BAMG v1.01, Mesh2.cpp/swap)*/
+
+		if(a/4 !=0) return 0;// arete lock or MarkUnSwap
+
+		register Triangle *t1=this,*t2=adj[a];// les 2 triangles adjacent
+		register short a1=a,a2=AdjEdgeIndex[a];// les 2 numero de l arete dans les 2 triangles
+		if(a2/4 !=0) return 0; // arete lock or MarkUnSwap
+
+		register BamgVertex  *sa=t1->vertices[VerticesOfTriangularEdge[a1][0]];
+		register BamgVertex  *sb=t1->vertices[VerticesOfTriangularEdge[a1][1]];
+		register BamgVertex  *s1=t1->vertices[OppositeVertex[a1]];
+		register BamgVertex  *s2=t2->vertices[OppositeVertex[a2]];
+
+		Icoor2 det1=t1->det , det2=t2->det ;
+		Icoor2 detT = det1+det2;
+		Icoor2 detA = Abs(det1) + Abs(det2);
+		Icoor2 detMin = Min(det1,det2);
+
+		int OnSwap = 0;       
+		// si 2 triangle infini (bord) => detT = -2;
+		if (sa == 0) {// les deux triangles sont frontieres
+			det2=bamg::det(s2->i,sb->i,s1->i);
+			OnSwap = det2 >0;}
+		else if (sb == 0) { // les deux triangles sont frontieres
+			det1=bamg::det(s1->i,sa->i,s2->i);
+			OnSwap = det1 >0;}
+		else if(( s1 != 0) && (s2 != 0) ) {
+			det1 = bamg::det(s1->i,sa->i,s2->i);
+			det2 = detT - det1;
+			OnSwap = (Abs(det1) + Abs(det2)) < detA;
+
+			Icoor2 detMinNew=Min(det1,det2);
+			//     if (detMin<0 && (Abs(det1) + Abs(det2) == detA)) OnSwap=BinaryRand();// just for test   
+			if (! OnSwap &&(detMinNew>0)) {
+				OnSwap = detMin ==0;
+				if (! OnSwap) {
+					int  kopt = koption;
+					while (1)
+					 if(kopt) {
+						 // critere de Delaunay pure isotrope
+						 register Icoor2 xb1 = sb->i.x - s1->i.x,
+									 x21 = s2->i.x - s1->i.x,
+									 yb1 = sb->i.y - s1->i.y,
+									 y21 = s2->i.y - s1->i.y,
+									 xba = sb->i.x - sa->i.x, 
+									 x2a = s2->i.x - sa->i.x,
+									 yba = sb->i.y - sa->i.y,
+									 y2a = s2->i.y - sa->i.y;
+						 register double
+							cosb12 =  double(xb1*x21 + yb1*y21),
+									 cosba2 =  double(xba*x2a + yba*y2a) ,
+									 sinb12 = double(det2),
+									 sinba2 = double(t2->det);
+
+
+						 // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2)
+						 OnSwap =  ((double) cosb12 * (double)  sinba2) <  ((double) cosba2 * (double) sinb12);
+						 break;
+					 }
+					 else {	
+						 // critere de Delaunay anisotrope 
+						 double som;
+						 I2 AB=(I2) *sb - (I2) *sa;
+						 I2 MAB2=((I2) *sb + (I2) *sa);
+						 R2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+						 I2 A1=(I2) *s1 - (I2) *sa;
+						 I2 D = (I2) * s1 - (I2) * sb ;
+						 R2 S2(s2->i.x,s2->i.y);
+						 R2 S1(s1->i.x,s1->i.y);
+							{
+							 Metric M=s1->m;
+							 R2 ABo = M.Orthogonal(AB);
+							 R2 A1o = M.Orthogonal(A1);
+							 // (A+B)+ x ABo = (S1+B)/2+ y A1 
+							 // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+							 double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+							 double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+							 if (Abs(d) > dd*1.e-3) {
+								 R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+								 som  = M(C - S2)/M(C - S1);
+							 } else 
+								{kopt=1;continue;}
+
+							}
+							{
+							 Metric M=s2->m;
+							 R2 ABo = M.Orthogonal(AB);
+							 R2 A1o = M.Orthogonal(A1);
+							 // (A+B)+ x ABo = (S1+B)/2+ y A1 
+							 // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+							 double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+							 double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+							 if(Abs(d) > dd*1.e-3) {
+								 R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+								 som  += M(C - S2)/M(C -  S1);
+							 } else 
+								{kopt=1;continue;}
+							}
+						 OnSwap = som < 2;
+						 break;
+					 }
+
+				} // OnSwap 
+			} // (! OnSwap &&(det1 > 0) && (det2 > 0) )
+		}
+		if( OnSwap ) 
+		 bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2);
+		else {
+			t1->SetMarkUnSwap(a1);     
+		}
+		return OnSwap;
+	}
+	/*}}}*/
+	/*FUNCTION Triangle::TriangleAdj{{{*/
+	Triangle* Triangle::TriangleAdj(int i) const {
+		return adj[i&3];
+	}/*}}}*/
+
+}
Index: /issm/trunk-jpl/src/c/classes/bamg/Triangle.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/Triangle.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/Triangle.h	(revision 12821)
@@ -0,0 +1,76 @@
+#ifndef _TRIANGLE_H_
+#define _TRIANGLE_H_
+
+#include "./include.h"
+#include "AdjacentTriangle.h"
+
+namespace bamg {
+
+	//classes
+	class Mesh;
+	class BamgVertex;
+	class Triangle;
+
+	class Triangle {
+
+		friend class AdjacentTriangle;
+
+		private:
+			BamgVertex *vertices[3];        // 3 vertices if t is triangle, t[i] allowed by access function, (*t)[i] if pointer
+			Triangle   *adj[3];             // 3 pointers toward the adjacent triangles
+			short       AdjEdgeIndex[3];   // edge id in the adjacent triangles. The edge number 1 is the edge number AdjEdgeIndex[1] in the Adjacent triangle 1
+
+		public: 
+			Icoor2 det; //Integer determinant (twice its area)
+			union { 
+				Triangle *link;
+				long      color;
+			};
+
+			//Constructors/Destructors
+			Triangle();
+			Triangle(Mesh *Th,long i,long j,long k);
+			Triangle(BamgVertex *v0,BamgVertex *v1,BamgVertex *v2);
+
+			//Operators
+			const BamgVertex & operator[](int i) const {return *vertices[i];};
+			BamgVertex & operator[](int i)  {return *vertices[i];};
+			const BamgVertex * operator()(int i) const {return vertices[i];};
+			BamgVertex * & operator()(int i)  {return vertices[i];};
+
+			//Methods
+			void              Echo();
+			double            Anisotropy() const;
+			double            Length() const;
+			int               swap(short a1,int=0);
+			long              Optim(short a,int =0);
+			int               Locked(int a)const;
+			int               Hidden(int a)const;
+			int               GetAllflag(int a);
+			void              SetAllFlag(int a,int f);
+			double            QualityQuad(int a,int option=1) const;
+			short             NuEdgeTriangleAdj(int i) const;
+			AdjacentTriangle  FindBoundaryEdge(int  i) const;
+			AdjacentTriangle  Adj(int i) const;
+			Triangle         *TriangleAdj(int i) const;
+			Triangle         *Quadrangle(BamgVertex  *& v0,BamgVertex *& v1,BamgVertex *& v2,BamgVertex *& v3) const;
+			void              Renumbering(Triangle   *tb,Triangle *te, long *renu);
+			void              Renumbering(BamgVertex *vb,BamgVertex *ve, long *renu);
+			void              SetAdjAdj(short a);
+			void              SetAdj2(short a,Triangle *t,short aat);
+			void              SetSingleVertexToTriangleConnectivity();
+			void              SetHidden(int a);
+			void              SetLocked(int a);
+			void              SetMarkUnSwap(int a);
+			void              SetUnMarkUnSwap(int a);
+			void              SetDet();
+
+			//Inline methods
+			double qualite() ;
+			void  Set(const Triangle &,const Mesh &,Mesh &);
+			int   In(BamgVertex *v) const { return vertices[0]==v || vertices[1]==v || vertices[2]==v ;}
+
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.cpp	(revision 12821)
@@ -0,0 +1,25 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "VertexOnEdge.h"
+#include "Mesh.h"
+
+namespace bamg {
+
+	/*Methods*/
+	/*FUNCTION VertexOnEdge::Set {{{*/
+	void VertexOnEdge::Set(const Mesh & Th ,long i,Mesh & ThNew){
+		*this = Th.VertexOnBThEdge[i];  
+		v = ThNew.vertices + Th.GetId(v);
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnEdge::SetOnBTh{{{*/
+	void VertexOnEdge::SetOnBTh(){
+		v->BackgroundEdgeHook=this;
+		v->IndexInTriangle=IsVertexOnEdge;  
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnEdge.h	(revision 12821)
@@ -0,0 +1,36 @@
+#ifndef _VERTEXONEDGE_H_
+#define _VERTEXONEDGE_H_
+
+#include "./include.h"
+#include "./Edge.h"
+
+namespace bamg {
+
+	//classes
+	class Mesh;
+	class BamgVertex;
+
+	class VertexOnEdge {
+
+		public:
+			BamgVertex* v;
+			Edge*   be;
+			double abcisse;
+
+			//Constructors
+			VertexOnEdge(BamgVertex * w, Edge *bw,double s) :v(w),be(bw),abcisse(s) {};
+			VertexOnEdge(){};
+
+			//Operators
+			operator double () const { return abcisse;}
+			operator BamgVertex* () const { return v;}  
+			operator Edge* () const { return be;}  
+			BamgVertex & operator[](int i) const { return (*be)[i];}
+
+			//Methods
+			void SetOnBTh();
+			void Set(const Mesh &,long,Mesh &);  
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.cpp	(revision 12821)
@@ -0,0 +1,70 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "VertexOnGeom.h"
+#include "Mesh.h"
+#include "Geometry.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION VertexOnGeom::VertexOnGeom(){{{*/
+	VertexOnGeom::VertexOnGeom(){
+		meshvertex=NULL;
+		curvilincoord=0;
+		gv=0;
+	} 
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::VertexOnGeom(BamgVertex & m,GeomVertex &g){{{*/
+	VertexOnGeom::VertexOnGeom(BamgVertex & m,GeomVertex &g){
+		meshvertex=&m;
+		curvilincoord=-1;
+		gv=&g;
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::VertexOnGeom(BamgVertex & m,GeomEdge &g,double s){{{*/
+	VertexOnGeom::VertexOnGeom(BamgVertex & m,GeomEdge &g,double s){
+		meshvertex=&m;
+		curvilincoord=s;
+		ge=&g;
+	}
+	/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION VertexOnGeom::Set {{{*/
+	void VertexOnGeom::Set(const VertexOnGeom & rec,const Mesh & Th ,Mesh & ThNew){
+		*this = rec;  
+		meshvertex = ThNew.vertices + Th.GetId(meshvertex);
+		if (gv)
+		 if (curvilincoord < 0 )
+		  gv = ThNew.Gh.vertices + Th.Gh.GetId(gv);
+		 else
+		  ge = ThNew.Gh.edges + Th.Gh.GetId(ge);
+
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::OnGeomVertex{{{*/
+	int VertexOnGeom::OnGeomVertex()const{
+		return this? curvilincoord <0 :0;
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::OnGeomEdge{{{*/
+	int VertexOnGeom::OnGeomEdge() const{
+		return this? curvilincoord >=0 :0;
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::IsRequiredVertex{{{*/
+	int VertexOnGeom::IsRequiredVertex() {
+		return this? ((curvilincoord<0 ? (gv?gv->Required():0):0 )) : 0;
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnGeom::SetOn{{{*/
+	void VertexOnGeom::SetOn(){
+		meshvertex->GeomEdgeHook=this;
+		meshvertex->IndexInTriangle=IsVertexOnGeom;
+	}
+	/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnGeom.h	(revision 12821)
@@ -0,0 +1,46 @@
+#ifndef _VERTEXONGEOM_H_
+#define _VERTEXONGEOM_H_
+
+#include "./include.h"
+#include "./GeomVertex.h"
+
+namespace bamg {
+
+	//classes
+	class Mesh;
+	class BamgVertex;
+	class GeomEdge;
+
+	class VertexOnGeom{
+
+		public:
+
+			BamgVertex* meshvertex;
+			double curvilincoord;  
+			union{ 
+				GeomVertex* gv; // if curvilincoord <0; 
+				GeomEdge*   ge; // if curvilincoord in [0..1]
+			};
+
+			//Constructors/Destructors
+			VertexOnGeom();
+			VertexOnGeom(BamgVertex & m,GeomVertex &g);
+			VertexOnGeom(BamgVertex & m,GeomEdge &g,double s);
+
+			//Operators
+			operator BamgVertex*() const  {return meshvertex;}
+			operator GeomVertex * () const  {return gv;}
+			operator GeomEdge * () const  {return ge;}
+			operator const double & () const {return curvilincoord;}
+
+			//Methods
+			int  OnGeomVertex()const;
+			int  OnGeomEdge() const;
+			int  IsRequiredVertex();
+			void SetOn();
+
+			//Inline methods
+			void Set(const VertexOnGeom&,const Mesh &,Mesh &);  
+	};
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.cpp	(revision 12821)
@@ -0,0 +1,34 @@
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+#include "VertexOnVertex.h"
+#include "Mesh.h"
+
+namespace bamg {
+
+	/*Constructors/Destructors*/
+	/*FUNCTION VertexOnVertex::VertexOnVertex(){{{*/
+	VertexOnVertex::VertexOnVertex() {
+		v=NULL;
+		bv=NULL;
+	};/*}}}*/
+	/*FUNCTION VertexOnVertex::VertexOnVertex(BamgVertex * w,BamgVertex *bw){{{*/
+	VertexOnVertex::VertexOnVertex(BamgVertex * w,BamgVertex *bw) :v(w),bv(bw){
+	
+	}/*}}}*/
+
+	/*Methods*/
+	/*FUNCTION VertexOnVertex::Set{{{*/
+	void VertexOnVertex::Set(const Mesh &Th ,long i,Mesh &ThNew) { 
+		*this = Th.VertexOnBThVertex[i];  
+		v     = ThNew.vertices + Th.GetId(v);
+	}
+	/*}}}*/
+	/*FUNCTION VertexOnVertex::SetOnBTh{{{*/
+	void VertexOnVertex::SetOnBTh(){
+		v->BackgroundVertexHook=bv;v->IndexInTriangle=IsVertexOnVertex;
+	}/*}}}*/
+
+} 
Index: /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/VertexOnVertex.h	(revision 12821)
@@ -0,0 +1,28 @@
+#ifndef _VERTEXONVERTEX_H_
+#define _VERTEXONVERTEX_H_
+
+#include "./include.h"
+#include "./BamgVertex.h"
+
+namespace bamg {
+
+	//classes
+	class Mesh;
+
+	class VertexOnVertex {
+
+		public:
+			BamgVertex* v;
+			BamgVertex* bv;
+
+			//Constructors
+			VertexOnVertex();
+			VertexOnVertex(BamgVertex * w,BamgVertex *bw);
+
+			//Methods
+			void SetOnBTh();
+			void Set(const Mesh &,long,Mesh &);
+	};
+
+}
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/include.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/include.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/include.h	(revision 12821)
@@ -0,0 +1,12 @@
+/*!\file: include.h
+ * \brief prototypes for include.h
+ */ 
+
+#ifndef _INCLUDE2_H_
+#define  _INCLUDE2_H_
+
+#include "../../include/macros.h"
+#include "./macros.h"
+#include "./typedefs.h"
+
+#endif //ifndef _INCLUDE2_H_
Index: /issm/trunk-jpl/src/c/classes/bamg/macros.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/macros.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/macros.h	(revision 12821)
@@ -0,0 +1,29 @@
+#ifndef _BAMGMACROS_H
+#define _BAMGMACROS_H
+
+#include "./typedefs.h"
+
+namespace bamg {
+
+	const double Pi =3.141592653589793238462643383279502884197169399375105820974944592308;
+	const float  fPi=3.141592653589793238462643383279502884197169399375105820974944592308;
+	const  int   IsVertexOnGeom = 8;
+	const  int   IsVertexOnVertex = 16;
+	const  int   IsVertexOnEdge = 32;
+	static const short VerticesOfTriangularEdge[3][2] = {{1,2},{2,0},{0,1}};
+	static const short EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}};
+	static const short OppositeVertex[3] = {0,1,2};
+	static const short OppositeEdge[3] =  {0,1,2};
+	static const short NextEdge[3] = {1,2,0};
+	static const short PreviousEdge[3] = {2,0,1};
+	static const short NextVertex[3] = {1,2,0};
+	static const short PreviousVertex[3] = {2,0,1};
+	#if LONG_BIT > 63
+	const  Icoor1 MaxICoor   = 1073741823; // 2^30-1 =111...111 (29 times)
+	#else
+	const  Icoor1 MaxICoor   = 8388608;    // 2^23
+	#endif
+	const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+}
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/bamg/typedefs.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/bamg/typedefs.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/bamg/typedefs.h	(revision 12821)
@@ -0,0 +1,21 @@
+#ifndef _BAMGTYPEDEFS_H
+#define _BAMGTYPEDEFS_H
+
+#include "./R2.h"
+
+namespace bamg {
+
+	/*Integer coordinates types*/
+	typedef int  Icoor1; 
+	#if LONG_BIT > 63 //64 bits or more
+	typedef long Icoor2;
+	#else //32 bits
+	typedef double Icoor2;
+	#endif
+
+	/*I2 and R2*/
+	typedef P2<Icoor1,Icoor2>  I2;
+	typedef P2<double,double>  R2;
+}
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.cpp	(revision 12821)
@@ -0,0 +1,118 @@
+/*!\file:  DakotaPlugin.cpp (see DakotaPlugin.h for explanations)
+ * \brief  header file for derived DirectApplicInterface class. 
+ * \sa SpwanCore.cpp and \sa qmu.cpp
+ *
+ * This class needs to be understood simultaneously with qmu.cpp and SpwanCore.cpp. 
+ * This call is derived from the Dakota DirectApplicInterface class. This is the 
+ * only way to plug ISSM's own routines into the Dakota engine. The derived class 
+ * has one function called derived_map_ac, which is called by Dakota to drive the 
+ * entire snesitivity analysis. 
+ *
+ * We use this routine (which gets variables, variable_descriptors from the Dakota 
+ * engine, and requests responses from the ISSM solution sequences), to call our 
+ * own solutoin cores. This routines calls the SpawnCore routine, which will drive 
+ * the entire computations. 
+ */ 
+
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+/*Standard ISSM includes: */
+#include "../shared/shared.h"
+#include "../include/include.h"
+#include "../objects/objects.h"
+#include "../modules/Dakotax/Dakotax.h"
+
+/*Standard includes: */
+#include <string>
+
+#ifdef _HAVE_DAKOTA_ //only works if dakota library has been compiled in.
+
+//Dakota headers
+#include "DakotaResponse.H"
+#include "ParamResponsePair.H"
+#include "DakotaPlugin.h"
+#include "system_defs.h"
+#include "ProblemDescDB.H"
+#include "ParallelLibrary.H"
+
+namespace SIM {
+
+//constructor
+DakotaPlugin::DakotaPlugin(const Dakota::ProblemDescDB& problem_db,void* in_femmodel):Dakota::DirectApplicInterface(problem_db){
+
+
+	femmodel=in_femmodel;
+	counter=0;
+}
+
+//destructor
+DakotaPlugin::~DakotaPlugin(){ /* Virtual destructor handles referenceCount at Interface level. */ }
+
+int DakotaPlugin::derived_map_ac(const Dakota::String& driver) {
+
+	int i;
+	IssmDouble* variables=NULL;
+	char** variable_descriptors=NULL;
+	char*  variable_descriptor=NULL;
+	IssmDouble* responses=NULL;
+
+	/*increae counter: */
+	counter++;
+
+	/*Before launching analysis, we need to transfer the dakota inputs into Issm 
+	 *readable variables: */
+
+	/*First, the variables: */
+	variables=xNew<IssmDouble>(numACV);
+	for(i=0;i<numACV;i++){
+		variables[i]=xC[i];
+	}
+	/*The descriptors: */
+	variable_descriptors=xNew<char*>(numACV);
+	for(i=0;i<numACV;i++){
+		string label=xCLabels[i];
+		variable_descriptor=xNew<char>(strlen(label.c_str())+1);
+		memcpy(variable_descriptor,label.c_str(),(strlen(label.c_str())+1)*sizeof(char));
+
+		
+		variable_descriptors[i]=variable_descriptor;
+	}
+
+	/*Initialize responses: */
+	responses=xNewZeroInit<IssmDouble>(numFns);
+
+	/*run core solution: */
+	SpawnCore(responses,numFns, variables,variable_descriptors,numACV,femmodel,counter);
+
+	/*populate responses: */
+	for(i=0;i<numFns;i++){
+		fnVals[i]=responses[i];
+	}
+
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(variables);
+	for(i=0;i<numACV;i++){
+		variable_descriptor=variable_descriptors[i];
+		xDelete<char>(variable_descriptor);
+	}
+	xDelete<char*>(variable_descriptors);
+	xDelete<IssmDouble>(responses);
+
+	return 0;
+}
+  
+
+int DakotaPlugin::GetCounter(){
+	return counter;
+}
+
+} // namespace SIM
+
+
+#endif //only works if dakota library has been compiled in.
Index: /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/dakota/DakotaPlugin.h	(revision 12821)
@@ -0,0 +1,55 @@
+/*!\file:  DakotaPlugin.h:
+ */ 
+
+#ifndef _DAKOTAPLUGIN_H
+#define _DAKOTAPLUGIN_H
+
+
+#ifdef _HAVE_DAKOTA_ //only works if dakota library has been compiled in.
+
+/*Headers:*/
+/*{{{*/
+
+
+#include "DirectApplicInterface.H"
+#include "../toolkits/toolkits.h"
+#include "../objects/objects.h"
+
+/*}}}*/
+
+namespace SIM {
+
+class DakotaPlugin: public Dakota::DirectApplicInterface
+{
+public:
+
+	DakotaPlugin(const Dakota::ProblemDescDB& problem_db,void* model);
+	~DakotaPlugin();
+
+	/*these fields are used by core solutions: */
+	void* femmodel;
+
+	int counter;
+
+protected:
+
+  // execute the input filter portion of a direct evaluation invocation
+  //int derived_map_if(const Dakota::String& if_name);
+  /// execute an analysis code portion of a direct evaluation invocation
+  int derived_map_ac(const Dakota::String& ac_name);
+  // execute the output filter portion of a direct evaluation invocation
+  //int derived_map_of(const Dakota::String& of_name);
+
+  /*add for issm: */
+  int GetCounter();
+
+private:
+
+};
+
+} // namespace SIM
+
+#endif //only works if dakota library has been compiled in.
+
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.cpp	(revision 12821)
@@ -0,0 +1,95 @@
+/*!\file ExponentialVariogram.c
+ * \brief: implementation of the ExponentialVariogram object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/include.h"
+
+/*ExponentialVariogram constructors and destructor*/
+/*FUNCTION ExponentialVariogram::ExponentialVariogram(){{{*/
+ExponentialVariogram::ExponentialVariogram(){
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+	return;
+}
+/*}}}*/
+/*FUNCTION ExponentialVariogram::ExponentialVariogram(Options* options){{{*/
+ExponentialVariogram::ExponentialVariogram(Options* options){
+
+	/*Defaults*/
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+
+	/*Overwrite from options*/
+	if(options->GetOption("nugget")) options->Get(&this->nugget,"nugget");
+	if(options->GetOption("sill"))   options->Get(&this->sill,"sill");
+	if(options->GetOption("range"))  options->Get(&this->range,"range");
+
+	/*Checks*/
+	if(nugget==sill) _error2_("nugget and sill cannot be equal (constant semivariogram not allowed)");
+}
+/*}}}*/
+/*FUNCTION ExponentialVariogram::~ExponentialVariogram(){{{*/
+ExponentialVariogram::~ExponentialVariogram(){
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION ExponentialVariogram::Echo {{{*/
+void ExponentialVariogram::Echo(void){
+	_printLine_("ExponentialVariogram");
+	_printLine_("   nugget: " << this->nugget);
+	_printLine_("   sill  : " << this->sill);
+	_printLine_("   range : " << this->range);
+}
+/*}}}*/
+
+/*Variogram function*/
+/*FUNCTION ExponentialVariogram::Covariance{{{*/
+double ExponentialVariogram::Covariance(double deltax,double deltay){
+	/*The covariance can be deduced from the variogram from the following
+	 * relationship:
+	 *    2 gamma = C(x,x) + C(y,y) -2 C(x,y)
+	 * so
+	 *    C(h) = sill - gamma                                            */
+	double h,a,cova;
+
+	/*Calculate length*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*If h is too small, return sill*/
+	if(h<0.0000001) return sill;
+
+	/*compute covariance*/
+	a     = 1./3.;
+	cova = (sill-nugget)*exp(-h/(a*range));
+	return cova;
+}
+/*}}}*/
+/*FUNCTION ExponentialVariogram::SemiVariogram{{{*/
+double ExponentialVariogram::SemiVariogram(double deltax,double deltay){
+	/*http://en.wikipedia.org/wiki/Variogram*/
+	double h,a,gamma;
+
+	/*Calculate length*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*return semi-variogram*/
+	a     = 1./3.;
+	gamma = (sill-nugget)*(1-exp(-h/(a*range))) + nugget;
+	return gamma;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/ExponentialVariogram.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*! \file ExponentialVariogram.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+#ifndef _EXPONENTIALVARIOGRAM_H_
+#define _EXPONENTIALVARIOGRAM_H_
+
+/*Headers:*/
+#include "./Variogram.h"
+
+class ExponentialVariogram: public Variogram{
+
+	public:
+		double nugget; //The height of the jump of the semivariogram at the discontinuity at the origin
+		double sill;   //Limit of the variogram tending to infinity lag distances
+		double range;  //The distance in which the difference of the variogram from the sill becomes negligible
+
+		/*ExponentialVariogram constructors, destructors*/
+		ExponentialVariogram();
+		ExponentialVariogram(Options* options);
+		~ExponentialVariogram();
+
+		/*Object virtual functions definitions*/
+		void  Echo();
+		void  DeepEcho(){_error2_("Not implemented yet");};
+		int   Id(){_error2_("Not implemented yet");}; 
+		int   MyRank(){_error2_("Not implemented yet");};
+		int   ObjectEnum(){_error2_("Not implemented yet");};
+		Object* copy(){_error2_("Not implemented yet");};
+
+		/*Variogram functions*/
+		double SemiVariogram(double deltax,double deltay);
+		double Covariance(double deltax,double deltay);
+};
+#endif  /* _EXPONENTIALVARIOGRAM_H */
Index: /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.cpp	(revision 12821)
@@ -0,0 +1,99 @@
+/*!\file GaussianVariogram.c
+ * \brief: implementation of the GaussianVariogram object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/include.h"
+
+/*GaussianVariogram constructors and destructor*/
+/*FUNCTION GaussianVariogram::GaussianVariogram(){{{*/
+GaussianVariogram::GaussianVariogram(){
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+	return;
+}
+/*}}}*/
+/*FUNCTION GaussianVariogram::GaussianVariogram(Options* options){{{*/
+GaussianVariogram::GaussianVariogram(Options* options){
+
+	/*Defaults*/
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+
+	/*Overwrite from options*/
+	if(options->GetOption("nugget")) options->Get(&this->nugget,"nugget");
+	if(options->GetOption("sill"))   options->Get(&this->sill,"sill");
+	if(options->GetOption("range"))  options->Get(&this->range,"range");
+
+	/*Checks*/
+	if(nugget==sill) _error2_("nugget and sill cannot be equal (constant semivariogram not allowed)");
+}
+/*}}}*/
+/*FUNCTION GaussianVariogram::~GaussianVariogram(){{{*/
+GaussianVariogram::~GaussianVariogram(){
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION GaussianVariogram::Echo {{{*/
+void GaussianVariogram::Echo(void){
+	_printLine_("GaussianVariogram");
+	_printLine_("   nugget: " << this->nugget);
+	_printLine_("   sill  : " << this->sill);
+	_printLine_("   range : " << this->range);
+}
+/*}}}*/
+
+/*Variogram function*/
+/*FUNCTION GaussianVariogram::Covariance{{{*/
+double GaussianVariogram::Covariance(double deltax,double deltay){
+	/*The covariance can be deduced from the variogram from the following
+	 * relationship:
+	 *    2 gamma = C(x,x) + C(y,y) -2 C(x,y)
+	 * so
+	 *    C(h) = sill - gamma                                            */
+	double h2,a,cova;
+
+	/*Calculate length square*/
+	h2=pow(deltax,2.)+pow(deltay,2.);
+
+	/*If h is too small, return sill*/
+	if(h2<0.0000001) return sill;
+
+	/*compute covariance*/
+	a     = 1./3.;
+	cova = (sill-nugget)*exp(-h2/(a*range*range));
+
+	return cova;
+}
+/*}}}*/
+/*FUNCTION GaussianVariogram::SemiVariogram{{{*/
+double GaussianVariogram::SemiVariogram(double deltax,double deltay){
+	/*http://en.wikipedia.org/wiki/Variogram*/
+	double h2,a,gamma;
+
+	/*Calculate length square*/
+	h2=pow(deltax,2.)+pow(deltay,2.);
+
+	/*return semi-variogram*/
+	a     = 1./3.;
+	gamma = (sill-nugget)*(1.-exp(-h2/(a*range*range))) + nugget;
+
+	//if(h2>1000*1000) _printLine_("gamma = " << gamma << " h= " << sqrt(h2));
+	_printLine_("h = " << sqrt(h2) << " gamma = " << gamma);
+	return gamma;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/GaussianVariogram.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*! \file GaussianVariogram.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+#ifndef _GAUSSIANVARIOGRAM_H_
+#define _GAUSSIANVARIOGRAM_H_
+
+/*Headers:*/
+#include "./Variogram.h"
+
+class GaussianVariogram: public Variogram{
+
+	public:
+		double nugget; //The height of the jump of the semivariogram at the discontinuity at the origin
+		double sill;   //Limit of the variogram tending to infinity lag distances
+		double range;  //The distance in which the difference of the variogram from the sill becomes negligible
+
+		/*GaussianVariogram constructors, destructors*/
+		GaussianVariogram();
+		GaussianVariogram(Options* options);
+		~GaussianVariogram();
+
+		/*Object virtual functions definitions*/
+		void  Echo();
+		void  DeepEcho(){_error2_("Not implemented yet");};
+		int   Id(){_error2_("Not implemented yet");}; 
+		int   MyRank(){_error2_("Not implemented yet");};
+		int   ObjectEnum(){_error2_("Not implemented yet");};
+		Object* copy(){_error2_("Not implemented yet");};
+
+		/*Variogram functions*/
+		double SemiVariogram(double deltax,double deltay);
+		double Covariance(double deltax,double deltay);
+};
+#endif  /* _GAUSSIANVARIOGRAM_H */
Index: /issm/trunk-jpl/src/c/classes/kriging/Observation.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/Observation.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/Observation.cpp	(revision 12821)
@@ -0,0 +1,57 @@
+/*!\file Observation.c
+ * \brief: implementation of the Observation object
+ */
+
+#include <stdlib.h>
+#include "../objects.h"
+
+/*Observation constructors and destructor*/
+/*FUNCTION Observation::Observation(){{{*/
+Observation::Observation(){
+	return;
+}
+/*}}}*/
+/*FUNCTION Observation::Observation(double x,double y,int xi,int yi,int index,double value){{{*/
+Observation::Observation(double x_in,double y_in,int xi_in,int yi_in,int index_in,double value_in){
+
+	this->x      = x_in;
+	this->y      = y_in;
+	this->xi     = xi_in;
+	this->yi     = yi_in;
+	this->index  = index_in;
+	this->value  = value_in;
+	this->weight = 1.;
+
+}
+/*}}}*/
+/*FUNCTION Observation::~Observation(){{{*/
+Observation::~Observation(){
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION Observation::Echo {{{*/
+void Observation::Echo(void){
+
+	int  bit;
+
+	_printLine_("Observation");
+	_printLine_("   index : " << this->index);
+	_printLine_("   x     : " << this->x);
+	_printLine_("   y     : " << this->y);
+	_printLine_("   xi    : "); printbinary(this->xi); _printLine_("");
+	_printLine_("   yi    : "); printbinary(this->yi); _printLine_("");
+	_printLine_("   weight: " << this->weight);
+	_printLine_("   value : " << this->value);
+}
+/*}}}*/
+
+/*Observations functions*/
+/*FUNCTION Observation::WriteXYObs(double* px,double* py,double* pobs){{{*/
+void Observation::WriteXYObs(double* px,double* py,double* pobs){
+	*px   = this->x;
+	*py   = this->y;
+	*pobs = this->value;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/Observation.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/Observation.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/Observation.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*! \file Observation.h 
+ *  \brief: header file for Observation object
+ */
+
+#ifndef _OBSERVATION_H_
+#define _OBSERVATION_H_
+
+#include "../Object.h"
+
+class Observation: public Object{
+
+	public:
+		double x,y;
+		int    xi,yi;
+		int    index;
+		double weight;
+		double value;
+
+		/*Observation constructors, destructors*/
+		Observation();
+		Observation(double x_in,double y_in,int xi_in,int yi_in,int index_in,double value_in);
+		~Observation();
+
+		/*Object virtual functions definitions*/
+		void    Echo();
+		void    DeepEcho()  {_error2_("Not implemented yet"); };
+		int     Id()        {_error2_("Not implemented yet"); };
+		int     MyRank()    {_error2_("Not implemented yet"); };
+		int     ObjectEnum(){_error2_("Not implemented yet"); };
+		Object *copy()      {_error2_("Not implemented yet"); };
+
+		/*Management*/
+		void WriteXYObs(double* px,double* py,double* pobs);
+};
+#endif  /* _OBSERVATION_*/
Index: /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.cpp	(revision 12821)
@@ -0,0 +1,94 @@
+/*!\file PowerVariogram.c
+ * \brief: implementation of the PowerVariogram object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/include.h"
+
+/*PowerVariogram constructors and destructor*/
+/*FUNCTION PowerVariogram::PowerVariogram(){{{*/
+PowerVariogram::PowerVariogram(){
+	this->nugget = 0.2;
+	this->slope  = 1.;
+	this->power  = 1.;
+	return;
+}
+/*}}}*/
+/*FUNCTION PowerVariogram::PowerVariogram(Options* options){{{*/
+PowerVariogram::PowerVariogram(Options* options){
+
+	/*Defaults*/
+	this->nugget = 0.2;
+	this->slope  = 1.;
+	this->power  = 1.;
+
+	/*Overwrite from options*/
+	if(options->GetOption("nugget")) options->Get(&this->nugget,"nugget");
+	if(options->GetOption("slope"))  options->Get(&this->slope,"slope");
+	if(options->GetOption("power"))  options->Get(&this->power,"power");
+
+	/*Checks*/
+	if(power<=0 || power>=2) _error2_("power must be betwwen 0 and 2 (0 < power < 2)");
+	if(slope<=0) _error2_("slope must be positive");
+}
+/*}}}*/
+/*FUNCTION PowerVariogram::~PowerVariogram(){{{*/
+PowerVariogram::~PowerVariogram(){
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION PowerVariogram::Echo {{{*/
+void PowerVariogram::Echo(void){
+	_printLine_("PowerVariogram");
+	_printLine_("   nugget: " << this->nugget);
+	_printLine_("   slope : " << this->slope);
+	_printLine_("   power : " << this->power);
+}
+/*}}}*/
+
+/*Variogram function*/
+/*FUNCTION PowerVariogram::Covariance{{{*/
+double PowerVariogram::Covariance(double deltax,double deltay){
+	/*The covariance can be deduced from the variogram from the following
+	 * relationship:
+	 *    2 gamma = C(x,x) + C(y,y) -2 C(x,y)
+	 * so
+	 *    C(h) = sill - gamma                                            */
+	double h,cova;
+
+	/*Calculate length square*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*return covariance*/
+	cova = 9999. - this->slope*pow(h,this->power);
+
+	return cova;
+}
+/*}}}*/
+/*FUNCTION PowerVariogram::SemiVariogram{{{*/
+double PowerVariogram::SemiVariogram(double deltax,double deltay){
+	/*http://en.wikipedia.org/wiki/Variogram*/
+	double h,gamma;
+
+	/*Calculate length square*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*return semi-variogram*/
+	gamma = this->nugget + this->slope*pow(h,this->power);
+
+	//if(h>1000) _printLine_("gamma = " << gamma << " h=" << h);
+	return gamma;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/PowerVariogram.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*! \file PowerVariogram.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+#ifndef _POWERVARIOGRAM_H_
+#define _POWERVARIOGRAM_H_
+
+/*Headers:*/
+#include "./Variogram.h"
+
+class PowerVariogram: public Variogram{
+
+	public:
+		double nugget; //The height of the jump of the semivariogram at the discontinuity at the origin
+		double slope;  
+		double power; 
+
+		/*PowerVariogram constructors, destructors*/
+		PowerVariogram();
+		PowerVariogram(Options* options);
+		~PowerVariogram();
+
+		/*Object virtual functions definitions*/
+		void  Echo();
+		void  DeepEcho(){_error2_("Not implemented yet");};
+		int   Id(){_error2_("Not implemented yet");}; 
+		int   MyRank(){_error2_("Not implemented yet");};
+		int   ObjectEnum(){_error2_("Not implemented yet");};
+		Object* copy(){_error2_("Not implemented yet");};
+
+		/*Variogram functions*/
+		double SemiVariogram(double deltax,double deltay);
+		double Covariance(double deltax,double deltay);
+};
+#endif  /* _POWERVARIOGRAM_H */
Index: /issm/trunk-jpl/src/c/classes/kriging/Quadtree.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/Quadtree.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/Quadtree.cpp	(revision 12821)
@@ -0,0 +1,607 @@
+#include "../objects.h"
+
+/*DOCUMENTATION What is a Quadtree? {{{
+ * A Quadtree is a very simple way to group vertices according
+ * to their locations. A square that holds all the points of the mesh
+ * (or the geometry) is divided into 4 boxes. As soon as one box
+ * hold more than 4 vertices, it is divided into 4 new boxes, etc...
+ * There cannot be more than MAXDEEP (=30) subdivision.
+ * This process is like a Dichotomy in dimension 2
+ *
+ *  + - -  -    - -    -    - - + -   - + - + - + - -     - - +
+ *  |                           |       |   | X |             |
+ *                                      + - + - +
+ *  |                           |       |   |   |             |
+ *                              + -   - + - + - +             +
+ *  |                           |       |       |             |
+ *                         
+ *  |                           |       |       |             |
+ *  + - -  -    - -    -    - - + -   - + -   - + - -     - - +
+ *  |                           |               |             |
+ *                         
+ *  |                           |               |             |
+ *                         
+ *  |                           |               |             |
+ *  |                           |               |             |
+ *  + - -  -    - -    -    - - + -   -   -   - + - -     - - +
+ *  |                           |                             |
+ *                         
+ *  |                           |                             |
+ *                         
+ *  |                           |                             |
+ *                         
+ *  |                           |                             |
+ *  |                           |                             |
+ *  |                           |                             |
+ *  |                           |                             |
+ *  |                           |                             |
+ *  + - -  -    - -    -    - - + -   -   -   -   - -     - - +
+ *
+ * The coordinate system used in a quadtree are integers to avoid
+ * round-off errors. The vertex in the lower left box has the coordinates
+ * (0 0) 
+ * The upper right vertex has the follwing coordinates:
+ * 2^30 -1           2^30 -1        in decimal
+ * 0 1 1 1 .... 1    0 1 1 1 .... 1 in binary
+ *  \--   29  --/     \--   29  --/
+ * Using binaries is therefore very easy to locate a vertex in a box:
+ * we just need to look at the bits from the left to the right (See ::Add)
+ }}}*/
+/*MACROS {{{*/
+/* 
+ * 
+ *    J    j
+ *    ^    ^
+ *    |    | +--------+--------+
+ *    |    | |        |        |
+ * 1X |    | |   2    |   3    |
+ *    |    | |        |        |
+ *    |    | +--------+--------+
+ *    |    | |        |        |
+ * 0X |    | |   0    |   1    |
+ *    |    | |        |        |
+ *    |    | +--------+--------+
+ *    |    +-----------------------> i
+ *    |         
+ *    |----------------------------> I
+ *              X0        X1  
+ *
+ * box 0 -> I=0 J=0 IJ=00  = 0
+ * box 1 -> I=1 J=0 IJ=01  = 1
+ * box 2 -> I=0 J=1 IJ=10  = 2
+ * box 3 -> I=1 J=1 IJ=11  = 3
+ */
+//IJ(i,j,l) returns the box number of i and j with respect to l
+//if !j&l and !i&l -> 0 (box zero: lower left )
+//if !j&l and  i&l -> 1 (box one:  lower right)
+//if  j&l and !i&l -> 2 (box two:  upper left )
+//if  j&l and  i&l -> 3 (box three:upper right)
+#define IJ(i,j,l)  ((j&l) ? ((i&l) ? 3:2 ) :((i&l) ? 1:0 ))
+/*}}}*/
+
+	/*Constructors/Destructors*/
+/*FUNCTION Quadtree::Quadtree(){{{*/
+Quadtree::Quadtree(){
+	_error2_("Constructor not supported");
+
+}
+/*}}}*/
+/*FUNCTION Quadtree::Quadtree(double xmin,double xmax,double ymin,double ymax,int maxdepth){{{*/
+Quadtree::Quadtree(double xmin,double xmax,double ymin,double ymax,int maxdepth){
+
+	/*Intermediaries*/
+	double length;
+
+	/*Initialize fields*/
+	this->MaxDepth=maxdepth;
+	this->NbQuadtreeBox=0;
+	this->NbObs=0;
+
+	/*Create container*/
+	this->boxcontainer=new DataSet();
+
+	/*Create Root, pointer toward the main box*/
+	length=max(xmax-xmin,ymax-ymin);
+	this->root=NewQuadtreeBox(xmin+length/2,ymin+length/2,length);
+}
+/*}}}*/
+	/*FUNCTION Quadtree::~Quadtree(){{{*/
+	Quadtree::~Quadtree(){
+
+		delete boxcontainer;
+		root=NULL;
+
+	}
+	/*}}}*/
+
+	/*Methods*/
+/*FUNCTION Quadtree::Add{{{*/
+void  Quadtree::Add(Observation* observation){
+
+	/*Intermediaries*/
+	int          xi,yi,ij,level,levelbin;
+	QuadtreeBox **pbox    = NULL; // pointer toward current box b
+	QuadtreeBox **pmaster = NULL; // pointer toward master of b
+	QuadtreeBox  *box     = NULL; // current box b
+	QuadtreeBox  *slave   = NULL; // suslaveox of b (if necessary)
+	Observation  *obs[4];
+
+	/*Get integer coodinates*/
+	xi = observation->xi;
+	yi = observation->yi;
+
+	/*Initialize levels*/
+	level    = 0;
+	levelbin = (1L<<this->MaxDepth);// = 2^30
+
+	/*Get inital box (the largest)*/
+	pmaster = &root;
+	pbox    = &root;
+
+	/*Find the smallest box where the observation is located*/
+	while((box=*pbox) && (box->nbitems<0)){ 
+
+		/*Go down one level (levelbin = 00100 -> 00010)*/
+		levelbin>>=1; level+=1; _assert_(level<this->MaxDepth);
+
+		/*Get next box according to the bit value (levelbin)*/
+		pmaster = pbox;
+		pbox    = &box->box[IJ(xi,yi,levelbin)];
+	}
+	_assert_(levelbin>0);
+
+	/*Now, try to add the vertex, if the box is full (nbitems=4), we have to divide it in 4 new boxes*/
+	while((box=*pbox) && (box->nbitems==4)){
+
+		/*Copy the 4 observation in the current Quadtreebox*/
+		obs[0] = box->obs[0];
+		obs[1] = box->obs[1];
+		obs[2] = box->obs[2];
+		obs[3] = box->obs[3];
+
+		/*set nbitems as -1 (now holding boxes instead of observations)*/
+		box->nbitems = -1;
+		box->box[0]  = NULL;
+		box->box[1]  = NULL;
+		box->box[2]  = NULL;
+		box->box[3]  = NULL;
+
+		/*Go down one level (levelbin = 00010 -> 00001)*/
+		levelbin>>=1; level+=1; _assert_(level<this->MaxDepth);
+
+		/*Put the four observations in the new boxes*/
+		for (int k=0;k<4;k++){
+
+			/*Get box for observation number k*/
+			ij    = IJ(obs[k]->xi,obs[k]->yi,levelbin);
+			slave = box->box[ij];
+			if(!slave){
+				box->box[ij] = NewQuadtreeBox(box,ij);
+				slave        = box->box[ij];
+			}
+			slave->obs[slave->nbitems++] = obs[k];
+		}
+
+		/*Get the suslaveox where the current observation is located*/
+		ij      = IJ(xi,yi,levelbin);
+		pmaster = pbox;
+		pbox    = &box->box[ij];
+	}
+
+	/*alloc the QuadtreeBox if necessary and add current observation*/
+	box = *pbox;
+	if(!box){
+		ij  = IJ(xi,yi,levelbin);
+		box = *pbox = NewQuadtreeBox(*pmaster,ij);
+	}
+	box->obs[box->nbitems++]=observation;
+	NbObs++;
+
+}/*}}}*/
+/*FUNCTION Quadtree::AddAndAverage{{{*/
+void Quadtree::AddAndAverage(double x,double y,double value){
+
+	QuadtreeBox **pbox = NULL;
+	QuadtreeBox  *box  = NULL;
+	int           xi,yi;
+	int           level,levelbin;
+	int           index;
+	double        length,length2;
+
+	/*Get integer coodinates*/
+	this->IntergerCoordinates(&xi,&yi,x,y);
+
+	/*Initialize levels*/
+	level    = 0;
+	levelbin = (1L<<this->MaxDepth);// = 2^30
+
+	/*Get inital box (the largest)*/
+	pbox=&root;
+
+	/*Find the smallest box where this point is located*/
+	while((box=*pbox) && (box->nbitems<0)){ 
+
+		levelbin>>=1; level+=1; 
+
+		pbox = &box->box[IJ(xi,yi,levelbin)];
+	}
+
+	/*Add obervation in this box (should be full)*/
+	if(box && box->nbitems==4){
+		index  = 0;
+		length = pow(box->obs[0]->x - x,2.) + pow(box->obs[0]->y - y,2.);
+		for(int i=1;i<4;i++){
+			length2 = pow(box->obs[i]->x - x,2.) + pow(box->obs[i]->y - y,2.);
+			if(length2<length){
+				index  = i;
+				length = length2;
+			}
+		}
+
+		/*We found the closest observation, now average observation (do not change xi and yi to avoid round off errors*/
+		box->obs[index]->x = (box->obs[index]->weight*box->obs[index]->x + x)/(box->obs[index]->weight+1);
+		box->obs[index]->y = (box->obs[index]->weight*box->obs[index]->y + y)/(box->obs[index]->weight+1);
+		box->obs[index]->xi= int((box->obs[index]->weight*double(box->obs[index]->xi) + double(xi))/(box->obs[index]->weight+1));
+		box->obs[index]->yi= int((box->obs[index]->weight*double(box->obs[index]->yi) + double(yi))/(box->obs[index]->weight+1));
+		box->obs[index]->value   = (box->obs[index]->weight*box->obs[index]->value + value)/(box->obs[index]->weight+1);
+		box->obs[index]->weight += 1;
+	}
+	else{
+		_error2_("Box is not full");
+	}
+}/*}}}*/
+/*FUNCTION Quadtree::ClosestObs{{{*/
+void Quadtree::ClosestObs(int *pindex,double x,double y){
+
+	QuadtreeBox **pbox = NULL;
+	QuadtreeBox  *box  = NULL;
+	int           xi,yi;
+	int           level,levelbin;
+	int           index = -1;
+	double        length,length2;
+
+	/*Get integer coodinates*/
+	this->IntergerCoordinates(&xi,&yi,x,y);
+
+	/*Initialize levels*/
+	level    = 0;
+	levelbin = (1L<<this->MaxDepth);// = 2^30
+
+	/*Get inital box (the largest)*/
+	pbox=&root;
+
+	/*Find the smallest box where this point is located*/
+	while((box=*pbox) && (box->nbitems<0)){ 
+
+		levelbin>>=1; level+=1; 
+
+		pbox = &box->box[IJ(xi,yi,levelbin)];
+	}
+
+	/*Add obervation in this box (should be full)*/
+	if(box && box->nbitems>0){
+		index  = box->obs[0]->index;
+		length = pow(box->obs[0]->x - x,2.) + pow(box->obs[0]->y - y,2.);
+		for(int i=1;i<box->nbitems;i++){
+			length2 = pow(box->obs[i]->x - x,2.) + pow(box->obs[i]->y - y,2.);
+			if(length2<length){
+				index  = box->obs[i]->index;
+				length = length2;
+			}
+		}
+	}
+
+	*pindex=index;
+}/*}}}*/
+/*FUNCTION Quadtree::Echo{{{*/
+void  Quadtree::Echo(void){
+
+	_printLine_("Quadtree:");
+	_printLine_("   MaxDepth      = " << this->MaxDepth);
+	_printLine_("   NbQuadtreeBox = " << this->NbQuadtreeBox);
+	_printLine_("   NbObs         = " << this->NbObs);
+	_printLine_("   root          = " << this->root);
+
+}/*}}}*/
+/*FUNCTION Quadtree::DeepEcho{{{*/
+void  Quadtree::DeepEcho(void){
+
+	_printLine_("Quadtree:");
+	_printLine_("   MaxDepth      = " << this->MaxDepth);
+	_printLine_("   NbQuadtreeBox = " << this->NbQuadtreeBox);
+	_printLine_("   NbObs         = " << this->NbObs);
+	_printLine_("   root          = " << this->root);
+	boxcontainer->Echo();
+
+}/*}}}*/
+/*FUNCTION Quadtree::IntergerCoordinates{{{*/
+void  Quadtree::IntergerCoordinates(int *xi,int *yi,double x,double y){
+
+	/*Intermediaries*/
+	double coefficient;
+	double xmin,ymin;
+
+	/*Checks in debugging mode*/
+	_assert_(xi && yi);
+	_assert_(this->root);
+
+	/*coeffIcoor is the coefficient used for integer coordinates:
+	 *                (x-xmin)
+	 * xi = (2^30 -1) --------- 
+	 *                 length
+	 * coefficient = (2^30 -1)/length
+	 */
+	coefficient = double((1L<<this->MaxDepth)-1)/(this->root->length);
+	xmin        = this->root->xcenter - this->root->length/2;
+	ymin        = this->root->ycenter - this->root->length/2;
+
+	*xi=int(coefficient*(x - xmin));
+	*yi=int(coefficient*(y - ymin));
+}/*}}}*/
+/*FUNCTION Quadtree::NewQuadtreeBox(double xcenter,double ycenter,double length){{{*/
+Quadtree::QuadtreeBox* Quadtree::NewQuadtreeBox(double xcenter,double ycenter,double length){
+
+	/*Output*/
+	QuadtreeBox* newbox=NULL;
+
+	/*Create and initialize a new box*/
+	newbox=new QuadtreeBox();
+	newbox->nbitems=0;
+	newbox->xcenter=xcenter;
+	newbox->ycenter=ycenter;
+	newbox->length=length;
+	newbox->box[0]=NULL;
+	newbox->box[1]=NULL;
+	newbox->box[2]=NULL;
+	newbox->box[3]=NULL;
+
+	/*Add to container*/
+	this->boxcontainer->AddObject(newbox);
+	NbQuadtreeBox++;
+
+	/*currentbox now points toward next quadtree box*/
+	return newbox;
+}/*}}}*/
+/*FUNCTION Quadtree::NewQuadtreeBox(QuadtreeBox* master,int index) {{{*/
+Quadtree::QuadtreeBox* Quadtree::NewQuadtreeBox(QuadtreeBox* master,int index){
+
+	/*Output*/
+	QuadtreeBox* newbox=NULL;
+
+	/*Checks in debugging mode*/
+	_assert_(master);
+
+	/*Create and initialize a new box*/
+	newbox=new QuadtreeBox();
+	newbox->nbitems=0;
+	newbox->box[0]=NULL;
+	newbox->box[1]=NULL;
+	newbox->box[2]=NULL;
+	newbox->box[3]=NULL;
+	switch(index){
+		case 0:
+			newbox->xcenter=master->xcenter - master->length/4;
+			newbox->ycenter=master->ycenter - master->length/4;
+			break;
+		case 1:
+			newbox->xcenter=master->xcenter + master->length/4;
+			newbox->ycenter=master->ycenter - master->length/4;
+			break;
+		case 2:
+			newbox->xcenter=master->xcenter - master->length/4;
+			newbox->ycenter=master->ycenter + master->length/4;
+			break;
+		case 3:
+			newbox->xcenter=master->xcenter + master->length/4;
+			newbox->ycenter=master->ycenter + master->length/4;
+			break;
+		default:
+			_error2_("Case " << index << " not supported");
+	}
+	newbox->length=master->length/2;
+
+	/*Add to container*/
+	this->boxcontainer->AddObject(newbox);
+	NbQuadtreeBox++;
+
+	/*currentbox now points toward next quadtree box*/
+	return newbox;
+}/*}}}*/
+/*FUNCTION Quadtree::QuadtreeDepth{{{*/
+void Quadtree::QuadtreeDepth(int* A,int xi,int yi){
+
+	QuadtreeBox **pbox = NULL;
+	QuadtreeBox  *box  = NULL;
+	int           level,levelbin;
+
+	/*Initialize levels*/
+	level    = 0;
+	levelbin = (1L<<this->MaxDepth);// = 2^30
+
+	/*Get inital box (the largest)*/
+	pbox=&root;
+
+	/*Find the smallest box where this point is located*/
+	while((box=*pbox) && (box->nbitems<0)){ 
+
+		levelbin>>=1; level+=1; _assert_(level<this->MaxDepth);
+
+		pbox = &box->box[IJ(xi,yi,levelbin)];
+	}
+	if(box && box->nbitems>0){
+		/*This box is not empty, add one level*/
+		level+=1;
+	}
+
+	*A=level;
+}/*}}}*/
+/*FUNCTION Quadtree::QuadtreeDepth2{{{*/
+void Quadtree::QuadtreeDepth2(int* A,int xi,int yi){
+
+	QuadtreeBox **pbox = NULL;
+	QuadtreeBox  *box  = NULL;
+	int           level,levelbin;
+
+	/*Initialize levels*/
+	level    = 0;
+	levelbin = (1L<<this->MaxDepth);// = 2^30
+
+	/*Get inital box (the largest)*/
+	pbox=&root;
+
+	/*Find the smallest box where this point is located*/
+	while((box=*pbox) && (box->nbitems<0)){ 
+
+		levelbin>>=1; level+=1; 
+
+		pbox = &box->box[IJ(xi,yi,levelbin)];
+	}
+	if(box && box->nbitems>0){
+		/*This box is not empty, add one level*/
+		level+=1;
+	}
+
+	/*If we were to add the vertex, get level*/
+	if(box && box->nbitems==4){
+		int ij;
+		bool flag=true;
+		while(flag){
+
+			levelbin>>=1; level+=1;
+			if(level>this->MaxDepth){
+				level+=1;
+				break;
+			}
+
+			/*loop over the four observations*/
+			ij=IJ(box->obs[0]->xi,box->obs[0]->yi,levelbin);
+			for (int k=1;k<4;k++){
+				if(IJ(box->obs[k]->xi,box->obs[k]->yi,levelbin) != ij){
+					flag = false;
+				}
+			}
+			if(IJ(xi,yi,levelbin)!=ij){
+				flag = false;
+			}
+		}
+	}
+
+	*A=level;
+}/*}}}*/
+/*FUNCTION Quadtree::RangeSearch{{{*/
+void Quadtree::RangeSearch(int **pindices,int *pnobs,double x,double y,double range){
+
+	/*Intermediaries*/
+	int  nobs;
+	int *indices = NULL;
+
+	/*Allocate indices (maximum by default*/
+	if(this->NbObs) indices = xNew<int>(this->NbObs);
+	nobs = 0;
+
+	if(this->root) this->root->RangeSearch(indices,&nobs,x,y,range);
+
+	/*Clean-up and return*/
+	*pnobs=nobs;
+	*pindices=indices;
+
+}/*}}}*/
+
+/*QuadtreeBox methos*/
+/*FUNCTION QuadtreeBox::Echo{{{*/
+void  Quadtree::QuadtreeBox::Echo(void){
+
+	_printLine_("QuadtreeBox:");
+	_printLine_("   nbitems = " << this->nbitems);
+	_printLine_("   xcenter = " << this->xcenter);
+	_printLine_("   ycenter = " << this->ycenter);
+	_printLine_("   length  = " << this->length);
+
+}/*}}}*/
+/*FUNCTION QuadtreeBox::IsWithinRange{{{*/
+int Quadtree::QuadtreeBox::IsWithinRange(double x,double y,double range){
+
+	/*Return 0 if the 2 boxes do not overlap*/
+	if(this->xcenter+this->length/2 < x-range) return 0;
+	if(this->xcenter-this->length/2 > x+range) return 0;
+	if(this->ycenter+this->length/2 < y-range) return 0;
+	if(this->ycenter-this->length/2 > y+range) return 0;
+
+	/*Return 2 if the this box is included in the range*/
+	if(this->xcenter+this->length/2 <= x+range &&
+		this->ycenter+this->length/2 <= y+range &&
+		this->xcenter-this->length/2 >= x-range &&
+		this->ycenter-this->length/2 >= y-range) return 2;
+
+	/*This is a simple overlap*/
+	return 1;
+
+}/*}}}*/
+/*FUNCTION QuadtreeBox::RangeSearch{{{*/
+void Quadtree::QuadtreeBox::RangeSearch(int* indices,int *pnobs,double x,double y,double range){
+
+	/*Intermediaries*/
+	int i,nobs;
+
+	/*Recover current number of observations*/
+	nobs = *pnobs;
+
+	switch(this->IsWithinRange(x,y,range)){
+		case 0:
+			/*If this box is not within range, return*/
+			break;
+		case 2:
+			/*This box is included in range*/
+			this->WriteObservations(indices,&nobs);
+			break;
+		case 1:
+			/*This box is partly included*/
+			if(this->nbitems>0){
+				/*If this box has only observations, add indices that are within range*/
+				for(i=0;i<this->nbitems;i++){
+					if(fabs(this->obs[i]->x-x) <= range && fabs(this->obs[i]->y-y) <= range){
+						indices[nobs++]=this->obs[i]->index;
+					}
+				}
+			}
+			else{
+				/*This box points toward boxes*/
+				if(this->box[0]) this->box[0]->RangeSearch(indices,&nobs,x,y,range);
+				if(this->box[1]) this->box[1]->RangeSearch(indices,&nobs,x,y,range);
+				if(this->box[2]) this->box[2]->RangeSearch(indices,&nobs,x,y,range);
+				if(this->box[3]) this->box[3]->RangeSearch(indices,&nobs,x,y,range);
+			}
+			break;
+		default:
+			_error2_("Case " << this->IsWithinRange(x,y,range) << " not supported");
+	}
+
+	/*Assign output pointers: */
+	*pnobs=nobs;
+}/*}}}*/
+/*FUNCTION QuadtreeBox::WriteObservations{{{*/
+void Quadtree::QuadtreeBox::WriteObservations(int* indices,int *pnobs){
+
+	/*Intermediaries*/
+	int i,nobs;
+
+	/*Recover current number of observations*/
+	nobs = *pnobs;
+
+	if(this->nbitems>0){
+		/*If this box has only observations, add all indices*/
+		for(i=0;i<this->nbitems;i++){
+			indices[nobs++]=this->obs[i]->index;
+		}
+	}
+	else{
+		/*This box points toward boxes, */
+		if(this->box[0]) this->box[0]->WriteObservations(indices,&nobs);
+		if(this->box[1]) this->box[1]->WriteObservations(indices,&nobs);
+		if(this->box[2]) this->box[2]->WriteObservations(indices,&nobs);
+		if(this->box[3]) this->box[3]->WriteObservations(indices,&nobs);
+	}
+
+	/*Assign output pointers: */
+	*pnobs=nobs;
+}/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/Quadtree.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/Quadtree.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/Quadtree.h	(revision 12821)
@@ -0,0 +1,66 @@
+
+#ifndef _QUADTREE_H
+#define _QUADTREE_H
+
+class Observation;
+
+class Quadtree{
+
+	private:
+		/* A quadtree box contains up to 4 points (locations). 4 new quadtree boxes are
+		 * created if a fifth point is added to the same box. A Quadtree box is therefore
+		 * composed of EITHER:
+		 * - up to 4 vertices
+		 * - 4 "sub" quadtree boxes*/
+
+		class QuadtreeBox: public Object{ 
+			public:
+				int    nbitems; // number of current vertices in the box
+				double xcenter; // x position of the center (double)
+				double ycenter; // x position of the center (double)
+				double length;  // width of the box
+				union{
+					QuadtreeBox *box[4];
+					Observation *obs[4];
+				};
+
+				/*Object functions (Needed because the Quadtree uses a Container*/
+				void    Echo();
+				void    DeepEcho()  {_error2_("not implemented yet"); };
+				int     Id()        {_error2_("not implemented yet"); };
+				int     MyRank()    {_error2_("not implemented yet"); };
+				int     ObjectEnum(){_error2_("not implemented yet"); };
+				Object *copy()      {_error2_("not implemented yet"); };
+
+				/*Methods*/
+				int          IsWithinRange(double  x,double y,double range);
+				void         RangeSearch(int *indices,int *pnobs,double x,double y,double range);
+				void         WriteObservations(int *indices,int *pnobs);
+
+		};
+
+		/*Quadtree private Fields*/
+		DataSet* boxcontainer;
+
+	public:
+		int          MaxDepth;          // maximum number of subdivision
+		QuadtreeBox *root;              // main box
+		int          NbQuadtreeBox;     // total number of boxes
+		int          NbObs;             // number of points
+
+		Quadtree();
+		Quadtree(double xmin,double xmax,double ymin,double ymax,int maxdepth_in);
+		~Quadtree();
+		void         Add(Observation *observation);
+		void         AddAndAverage(double x,double y,double value);
+		void         ClosestObs(int *pindex,double x,double y);
+		void         DeepEcho(void);
+		void         Echo(void);
+		void         IntergerCoordinates(int *xi,int *yi,double x,double y);
+		QuadtreeBox *NewQuadtreeBox(double xcenter,double ycenter,double length);
+		QuadtreeBox *NewQuadtreeBox(QuadtreeBox* master,int index);
+		void         QuadtreeDepth(int *A,int xi,int yi);
+		void         QuadtreeDepth2(int *A,int xi,int yi);
+		void         RangeSearch(int **pindices,int *pnobs,double x,double y,double range);
+};
+#endif //_QUADTREE_H
Index: /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.cpp	(revision 12821)
@@ -0,0 +1,98 @@
+/*!\file SphericalVariogram.c
+ * \brief: implementation of the SphericalVariogram object
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+#include "../../shared/shared.h"
+#include "../../include/include.h"
+
+/*SphericalVariogram constructors and destructor*/
+/*FUNCTION SphericalVariogram::SphericalVariogram(){{{*/
+SphericalVariogram::SphericalVariogram(){
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+	return;
+}
+/*}}}*/
+/*FUNCTION SphericalVariogram::SphericalVariogram(Options* options){{{*/
+SphericalVariogram::SphericalVariogram(Options* options){
+
+	/*Defaults*/
+	this->nugget = 0.2;
+	this->sill   = 1;
+	this->range  = SQRT3;
+
+	/*Overwrite from options*/
+	if(options->GetOption("nugget")) options->Get(&this->nugget,"nugget");
+	if(options->GetOption("sill"))   options->Get(&this->sill,"sill");
+	if(options->GetOption("range"))  options->Get(&this->range,"range");
+
+	/*Checks*/
+	if(nugget==sill) _error2_("nugget and sill cannot be equal (constant semivariogram not allowed)");
+}
+/*}}}*/
+/*FUNCTION SphericalVariogram::~SphericalVariogram(){{{*/
+SphericalVariogram::~SphericalVariogram(){
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION SphericalVariogram::Echo {{{*/
+void SphericalVariogram::Echo(void){
+	_printLine_("SphericalVariogram");
+	_printLine_("   nugget: " << this->nugget);
+	_printLine_("   sill  : " << this->sill);
+	_printLine_("   range : " << this->range);
+}
+/*}}}*/
+
+/*Variogram function*/
+/*FUNCTION SphericalVariogram::Covariance{{{*/
+double SphericalVariogram::Covariance(double deltax,double deltay){
+	/*The covariance can be deduced from the variogram from the following
+	 * relationship:
+	 *    2 gamma = C(x,x) + C(y,y) -2 C(x,y)
+	 * so
+	 *    C(h) = sill - gamma                                            */
+	double h,cova;
+
+	/*Calculate length square*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*return covariance*/
+	if(h<=range)
+	 cova = (sill-nugget)*(1 - (3*h)/(2*range) + pow(h,3.)/(2*pow(range,3.)) );
+	else
+	 cova = 0.;
+
+	return cova;
+}
+/*}}}*/
+/*FUNCTION SphericalVariogram::SemiVariogram{{{*/
+double SphericalVariogram::SemiVariogram(double deltax,double deltay){
+	/*http://en.wikipedia.org/wiki/Variogram*/
+	double h,gamma;
+
+	/*Calculate length square*/
+	h=sqrt(pow(deltax,2.)+pow(deltay,2.));
+
+	/*return semi-variogram*/
+	if(h<=range)
+	 gamma = (sill-nugget)*( (3*h)/(2*range) - pow(h,3.)/(2*pow(range,3.)) ) + nugget;
+	else
+	 gamma = sill;
+
+	return gamma;
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/SphericalVariogram.h	(revision 12821)
@@ -0,0 +1,35 @@
+/*! \file SphericalVariogram.h 
+ *  \brief: header file for triavertexinput object
+ */
+
+#ifndef _SPHERICALVARIOGRAM_H_
+#define _SPHERICALVARIOGRAM_H_
+
+/*Headers:*/
+#include "./Variogram.h"
+
+class SphericalVariogram: public Variogram{
+
+	public:
+		double nugget; //The height of the jump of the semivariogram at the discontinuity at the origin
+		double sill;   //Limit of the variogram tending to infinity lag distances
+		double range;  //The distance in which the difference of the variogram from the sill becomes negligible
+
+		/*SphericalVariogram constructors, destructors*/
+		SphericalVariogram();
+		SphericalVariogram(Options* options);
+		~SphericalVariogram();
+
+		/*Object virtual functions definitions*/
+		void  Echo();
+		void  DeepEcho(){_error2_("Not implemented yet");};
+		int   Id(){_error2_("Not implemented yet");}; 
+		int   MyRank(){_error2_("Not implemented yet");};
+		int   ObjectEnum(){_error2_("Not implemented yet");};
+		Object* copy(){_error2_("Not implemented yet");};
+
+		/*Variogram functions*/
+		double SemiVariogram(double deltax,double deltay);
+		double Covariance(double deltax,double deltay);
+};
+#endif  /* _SPHERICALVARIOGRAM_H */
Index: /issm/trunk-jpl/src/c/classes/kriging/Variogram.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/kriging/Variogram.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/kriging/Variogram.h	(revision 12821)
@@ -0,0 +1,18 @@
+/*!\file:  Variogram.h
+ * \brief abstract class for Variogram object
+ */ 
+
+#ifndef _VARIOGRAM_H_
+#define _VARIOGRAM_H_
+
+#include "../Object.h"
+
+class Variogram: public Object{
+
+	public: 
+		virtual ~Variogram(){};
+		virtual double SemiVariogram(double deltax,double deltay)=0;
+		virtual double Covariance(double deltax,double deltay)=0;
+
+};
+#endif
Index: /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.cpp	(revision 12821)
@@ -0,0 +1,496 @@
+/*!\file ElementMatrix.cpp
+ * \brief: implementation of the ElementMatrix object, used to plug values from element into global stiffness matrix
+ */
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../Container/Container.h"
+#include "../../include/include.h"
+/*}}}*/
+
+/*ElementMatrix constructors and destructor*/
+/*FUNCTION ElementMatrix::ElementMatrix(){{{*/
+ElementMatrix::ElementMatrix(){
+
+	this->nrows=0;
+	this->ncols=0;
+	this->values=NULL;
+	this->dofsymmetrical=false;
+
+	this->row_fsize=0;
+	this->row_flocaldoflist=NULL;
+	this->row_fglobaldoflist=NULL;
+	this->row_ssize=0;
+	this->row_slocaldoflist=NULL;
+	this->row_sglobaldoflist=NULL;
+
+	this->col_fsize=0;
+	this->col_flocaldoflist=NULL;
+	this->col_fglobaldoflist=NULL;
+	this->col_ssize=0;
+	this->col_slocaldoflist=NULL;
+	this->col_sglobaldoflist=NULL;
+
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke){{{*/
+ElementMatrix::ElementMatrix(ElementMatrix* Ke){
+
+	if(!Ke) _error2_("Input Element Matrix is a NULL pointer");
+	this->Init(Ke);
+	return;
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2){{{*/
+ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2){
+
+	/*intermediaries*/
+	int i,j,counter;
+	int gsize,fsize,ssize;
+	int* P=NULL;
+	bool found;
+
+	/*If one of the two matrix is NULL, we copy the other one*/
+	if(!Ke1 && !Ke2){
+		_error2_("Two input element matrices are NULL");
+	}
+	else if(!Ke1){
+		this->Init(Ke2);
+		return;
+	}
+	else if(!Ke2){
+		this->Init(Ke1);
+		return;
+	}
+
+	/*General Case: Ke1 and Ke2 are not empty*/
+	if(!Ke1->dofsymmetrical || !Ke2->dofsymmetrical) _error2_("merging 2 non dofsymmetrical matrices not implemented yet");
+
+	/*Initialize itransformation matrix Ke[P[i]] = Ke2[i]*/
+	P=xNew<int>(Ke2->nrows);
+
+	/*1: Get the new numbering of Ke2 and get size of the new matrix*/
+	gsize=Ke1->nrows;
+	for(i=0;i<Ke2->nrows;i++){
+		found=false;
+		for(j=0;j<Ke1->nrows;j++){
+			if(Ke2->gglobaldoflist[i]==Ke1->gglobaldoflist[j]){
+				found=true; P[i]=j; break;
+			}
+		}
+		if(!found){
+			P[i]=gsize; gsize++;
+		}
+	}
+
+	/*2: Initialize static fields*/
+	this->nrows=gsize;
+	this->ncols=gsize;
+	this->dofsymmetrical=true;
+
+	/*Gset and values*/
+	this->gglobaldoflist=xNew<int>(this->nrows);
+	this->values=xNewZeroInit<IssmDouble>(this->nrows*this->ncols);
+	for(i=0;i<Ke1->nrows;i++){
+		for(j=0;j<Ke1->ncols;j++){
+			this->values[i*this->ncols+j] += Ke1->values[i*Ke1->ncols+j];
+		}
+		this->gglobaldoflist[i]=Ke1->gglobaldoflist[i];
+	}
+	for(i=0;i<Ke2->nrows;i++){
+		for(j=0;j<Ke2->ncols;j++){
+			this->values[P[i]*this->ncols+P[j]] += Ke2->values[i*Ke2->ncols+j];
+		}
+		this->gglobaldoflist[P[i]]=Ke2->gglobaldoflist[i];
+	}
+
+	/*Fset*/
+	fsize=Ke1->row_fsize;
+	for(i=0;i<Ke2->row_fsize;i++){
+		if(P[Ke2->row_flocaldoflist[i]] >= Ke1->nrows) fsize++;
+	}
+	this->row_fsize=fsize;
+	if(fsize){
+		this->row_flocaldoflist =xNew<int>(fsize);
+		this->row_fglobaldoflist=xNew<int>(fsize);
+		for(i=0;i<Ke1->row_fsize;i++){
+			this->row_flocaldoflist[i] =Ke1->row_flocaldoflist[i];
+			this->row_fglobaldoflist[i]=Ke1->row_fglobaldoflist[i];
+		}
+		counter=Ke1->row_fsize;
+		for(i=0;i<Ke2->row_fsize;i++){
+			if(P[Ke2->row_flocaldoflist[i]] >= Ke1->nrows){
+				this->row_flocaldoflist[counter] =P[Ke2->row_flocaldoflist[i]];
+				this->row_fglobaldoflist[counter]=Ke2->row_fglobaldoflist[i];
+				counter++;
+			}
+		}
+	}
+	else{
+		this->row_flocaldoflist=NULL;
+		this->row_fglobaldoflist=NULL;
+	}
+
+	/*Sset*/
+	ssize=Ke1->row_ssize;
+	for(i=0;i<Ke2->row_ssize;i++){
+		if(P[Ke2->row_slocaldoflist[i]] >= Ke1->nrows) ssize++;
+	}
+	this->row_ssize=ssize;
+	if(ssize){
+		this->row_slocaldoflist =xNew<int>(ssize);
+		this->row_sglobaldoflist=xNew<int>(ssize);
+		for(i=0;i<Ke1->row_ssize;i++){
+			this->row_slocaldoflist[i] =Ke1->row_slocaldoflist[i];
+			this->row_sglobaldoflist[i]=Ke1->row_sglobaldoflist[i];
+		}
+		counter=Ke1->row_ssize;
+		for(i=0;i<Ke2->row_ssize;i++){
+			if(P[Ke2->row_slocaldoflist[i]] >= Ke1->nrows){
+				this->row_slocaldoflist[counter] =P[Ke2->row_slocaldoflist[i]];
+				this->row_sglobaldoflist[counter]=Ke2->row_sglobaldoflist[i];
+				counter++;
+			}
+		}
+	}
+	else{
+		this->row_slocaldoflist=NULL;
+		this->row_sglobaldoflist=NULL;
+	}
+
+	/*don't do cols, we can pick them up from the rows: */
+	this->col_fsize=0;
+	this->col_flocaldoflist=NULL;
+	this->col_fglobaldoflist=NULL;
+	this->col_ssize=0;
+	this->col_slocaldoflist=NULL;
+	this->col_sglobaldoflist=NULL;
+
+	/*clean-up*/
+	xDelete<int>(P);
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2,ElementMatrix* Ke3){{{*/
+ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2,ElementMatrix* Ke3){
+
+	/*Concatenate all matrices*/
+	ElementMatrix* Ke12 =new ElementMatrix(Ke1,Ke2);
+	ElementMatrix* Ke123=new ElementMatrix(Ke12,Ke3);
+
+	/*Initialize current object with this matrix*/
+	this->Init(Ke123);
+
+	/*clean-up*/
+	delete Ke12;
+	delete Ke123;
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation){{{*/
+ElementMatrix::ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation){
+
+	/*get Matrix size and properties*/
+	this->dofsymmetrical=true;
+	this->nrows=GetNumberOfDofs(nodes,numnodes,GsetEnum,approximation);
+	this->ncols=this->nrows;
+
+	/*fill values with 0: */
+	this->values=xNewZeroInit<IssmDouble>(this->nrows*this->ncols);
+
+	/*g list*/
+	this->gglobaldoflist=GetGlobalDofList(nodes,numnodes,GsetEnum,approximation);
+
+	/*get dof lists for f and s set: */
+	this->row_fsize=GetNumberOfDofs(nodes,numnodes,FsetEnum,approximation);
+	this->row_flocaldoflist =GetLocalDofList( nodes,numnodes,FsetEnum,approximation);
+	this->row_fglobaldoflist=GetGlobalDofList(nodes,numnodes,FsetEnum,approximation);
+	this->row_ssize=GetNumberOfDofs(nodes,numnodes,SsetEnum,approximation);
+	this->row_slocaldoflist =GetLocalDofList( nodes,numnodes,SsetEnum,approximation);
+	this->row_sglobaldoflist=GetGlobalDofList(nodes,numnodes,SsetEnum,approximation);
+
+	/*Because this matrix is "dofsymmetrical" don't do cols, we can pick them up from the rows: */
+	this->col_fsize=0;
+	this->col_flocaldoflist=NULL;
+	this->col_fglobaldoflist=NULL;
+	this->col_ssize=0;
+	this->col_slocaldoflist=NULL;
+	this->col_sglobaldoflist=NULL;
+
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::~ElementMatrix(){{{*/
+ElementMatrix::~ElementMatrix(){
+	
+	xDelete<IssmDouble>(this->values);
+	xDelete<int>(this->gglobaldoflist);
+	xDelete<int>(this->row_flocaldoflist);
+	xDelete<int>(this->row_fglobaldoflist);
+	xDelete<int>(this->row_slocaldoflist);
+	xDelete<int>(this->row_sglobaldoflist);
+	xDelete<int>(this->col_flocaldoflist);
+	xDelete<int>(this->col_fglobaldoflist);
+	xDelete<int>(this->col_slocaldoflist);
+	xDelete<int>(this->col_sglobaldoflist);
+}
+/*}}}*/
+
+/*ElementMatrix specific routines: */
+/*FUNCTION ElementMatrix::AddToGlobal(Matrix* Kff, Matrix* Kfs){{{*/
+void ElementMatrix::AddToGlobal(Matrix* Kff, Matrix* Kfs){
+
+	int i,j;
+	IssmDouble* localvalues=NULL;
+
+	/*If Kfs is not provided, call the other function*/
+	if(!Kfs){
+		this->AddToGlobal(Kff);
+		return;
+	}
+
+	/*In debugging mode, check consistency (no NaN, and values not too big)*/
+	this->CheckConsistency();
+
+	if(this->dofsymmetrical){
+		/*only use row dofs to add values into global matrices: */
+
+		if(this->row_fsize){
+			/*first, retrieve values that are in the f-set from the g-set values matrix: */
+			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_fsize);
+			for(i=0;i<this->row_fsize;i++){
+				for(j=0;j<this->row_fsize;j++){
+					*(localvalues+this->row_fsize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_flocaldoflist[j]);
+				}
+			}
+			/*add local values into global  matrix, using the fglobaldoflist: */
+			Kff->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_fsize,this->row_fglobaldoflist,localvalues,ADD_VAL);
+
+			/*Free ressources:*/
+			xDelete<IssmDouble>(localvalues);
+		}
+
+
+		if((this->row_ssize!=0) && (this->row_fsize!=0)){
+			/*first, retrieve values that are in the f and s-set from the g-set values matrix: */
+			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_ssize);
+			for(i=0;i<this->row_fsize;i++){
+				for(j=0;j<this->row_ssize;j++){
+					*(localvalues+this->row_ssize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_slocaldoflist[j]);
+				}
+			}
+			/*add local values into global  matrix, using the fglobaldoflist: */
+			Kfs->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_ssize,this->row_sglobaldoflist,localvalues,ADD_VAL);
+
+			/*Free ressources:*/
+			xDelete<IssmDouble>(localvalues);
+		}
+	}
+	else{
+		_error2_("non dofsymmetrical matrix AddToGlobal routine not support yet!");
+	}
+
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::AddToGlobal(Matrix* Jff){{{*/
+void ElementMatrix::AddToGlobal(Matrix* Jff){
+
+	int i,j;
+	IssmDouble* localvalues=NULL;
+
+	/*Check that Jff is not NULL*/
+	_assert_(Jff); 
+
+	/*In debugging mode, check consistency (no NaN, and values not too big)*/
+	this->CheckConsistency();
+
+	if(this->dofsymmetrical){
+		/*only use row dofs to add values into global matrices: */
+
+		if(this->row_fsize){
+			/*first, retrieve values that are in the f-set from the g-set values matrix: */
+			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_fsize);
+			for(i=0;i<this->row_fsize;i++){
+				for(j=0;j<this->row_fsize;j++){
+					*(localvalues+this->row_fsize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_flocaldoflist[j]);
+				}
+			}
+			/*add local values into global  matrix, using the fglobaldoflist: */
+			Jff->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_fsize,this->row_fglobaldoflist,localvalues,ADD_VAL);
+
+			/*Free ressources:*/
+			xDelete<IssmDouble>(localvalues);
+		}
+
+	}
+	else{
+		_error2_("non dofsymmetrical matrix AddToGlobal routine not support yet!");
+	}
+
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::CheckConsistency{{{*/
+void ElementMatrix::CheckConsistency(void){
+	/*Check element matrix values, only in debugging mode*/
+	#ifdef _ISSM_DEBUG_ 
+	for (int i=0;i<this->nrows;i++){
+		for(int j=0;j<this->ncols;j++){
+			if (xIsNan<IssmDouble>(this->values[i*this->ncols+j])) _error2_("NaN found in Element Matrix");
+			if (fabs(this->values[i*this->ncols+j])>1.e+50) _error2_("Element Matrix values exceeds 1.e+50");
+		}
+	}
+	#endif
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::Transpose{{{*/
+void ElementMatrix::Transpose(void){
+
+	/*Intermediaries*/
+	ElementMatrix* Ke_copy=new ElementMatrix(this);
+
+	/*Update sizes*/
+	this->nrows=Ke_copy->ncols;
+	this->ncols=Ke_copy->nrows;
+
+	/*Transpose values*/
+	for (int i=0;i<this->nrows;i++) for(int j=0;j<this->ncols;j++) this->values[i*this->ncols+j]=Ke_copy->values[j*Ke_copy->ncols+i];
+
+	/*Transpose indices*/
+	if(!dofsymmetrical){
+		_error2_("not supported yet");
+	}
+
+	/*Clean up and return*/
+	delete Ke_copy;
+	return;
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::Echo{{{*/
+void ElementMatrix::Echo(void){
+
+	int i,j;
+	_printLine_("Element Matrix echo:");
+	_printLine_("   nrows: " << nrows);
+	_printLine_("   ncols: " << nrows);
+	_printLine_("   dofsymmetrical: " << (dofsymmetrical?"true":"false"));
+
+	_printLine_("   values:");
+	for(i=0;i<nrows;i++){
+		_printString_(setw(4) << right << i << ": ");
+		for(j=0;j<ncols;j++) _printString_( " " << setw(11) << setprecision (5) << right << values[i*ncols+j]);
+		_printLine_("");
+	}
+
+	_printString_("   gglobaldoflist (" << gglobaldoflist << "): ");
+	if(gglobaldoflist) for(i=0;i<nrows;i++) _printString_(" " << gglobaldoflist[i]); _printLine_("");
+
+	_printLine_("   row_fsize: " << row_fsize);
+	_printString_("   row_flocaldoflist  (" << row_flocaldoflist << "): ");
+	if(row_flocaldoflist) for(i=0;i<row_fsize;i++) _printString_(" " << row_flocaldoflist[i]); _printLine_(" ");
+	_printString_("   row_fglobaldoflist  (" << row_fglobaldoflist << "): ");
+	if(row_fglobaldoflist) for(i=0;i<row_fsize;i++) _printString_(" " << row_fglobaldoflist[i]); _printLine_(" ");
+
+	_printLine_("   row_ssize: " << row_ssize);
+	_printString_("   row_slocaldoflist  (" << row_slocaldoflist << "): ");
+	if(row_slocaldoflist) for(i=0;i<row_ssize;i++) _printString_(" " << row_slocaldoflist[i]); _printLine_(" ");
+	_printString_("   row_sglobaldoflist  (" << row_sglobaldoflist << "): ");
+	if(row_sglobaldoflist) for(i=0;i<row_ssize;i++) _printString_(" " << row_sglobaldoflist[i]); _printLine_(" ");
+
+	if(!dofsymmetrical){
+		_printLine_("   col_fsize: " << col_fsize);
+		_printString_("   col_flocaldoflist  (" << col_flocaldoflist << "): ");
+		if(col_flocaldoflist) for(i=0;i<col_fsize;i++) _printString_(" " << col_flocaldoflist[i]); _printLine_(" ");
+		_printString_("   col_fglobaldoflist  (" << col_fglobaldoflist << "): ");
+		if(col_fglobaldoflist) for(i=0;i<col_fsize;i++) _printString_(" " << col_fglobaldoflist[i]); _printLine_(" ");
+
+		_printLine_("   col_ssize: " << col_ssize);
+		_printString_("   col_slocaldoflist  (" << col_slocaldoflist << "): ");
+		if(col_slocaldoflist) for(i=0;i<col_ssize;i++) _printString_(" " << col_slocaldoflist[i]); _printLine_(" ");
+		_printString_("   col_sglobaldoflist  (" << col_sglobaldoflist << "): ");
+		if(col_sglobaldoflist) for(i=0;i<col_ssize;i++) _printString_(" " << col_sglobaldoflist[i]); _printLine_(" ");
+	}
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::Init{{{*/
+void ElementMatrix::Init(ElementMatrix* Ke){
+
+	_assert_(Ke);
+
+	this->nrows =Ke->nrows;
+	this->ncols =Ke->ncols;
+	this->dofsymmetrical=Ke->dofsymmetrical;
+
+	this->values=xNew<IssmDouble>(this->nrows*this->ncols);
+	xMemCpy<IssmDouble>(this->values,Ke->values,this->nrows*this->ncols);
+
+	this->gglobaldoflist=xNew<int>(this->nrows);
+	xMemCpy<int>(this->gglobaldoflist,Ke->gglobaldoflist,this->nrows);
+
+	this->row_fsize=Ke->row_fsize;
+	if(this->row_fsize){
+		this->row_flocaldoflist=xNew<int>(this->row_fsize);
+		xMemCpy<int>(this->row_flocaldoflist,Ke->row_flocaldoflist,this->row_fsize);
+		this->row_fglobaldoflist=xNew<int>(this->row_fsize);
+		xMemCpy<int>(this->row_fglobaldoflist,Ke->row_fglobaldoflist,this->row_fsize);
+	}
+	else{
+		this->row_flocaldoflist=NULL;
+		this->row_fglobaldoflist=NULL;
+	}
+
+	this->row_ssize=Ke->row_ssize;
+	if(this->row_ssize){
+		this->row_slocaldoflist=xNew<int>(this->row_ssize);
+		xMemCpy<int>(this->row_slocaldoflist,Ke->row_slocaldoflist,this->row_ssize);
+		this->row_sglobaldoflist=xNew<int>(this->row_ssize);
+		xMemCpy<int>(this->row_sglobaldoflist,Ke->row_sglobaldoflist,this->row_ssize);
+	}
+	else{
+		this->row_slocaldoflist=NULL;
+		this->row_sglobaldoflist=NULL;
+	}
+
+	this->col_fsize=Ke->col_fsize;
+	if(this->col_fsize){
+		this->col_flocaldoflist=xNew<int>(this->col_fsize);
+		xMemCpy<int>(this->col_flocaldoflist,Ke->col_flocaldoflist,this->col_fsize);
+		this->col_fglobaldoflist=xNew<int>(this->col_fsize);
+		xMemCpy<int>(this->col_fglobaldoflist,Ke->col_fglobaldoflist,this->col_fsize);
+	}
+	else{
+		this->col_flocaldoflist=NULL;
+		this->col_fglobaldoflist=NULL;
+	}
+
+	this->col_ssize=Ke->col_ssize;
+	if(this->col_ssize){
+		this->col_slocaldoflist=xNew<int>(this->col_ssize);
+		xMemCpy<int>(this->col_slocaldoflist,Ke->col_slocaldoflist,this->col_ssize);
+		this->col_sglobaldoflist=xNew<int>(this->col_ssize);
+		xMemCpy<int>(this->col_sglobaldoflist,Ke->col_sglobaldoflist,this->col_ssize);
+	}
+	else{
+		this->col_slocaldoflist=NULL;
+		this->col_sglobaldoflist=NULL;
+	}
+}
+/*}}}*/
+/*FUNCTION ElementMatrix::SetDiag{{{*/
+void ElementMatrix::SetDiag(IssmDouble scalar){
+
+	int i;
+
+	if(this->nrows!=this->ncols)_error2_("need square matrix in input!");
+
+	for(i=0;i<this->nrows;i++){
+		this->values[this->ncols*i+i]=scalar;
+	}
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/ElementMatrix.h	(revision 12821)
@@ -0,0 +1,69 @@
+/*!\file:  ElementMatrix.h
+ * \brief container for information needed to plug element matrix generated by elements 
+ * into the Kff and Kfs global matrices. 
+ * This object will hold the element matrix on the g-set, the local as well as global 
+ * dof lists in the f and s sets.
+ */ 
+
+#ifndef _ELEMENT_MATRIX_H_
+#define _ELEMENT_MATRIX_H_
+
+/*Headers:*/
+/*{{{*/
+#include "../Object.h"
+#include "../../toolkits/toolkits.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+class Node;
+/*}}}*/
+
+class ElementMatrix{
+
+	public:
+	
+		int      nrows;
+		int      ncols;
+		bool     dofsymmetrical;
+		IssmDouble*  values;
+
+		//gset
+		int*     gglobaldoflist;
+
+		/*row wise: */
+		//fset
+		int      row_fsize;
+		int*     row_flocaldoflist;
+		int*     row_fglobaldoflist;
+		//sset
+		int      row_ssize;
+		int*     row_slocaldoflist;
+		int*     row_sglobaldoflist;
+
+		/*column wise: */
+		//fset
+		int      col_fsize;
+		int*     col_flocaldoflist;
+		int*     col_fglobaldoflist;
+		//sset
+		int      col_ssize;
+		int*     col_slocaldoflist;
+		int*     col_sglobaldoflist;
+
+		/*ElementMatrix constructors, destructors {{{*/
+		ElementMatrix();
+		ElementMatrix(ElementMatrix* Ke);
+		ElementMatrix(ElementMatrix* Ke1,ElementMatrix* Ke2);
+		ElementMatrix(ElementMatrix* Ke1,ElementMatrix* Ke2,ElementMatrix* Ke3);
+		ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation=NoneApproximationEnum);
+		~ElementMatrix();
+		/*}}}*/
+		/*ElementMatrix specific routines {{{*/
+		void AddToGlobal(Matrix* Kff, Matrix* Kfs);
+		void AddToGlobal(Matrix* Jff);
+		void Echo(void);
+		void CheckConsistency(void);
+		void Transpose(void);
+		void Init(ElementMatrix* Ke);
+		void SetDiag(IssmDouble scalar);
+		/*}}}*/
+};
+#endif //#ifndef _ELEMENT_MATRIX_H_
Index: /issm/trunk-jpl/src/c/classes/matrix/ElementVector.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/ElementVector.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/ElementVector.cpp	(revision 12821)
@@ -0,0 +1,276 @@
+/*!\file ElementVector.cpp
+ * \brief: implementation of the ElementVector object, used to plug values from element into global load
+ */
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../Container/Container.h"
+#include "../../include/include.h"
+/*}}}*/
+
+/*ElementVector constructors and destructor*/
+/*FUNCTION ElementVector::ElementVector(){{{*/
+ElementVector::ElementVector(){
+
+	this->nrows=0;
+	this->values=NULL;
+	this->fsize=0;
+	this->flocaldoflist=NULL;
+	this->fglobaldoflist=NULL;
+
+}
+/*}}}*/
+/*FUNCTION ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2){{{*/
+ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2){
+
+	/*intermediaries*/
+	int i,j,counter;
+	int gsize,fsize,ssize;
+	int* P=NULL;
+	bool found;
+
+	/*If one of the two matrix is NULL, we copy the other one*/
+	if(!pe1 && !pe2){
+		_error2_("Two input element matrices are NULL");
+	}
+	else if(!pe1){
+		this->Init(pe2);
+		return;
+	}
+	else if(!pe2){
+		this->Init(pe1);
+		return;
+	}
+
+	/*Initialize itransformation matrix pe[P[i]] = pe2[i]*/
+	P=xNew<int>(pe2->nrows);
+
+	/*1: Get the new numbering of pe2 and get size of the new matrix*/
+	gsize=pe1->nrows;
+	for(i=0;i<pe2->nrows;i++){
+		found=false;
+		for(j=0;j<pe1->nrows;j++){
+			if(pe2->gglobaldoflist[i]==pe1->gglobaldoflist[j]){
+				found=true; P[i]=j; break;
+			}
+		}
+		if(!found){
+			P[i]=gsize; gsize++;
+		}
+	}
+
+	/*2: Initialize static fields*/
+	this->nrows=gsize;
+
+	/*Gset and values*/
+	this->gglobaldoflist=xNew<int>(this->nrows);
+	this->values=xNewZeroInit<IssmDouble>(this->nrows);
+	for(i=0;i<pe1->nrows;i++){
+		this->values[i] += pe1->values[i];
+		this->gglobaldoflist[i]=pe1->gglobaldoflist[i];
+	}
+	for(i=0;i<pe2->nrows;i++){
+		this->values[P[i]] += pe2->values[i];
+		this->gglobaldoflist[P[i]]=pe2->gglobaldoflist[i];
+	}
+
+	/*Fset*/
+	fsize=pe1->fsize;
+	for(i=0;i<pe2->fsize;i++){
+		if(P[pe2->flocaldoflist[i]] >= pe1->nrows) fsize++;
+	}
+	this->fsize=fsize;
+	if(fsize){
+		this->flocaldoflist =xNew<int>(fsize);
+		this->fglobaldoflist=xNew<int>(fsize);
+		for(i=0;i<pe1->fsize;i++){
+			this->flocaldoflist[i] =pe1->flocaldoflist[i];
+			this->fglobaldoflist[i]=pe1->fglobaldoflist[i];
+		}
+		counter=pe1->fsize;
+		for(i=0;i<pe2->fsize;i++){
+			if(P[pe2->flocaldoflist[i]] >= pe1->nrows){
+				this->flocaldoflist[counter] =P[pe2->flocaldoflist[i]];
+				this->fglobaldoflist[counter]=pe2->fglobaldoflist[i];
+				counter++;
+			}
+		}
+	}
+	else{
+		this->flocaldoflist=NULL;
+		this->fglobaldoflist=NULL;
+	}
+
+	/*clean-up*/
+	xDelete<int>(P);
+}
+/*}}}*/
+/*FUNCTION ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2,ElementVector* pe3){{{*/
+ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2,ElementVector* pe3){
+
+	/*Concatenate all matrices*/
+	ElementVector* pe12 =new ElementVector(pe1,pe2);
+	ElementVector* pe123=new ElementVector(pe12,pe3);
+
+	/*Initialize current object with this matrix*/
+	this->Init(pe123);
+
+	/*clean-up*/
+	delete pe12;
+	delete pe123;
+}
+/*}}}*/
+/*FUNCTION ElementVector::ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation){{{*/
+ElementVector::ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation){
+
+	/*get Vector size and properties*/
+	this->nrows=GetNumberOfDofs(nodes,numnodes,GsetEnum,approximation);
+
+	/*fill values with 0: */
+	this->values=xNewZeroInit<IssmDouble>(this->nrows);
+	
+	/*g list*/
+	this->gglobaldoflist=GetGlobalDofList(nodes,numnodes,GsetEnum,approximation);
+
+	/*Get fsize*/
+	this->fsize=GetNumberOfDofs(nodes,numnodes,FsetEnum,approximation);
+	this->flocaldoflist =GetLocalDofList( nodes,numnodes,FsetEnum,approximation);
+	this->fglobaldoflist=GetGlobalDofList(nodes,numnodes,FsetEnum,approximation);
+}
+/*}}}*/
+/*FUNCTION ElementVector::~ElementVector(){{{*/
+ElementVector::~ElementVector(){
+	
+	xDelete<IssmDouble>(this->values);
+	xDelete<int>(this->gglobaldoflist);
+	xDelete<int>(this->flocaldoflist);
+	xDelete<int>(this->fglobaldoflist);
+}
+/*}}}*/
+
+/*ElementVector specific routines: */
+/*FUNCTION ElementVector::AddToGlobal(Vector* pf){{{*/
+void ElementVector::AddToGlobal(Vector* pf){
+
+	int i;
+	IssmDouble* localvalues=NULL;
+
+	/*In debugging mode, check consistency (no NaN, and values not too big)*/
+	this->CheckConsistency();
+
+	if(this->fsize){
+		/*first, retrieve values that are in the f-set from the g-set values vector: */
+		localvalues=xNew<IssmDouble>(this->fsize);
+		for(i=0;i<this->fsize;i++){
+			localvalues[i]=this->values[this->flocaldoflist[i]];
+		}
+		/*add local values into global  vector, using the fglobaldoflist: */
+		pf->SetValues(this->fsize,this->fglobaldoflist,localvalues,ADD_VAL);
+
+		/*Free ressources:*/
+		xDelete<IssmDouble>(localvalues);
+	}
+	
+}
+/*}}}*/
+/*FUNCTION ElementVector::InsertIntoGlobal(Vector* pf){{{*/
+void ElementVector::InsertIntoGlobal(Vector* pf){
+
+	int i;
+	IssmDouble* localvalues=NULL;
+
+	if(this->fsize){
+		/*first, retrieve values that are in the f-set from the g-set values vector: */
+		localvalues=xNew<IssmDouble>(this->fsize);
+		for(i=0;i<this->fsize;i++){
+			localvalues[i]=this->values[this->flocaldoflist[i]];
+		}
+		/*add local values into global  vector, using the fglobaldoflist: */
+		pf->SetValues(this->fsize,this->fglobaldoflist,localvalues,INS_VAL);
+
+		/*Free ressources:*/
+		xDelete<IssmDouble>(localvalues);
+	}
+
+}
+/*}}}*/
+/*FUNCTION ElementVector::CheckConsistency{{{*/
+void ElementVector::CheckConsistency(void){
+	/*Check element matrix values, only in debugging mode*/
+#ifdef _ISSM_DEBUG_ 
+	for (int i=0;i<this->nrows;i++){
+		if (xIsNan<IssmDouble>(this->values[i])) _error2_("NaN found in Element Vector");
+		if (fabs( this->values[i])>1.e+50) _error2_("Element Vector values exceeds 1.e+50");
+	}
+#endif
+}
+/*}}}*/
+/*FUNCTION ElementVector::Echo{{{*/
+void ElementVector::Echo(void){
+
+	int i,j;
+	_printLine_("Element Vector echo:");
+	_printLine_("   nrows: " << nrows);
+	_printLine_("   values:");
+	for(i=0;i<nrows;i++){
+		_printLine_(setw(4) << right << i << ": " << setw(10) << values[i]);
+	}
+
+	_printString_("   gglobaldoflist (" << gglobaldoflist << "): ");
+	if(gglobaldoflist) for(i=0;i<nrows;i++) _printString_(" " << gglobaldoflist[i] );
+	_printLine_(" ");
+
+	_printLine_("   fsize: " << fsize);
+	_printString_("   flocaldoflist  (" << flocaldoflist << "): ");
+	if(flocaldoflist) for(i=0;i<fsize;i++) _printString_(" " << flocaldoflist[i] );
+	_printLine_(" ");
+	_printString_("   fglobaldoflist (" << fglobaldoflist << "): ");
+	if(fglobaldoflist) for(i=0;i<fsize;i++) _printString_(" " << fglobaldoflist[i] );
+	_printLine_(" ");
+}
+/*}}}*/
+/*FUNCTION ElementVector::Init{{{*/
+void ElementVector::Init(ElementVector* pe){
+
+	_assert_(pe);
+
+	this->nrows =pe->nrows;
+
+	this->values=xNew<IssmDouble>(this->nrows);
+	xMemCpy<IssmDouble>(this->values,pe->values,this->nrows);
+
+	this->gglobaldoflist=xNew<int>(this->nrows);
+	xMemCpy<int>(this->gglobaldoflist,pe->gglobaldoflist,this->nrows);
+
+	this->fsize=pe->fsize;
+	if(this->fsize){
+		this->flocaldoflist=xNew<int>(this->fsize);
+		xMemCpy<int>(this->flocaldoflist,pe->flocaldoflist,this->fsize);
+		this->fglobaldoflist=xNew<int>(this->fsize);
+		xMemCpy<int>(this->fglobaldoflist,pe->fglobaldoflist,this->fsize);
+	}
+	else{
+		this->flocaldoflist=NULL;
+		this->fglobaldoflist=NULL;
+	}
+}
+/*}}}*/
+/*FUNCTION ElementVector::SetValue{{{*/
+void ElementVector::SetValue(IssmDouble scalar){
+
+	int i;
+
+	for(i=0;i<this->nrows;i++)this->values[i]=scalar;
+
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/matrix/ElementVector.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/ElementVector.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/ElementVector.h	(revision 12821)
@@ -0,0 +1,51 @@
+/*!\file:  ElementVector.h
+ * \brief container for information needed to plug element vector generated by elements 
+ * into the pf global load vector. 
+ * This object will hold the element vector on the g-set, the local as well as global 
+ * dof lists in the f set
+ */ 
+
+#ifndef _ELEMENT_VECTOR_H_
+#define _ELEMENT_VECTOR_H_
+
+/*Headers:*/
+/*{{{*/
+#include "../Object.h"
+#include "../../toolkits/toolkits.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+class Node;
+/*}}}*/
+
+class ElementVector{
+
+	public:
+	
+		int      nrows;
+		IssmDouble*  values;
+		
+		//gset
+		int*     gglobaldoflist;
+
+		//fset
+		int      fsize;
+		int*     flocaldoflist;
+		int*     fglobaldoflist;
+		
+		/*ElementVector constructors, destructors {{{*/
+		ElementVector();
+		ElementVector(ElementVector* pe1,ElementVector* pe2);
+		ElementVector(ElementVector* pe1,ElementVector* pe2,ElementVector* pe3);
+		ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation=NoneApproximationEnum);
+		~ElementVector();
+		/*}}}*/
+		/*ElementVector specific routines {{{*/
+		void AddToGlobal(Vector* pf);
+		void InsertIntoGlobal(Vector* pf);
+		void Echo(void);
+		void CheckConsistency(void);
+		void Init(ElementVector* pe);
+		void SetValue(IssmDouble scalar);
+		/*}}}*/
+};
+#endif //#ifndef _ELEMENT_VECTOR_H_
+
Index: /issm/trunk-jpl/src/c/classes/matrix/Matrix.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/Matrix.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/Matrix.cpp	(revision 12821)
@@ -0,0 +1,253 @@
+/*!\file Matrix.cpp
+ * \brief: implementation of the Matrix object
+ */
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../Container/Container.h"
+#include "../../include/include.h"
+#include "../../toolkits/toolkits.h"
+#include "./Matrix.h"
+	
+/*}}}*/
+
+/*Matrix constructors and destructor*/
+/*FUNCTION Matrix::Matrix(){{{*/
+Matrix::Matrix(){
+
+	#ifdef _HAVE_PETSC_
+	this->matrix=NULL;
+	#else
+	this->matrix=NULL;
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->amatrix=NULL;
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Matrix(int M,int N){{{*/
+Matrix::Matrix(int M,int N){
+
+	#ifdef _HAVE_PETSC_
+	this->matrix=NewMat(M,N);
+	#else
+	this->matrix=new SeqMat(M,N);
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->amatrix=xNew<IssmDouble>(M*N);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Matrix(int M,int N,IssmDouble sparsity){{{*/
+Matrix::Matrix(int M,int N,IssmDouble sparsity){
+
+	#ifdef _HAVE_PETSC_
+	this->matrix=NewMat(M,N,sparsity);
+	#else
+	this->matrix=new SeqMat(M,N,sparsity);
+	#endif
+	#ifdef _HAVE_ADOLC_
+ 	this->amatrix=xNew<IssmDouble>(M*N);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Matrix(IssmDouble* serial_mat, int M,int N,IssmDouble sparsity){{{*/
+Matrix::Matrix(IssmDouble* serial_mat, int M,int N,IssmDouble sparsity){
+
+	#ifdef _HAVE_PETSC_
+	int     i;
+
+
+	int* idxm=xNew<int>(M);
+	int* idxn=xNew<int>(N);
+	for(i=0;i<M;i++)idxm[i]=i;
+	for(i=0;i<N;i++)idxn[i]=i;
+
+	this->matrix=NewMat(M,N,sparsity);
+	MatSetValues(this->matrix,M,idxm,N,idxn,serial_mat,INSERT_VALUES);
+	MatAssemblyBegin(this->matrix,MAT_FINAL_ASSEMBLY);
+	MatAssemblyEnd(this->matrix,MAT_FINAL_ASSEMBLY);
+
+	xDelete<int>(idxm);
+	xDelete<int>(idxn);
+	#else
+	this->matrix=new SeqMat(serial_mat,M,N,sparsity);
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->amatrix=xNew<IssmDouble>(M*N);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Matrix(int M,int N,int connectivity,int numberofdofspernode){{{*/
+Matrix::Matrix(int M,int N,int connectivity,int numberofdofspernode){
+	
+	#ifdef _HAVE_PETSC_
+	this->matrix=NewMat(M,N,connectivity,numberofdofspernode);
+	#else
+	this->matrix=new SeqMat(M,N,connectivity,numberofdofspernode);
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->amatrix=xNew<IssmDouble>(M*N);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::~Matrix(){{{*/
+Matrix::~Matrix(){
+
+ 	#ifdef _HAVE_PETSC_
+	MatFree(&this->matrix);
+	#else
+	delete this->matrix;
+	#endif
+	#ifdef _HAVE_ADOLC_
+	xDelete<IssmDouble>(this->amatrix);
+	#endif
+}
+/*}}}*/
+
+/*Matrix specific routines: */
+/*FUNCTION Matrix::Echo{{{*/
+void Matrix::Echo(void){
+
+	int i,j;
+
+	#ifdef _HAVE_PETSC_
+	MatView(this->matrix,PETSC_VIEWER_STDOUT_WORLD);
+	#else
+	this->matrix->Echo();
+	#endif
+
+	#ifdef _HAVE_ADOLC_
+	/*Not sure about that one. Should we use the overloaded operator >>?*/
+	_printString_("ADOLC Matrix equivalent:" );
+//	for(i=0;i<M;i++){
+//		for(j=0;j<N;j++){
+//			_printString_(*(amatrix+N*i+j) << " ");
+//		}
+//		_printLine_("");
+//	}
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Assemble{{{*/
+void Matrix::Assemble(void){
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		MatAssemblyBegin(this->matrix,MAT_FINAL_ASSEMBLY);
+		MatAssemblyEnd(this->matrix,MAT_FINAL_ASSEMBLY);
+		#if _PETSC_MAJOR_ == 2 
+			MatCompress(this->matrix);
+		#endif
+	#else
+		this->matrix->Assemble();
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Matrix::Norm{{{*/
+IssmDouble Matrix::Norm(NormMode norm_type){
+	
+	IssmDouble norm=0;
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		MatNorm(this->matrix,ISSMToPetscNormMode(norm_type),&norm);
+	#else
+		norm=this->matrix->Norm(norm_type);
+	#endif
+	return norm;
+}
+/*}}}*/
+/*FUNCTION Matrix::GetSize{{{*/
+void Matrix::GetSize(int* pM,int* pN){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		MatGetSize(this->matrix,pM,pN);
+	#else
+		this->matrix->GetSize(pM,pN);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::GetLocalSize{{{*/
+void Matrix::GetLocalSize(int* pM,int* pN){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		MatGetLocalSize(this->matrix,pM,pN);
+	#else
+		this->matrix->GetLocalSize(pM,pN);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::MatMult{{{*/
+void Matrix::MatMult(Vector* X,Vector* AX){
+
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		_assert_(X->vector);
+		MatMultPatch(this->matrix,X->vector,AX->vector);
+	#else
+		this->matrix->MatMult(X->vector,AX->vector);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Duplicate{{{*/
+Matrix* Matrix::Duplicate(void){
+
+	Matrix* output=NULL;
+
+	output=new Matrix();
+
+	#ifdef _HAVE_PETSC_
+		_assert_(this->matrix);
+		MatDuplicate(this->matrix,MAT_COPY_VALUES,&output->matrix);
+	#else
+		output->matrix=this->matrix->Duplicate();
+	#endif
+	
+	return output;
+}
+/*}}}*/
+/*FUNCTION Matrix::ToSerial{{{*/
+IssmDouble* Matrix::ToSerial(void){
+
+	IssmDouble* output=NULL;
+
+	#ifdef _HAVE_PETSC_
+		MatToSerial(&output,this->matrix);
+	#else
+		output=this->matrix->ToSerial();
+	#endif
+	return output;
+}
+/*}}}*/
+/*FUNCTION Matrix::SetValues{{{*/
+void Matrix::SetValues(int m,int* idxm,int n,int* idxn,IssmDouble* values,InsMode mode){
+
+	#ifdef _HAVE_PETSC_
+		MatSetValues(this->matrix,m,idxm,n,idxn,values,ISSMToPetscInsertMode(mode));
+	#else
+		this->matrix->SetValues(m,idxm,n,idxn,values,mode);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Matrix::Convert{{{*/
+void Matrix::Convert(MatrixType type){
+
+	#ifdef _HAVE_PETSC_
+		MatConvert(this->matrix,ISSMToPetscMatrixType(type),MAT_REUSE_MATRIX,&this->matrix);
+	#else
+		this->matrix->Convert(type);
+	#endif
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/matrix/Matrix.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/Matrix.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/Matrix.h	(revision 12821)
@@ -0,0 +1,59 @@
+/*!\file:  Matrix.h
+ * \brief wrapper to matrix objects. The goal is to control which API (PETSc,Scalpack, Plapack?) 
+ * implements our underlying matrix format.
+ */ 
+
+#ifndef _MATRIX_H_
+#define _MATRIX_H_
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+#include "../../toolkits/toolkits.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+
+class Vector;
+
+/*}}}*/
+
+class Matrix{
+
+	public:
+	
+		#ifdef _HAVE_PETSC_
+		Mat matrix; 
+		#else
+		SeqMat* matrix; 
+		#endif
+		#ifdef _HAVE_ADOLC_
+		IssmDouble* amatrix;
+		#endif
+
+		/*Matrix constructors, destructors {{{*/
+		Matrix();
+		Matrix(int M,int N);
+		Matrix(int M,int N,IssmDouble sparsity);
+		Matrix(IssmDouble* serial_mat,int M,int N,IssmDouble sparsity);
+		Matrix(int M,int N,int connectivity,int numberofdofspernode);
+		~Matrix();
+		/*}}}*/
+		/*Matrix specific routines {{{*/
+		void Echo(void);
+		void Assemble(void);
+		IssmDouble Norm(NormMode norm_type);
+		void GetSize(int* pM,int* pN);
+		void GetLocalSize(int* pM,int* pN);
+		void MatMult(Vector* X,Vector* AX);
+		Matrix* Duplicate(void);
+		IssmDouble* ToSerial(void);
+		void SetValues(int m,int* idxm,int n,int* idxn,IssmDouble* values,InsMode mode);
+		void Convert(MatrixType type);
+		/*}}}*/
+
+};
+
+#endif //#ifndef _MATRIX_H_
Index: /issm/trunk-jpl/src/c/classes/matrix/Vector.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/Vector.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/Vector.cpp	(revision 12821)
@@ -0,0 +1,347 @@
+/*!\file Vector.cpp
+ * \brief: implementation of the Vector object
+ */
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../Container/Container.h"
+#include "../../include/include.h"
+#include "../../toolkits/toolkits.h"
+#include "./Vector.h"
+/*}}}*/
+
+/*Vector constructors and destructor*/
+/*FUNCTION Vector::Vector(){{{*/
+Vector::Vector(){
+
+	#ifdef _HAVE_PETSC_
+	this->vector=NULL;
+	#else
+	this->vector=NULL;
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->avector=NULL;
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::Vector(int M,bool fromlocalsize){{{*/
+Vector::Vector(int pM,bool fromlocalsize){
+
+	#ifdef _HAVE_PETSC_
+	this->vector=NewVec(pM,fromlocalsize);
+	#else
+	this->vector=new SeqVec(pM,fromlocalsize);
+	#endif
+	#ifdef _HAVE_ADOLC_
+	this->avector=xNew<IssmDouble>(pM);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::Vector(IssmDouble* serial_vec,int M){{{*/
+Vector::Vector(IssmDouble* serial_vec,int M){
+
+	#ifdef _HAVE_PETSC_
+		int* idxm=xNew<int>(M);
+		for(int i=0;i<M;i++) idxm[i]=i;
+
+		this->vector=NewVec(M);
+		VecSetValues(this->vector,M,idxm,serial_vec,INSERT_VALUES);
+		VecAssemblyBegin(this->vector);
+		VecAssemblyEnd(this->vector);
+
+		xDelete<int>(idxm);
+	#else
+		this->vector=new SeqVec(serial_vec,M);
+	#endif
+	#ifdef _HAVE_ADOLC_
+		this->avector=xNew<IssmDouble>(M);
+	#endif
+}
+/*}}}*/
+#ifdef _HAVE_PETSC_
+/*FUNCTION Vector::Vector(Vec petsc_vec){{{*/
+Vector::Vector(Vec petsc_vec){
+
+	if(petsc_vec==NULL){
+		this->vector=NewVec(0);
+	}
+	else{
+		/*copy vector*/
+		VecDuplicate(petsc_vec,&this->vector);
+		VecCopy(petsc_vec,this->vector);
+	}
+
+}
+/*}}}*/
+#endif
+#if defined(_HAVE_GSL_) && !defined(_HAVE_PETSC_)
+/*FUNCTION Vector::Vector(SeqVec* seq_vec){{{*/
+Vector::Vector(SeqVec*  seq_vec){
+
+	if(seq_vec==NULL){
+		this->vector=NULL;
+	}
+	else{
+		/*copy vector*/
+		this->vector=seq_vec->Duplicate();
+	}
+}
+/*}}}*/
+#endif
+
+		/*FUNCTION Vector::~Vector(){{{*/
+Vector::~Vector(){
+
+ 	#ifdef _HAVE_PETSC_
+	VecFree(&this->vector);
+	#else
+	delete this->vector;
+	#endif
+	#ifdef _HAVE_ADOLC_
+	xDelete<IssmDouble>(this->avector);
+	#endif
+}
+/*}}}*/
+
+/*Vector specific routines: */
+/*FUNCTION Vector::Echo{{{*/
+void Vector::Echo(void){
+
+	int i;
+
+	#ifdef _HAVE_PETSC_
+	_assert_(this->vector);
+	VecView(this->vector,PETSC_VIEWER_STDOUT_WORLD);
+	#else
+	this->vector->Echo();
+	#endif
+
+	#ifdef _HAVE_ADOLC_
+	/*do nothing for now: */
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::Assemble{{{*/
+void Vector::Assemble(void){
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecAssemblyBegin(this->vector); 
+		VecAssemblyEnd(this->vector);
+	#else
+		this->vector->Assemble();
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::SetValues{{{*/
+void Vector::SetValues(int ssize, int* list, IssmDouble* values, InsMode mode){
+		
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecSetValues(this->vector,ssize,list,values,ISSMToPetscInsertMode(mode));
+	#else
+		this->vector->SetValues(ssize,list,values,mode);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::SetValue{{{*/
+void Vector::SetValue(int dof, IssmDouble value, InsMode mode){
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecSetValues(this->vector,1,&dof,&value,ISSMToPetscInsertMode(mode));
+	#else
+		this->vector->SetValue(dof,value,mode);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::GetValue{{{*/
+void Vector::GetValue(IssmDouble* pvalue,int dof){
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecGetValues(this->vector,1,&dof,pvalue);
+	#else
+	this->vector->GetValue(pvalue,dof);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::GetSize{{{*/
+void Vector::GetSize(int* pM){
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecGetSize(this->vector,pM);
+	#else
+		this->vector->GetSize(pM);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::IsEmpty{{{*/
+bool Vector::IsEmpty(void){
+
+	int M;
+
+	_assert_(this->vector);
+	this->GetSize(&M);
+
+	if(M==0) 
+	 return true;
+	else
+	 return false;
+}
+/*}}}*/
+/*FUNCTION Vector::GetLocalSize{{{*/
+void Vector::GetLocalSize(int* pM){
+		
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecGetLocalSize(this->vector,pM);
+	#else
+		this->vector->GetLocalSize(pM);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::Duplicate{{{*/
+Vector* Vector::Duplicate(void){
+	
+	Vector* output=NULL;
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		Vec vec_output=NULL;
+		VecDuplicate(this->vector,&vec_output);
+		output=new Vector(vec_output);
+		VecFree(&vec_output);
+	#else
+		output=new Vector();
+		output->vector=this->vector->Duplicate();
+	#endif
+	return output;
+
+}
+/*}}}*/
+/*FUNCTION Vector::Set{{{*/
+void Vector::Set(IssmDouble value){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecSet(this->vector,value);
+	#else
+		this->vector->Set(value);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::AXPY{{{*/
+void Vector::AXPY(Vector* X, IssmDouble a){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecAXPY(this->vector,a,X->vector);
+	#else
+		this->vector->AXPY(X->vector,a);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::AYPX{{{*/
+void Vector::AYPX(Vector* X, IssmDouble a){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecAYPX(this->vector,a,X->vector);
+	#else
+		this->vector->AYPX(X->vector,a);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::ToMPISerial{{{*/
+IssmDouble* Vector::ToMPISerial(void){
+
+	IssmDouble* vec_serial=NULL;
+
+	#ifdef _HAVE_PETSC_
+		VecToMPISerial(&vec_serial, this->vector);
+	#else
+		vec_serial=this->vector->ToMPISerial();
+	#endif
+
+	return vec_serial;
+
+}
+/*}}}*/
+/*FUNCTION Vector::Copy{{{*/
+void Vector::Copy(Vector* to){
+
+	#ifdef _HAVE_PETSC_
+		if(this->vector) VecCopy(this->vector,to->vector);
+	#else
+		this->vector->Copy(to->vector);
+	#endif
+
+}
+/*}}}*/
+/*FUNCTION Vector::Norm{{{*/
+IssmDouble Vector::Norm(NormMode norm_type){
+	
+	IssmDouble norm=0;
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecNorm(this->vector,ISSMToPetscNormMode(norm_type),&norm);
+	#else
+		norm=this->vector->Norm(norm_type);
+	#endif
+	return norm;
+}
+/*}}}*/
+/*FUNCTION Vector::Scale{{{*/
+void Vector::Scale(IssmDouble scale_factor){
+	
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecScale(this->vector,scale_factor); 
+	#else
+		this->vector->Scale(scale_factor);
+	#endif
+}
+/*}}}*/
+/*FUNCTION Vector::Dot{{{*/
+IssmDouble Vector::Dot(Vector* vector){
+
+	IssmDouble dot;
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecDot(this->vector,vector->vector,&dot);
+	#else
+		dot=this->vector->Dot(vector->vector);
+	#endif
+	return dot;
+}
+/*}}}*/
+/*FUNCTION Vector::PointwiseDivide{{{*/
+void Vector::PointwiseDivide(Vector* x,Vector* y){
+
+	#ifdef _HAVE_PETSC_
+		_assert_(this->vector);
+		VecPointwiseDivide(this->vector,x->vector,y->vector);
+	#else
+		this->vector->PointwiseDivide(x->vector,y->vector);
+	#endif
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/matrix/Vector.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/matrix/Vector.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/matrix/Vector.h	(revision 12821)
@@ -0,0 +1,69 @@
+/*!\file:  Vector.h
+ * \brief wrapper to vector objects. The goal is to control which API (PETSc,Scalpack, Plapack?) 
+ * implements our underlying vector format.
+ */ 
+
+#ifndef _VECTOR_H_
+#define _VECTOR_H_
+
+/*Headers:*/
+/*{{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+#include "../../toolkits/toolkits.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+
+/*}}}*/
+
+class Vector{
+
+	public:
+	
+		#ifdef _HAVE_PETSC_
+			Vec vector; 
+		#else
+			SeqVec* vector;
+		#endif
+		#ifdef _HAVE_ADOLC_
+			IssmDouble* avector;
+		#endif
+
+		/*Vector constructors, destructors {{{*/
+		Vector();
+		Vector(int M,bool fromlocalsize=false);
+		Vector(IssmDouble* serial_vec,int pM);
+		#ifdef _HAVE_PETSC_
+		Vector(Vec petsc_vec);
+		#endif
+		#if defined(_HAVE_GSL_) && !defined(_HAVE_PETSC_)
+		Vector(SeqVec*  seq_vec);
+		#endif
+		~Vector();
+		/*}}}*/
+		/*Vector specific routines {{{*/
+		void Echo(void);
+		void    AXPY(Vector *X, IssmDouble a);
+		void    AYPX(Vector *X, IssmDouble a);
+		void    Assemble(void);
+		void    Copy(Vector *to);
+		IssmDouble  Dot(Vector *vector);
+		Vector *Duplicate(void);
+		void    GetValue(IssmDouble *pvalue, int dof);
+		void    GetSize(int *pM);
+		void    GetLocalSize(int *pM);
+		bool    IsEmpty(void);
+		IssmDouble  Norm(NormMode norm_type);
+		void    PointwiseDivide(Vector  *x,Vector*y);
+		void    Scale(IssmDouble scale_factor);
+		void    Set(IssmDouble value);
+		void    SetValues(int ssize, int *list, IssmDouble*values, InsMode mode);
+		void    SetValue(int dof, IssmDouble value, InsMode mode);
+		IssmDouble *ToMPISerial(void);
+		/*}}}*/
+};
+
+
+#endif //#ifndef _VECTOR_H_
Index: /issm/trunk-jpl/src/c/classes/objects.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects.h	(revision 12821)
@@ -0,0 +1,185 @@
+/* \file objects.h
+ * \brief: prototype header for all objects.
+ */
+
+#ifndef ALL_OBJECTS_H_
+#define ALL_OBJECTS_H_
+
+/*Abstract classes: */
+#include "./Object.h"
+
+/*Objects: */
+#include "./Hook.h"
+#include "./DofIndexing.h"
+#include "./Vertex.h"
+#include "./Node.h"
+#include "./Segment.h"
+#include "./IoModel.h"
+#include "./Patch.h"
+#include "./Update.h"
+
+/*Constraints: */
+#include "./Constraints/Constraint.h"
+#include "./Constraints/SpcStatic.h"
+#include "./Constraints/SpcTransient.h"
+#include "./Constraints/SpcDynamic.h"
+
+/*Gauss*/
+#include "./Gauss/GaussTria.h"
+#include "./Gauss/GaussPenta.h"
+
+/*Loads: */
+#include "./Loads/Load.h"
+#include "./Loads/Friction.h"
+#include "./Loads/Icefront.h"
+#include "./Loads/Numericalflux.h"
+#include "./Loads/Riftfront.h"
+#include "./Loads/Penpair.h"
+#include "./Loads/Pengrid.h"
+
+/*Elements: */
+#include "./Elements/Element.h"
+#include "./Elements/Penta.h"
+#include "./Elements/PentaHook.h"
+#include "./Elements/PentaRef.h"
+#include "./Elements/Tria.h"
+#include "./Elements/TriaHook.h"
+#include "./Elements/TriaRef.h"
+
+/*KML parsing objects: */
+#include "./KML/KML_Attribute.h"
+#include "./KML/KML_Comment.h"
+#include "./KML/KML_ColorStyle.h"
+#include "./KML/KML_Container.h"
+#include "./KML/KML_Document.h"
+#include "./KML/KML_Feature.h"
+#include "./KML/KML_File.h"
+#include "./KML/KML_Folder.h"
+#include "./KML/KML_Geometry.h"
+#include "./KML/KML_GroundOverlay.h"
+#include "./KML/KML_Icon.h"
+#include "./KML/KML_LatLonBox.h"
+#include "./KML/KML_LinearRing.h"
+#include "./KML/KML_LineString.h"
+#include "./KML/KML_LineStyle.h"
+#include "./KML/KML_MultiGeometry.h"
+#include "./KML/KML_Object.h"
+#include "./KML/KML_Overlay.h"
+#include "./KML/KML_Point.h"
+#include "./KML/KML_Placemark.h"
+#include "./KML/KML_Polygon.h"
+#include "./KML/KML_PolyStyle.h"
+#include "./KML/KML_Style.h"
+#include "./KML/KML_StyleSelector.h"
+#include "./KML/KML_SubStyle.h"
+#include "./KML/KML_Unknown.h"
+#include "./KML/KMLFileReadUtils.h"
+
+/*Option parsing objects: */
+#include "./Options/Option.h"
+#include "./Options/OptionDouble.h"
+#include "./Options/OptionLogical.h"
+#include "./Options/OptionChar.h"
+#include "./Options/OptionStruct.h"
+#include "./Options/OptionCell.h"
+#include "./Options/OptionUtilities.h"
+
+/*Inputs: */
+#include "./Inputs/Input.h"
+#include "./Inputs/BoolInput.h"
+#include "./Inputs/DoubleInput.h"
+#include "./Inputs/IntInput.h"
+#include "./Inputs/PentaP1Input.h"
+#include "./Inputs/TriaP1Input.h"
+#include "./Inputs/ControlInput.h"
+#include "./Inputs/DatasetInput.h"
+#include "./Inputs/TransientInput.h"
+
+/*ElementResults: */
+#include "./ElementResults/ElementResult.h"
+#include "./ElementResults/DoubleElementResult.h"
+#include "./ElementResults/TriaP1ElementResult.h"
+#include "./ElementResults/PentaP1ElementResult.h" 
+#include "./ElementResults/BoolElementResult.h"
+
+/*ExternalResults: */
+#include "./ExternalResults/ExternalResult.h"
+#include "./ExternalResults/BoolExternalResult.h"
+#include "./ExternalResults/DoubleExternalResult.h"
+#include "./ExternalResults/DoubleVecExternalResult.h"
+#include "./ExternalResults/DoubleMatExternalResult.h"
+#include "./ExternalResults/IntExternalResult.h"
+#include "./ExternalResults/PetscVecExternalResult.h"
+#include "./ExternalResults/StringExternalResult.h"
+
+/*Materials: */
+#include "./Materials/Material.h"
+#include "./Materials/Matice.h"
+#include "./Materials/Matpar.h"
+
+/*Numerics:*/
+#include "./Numerics/ElementMatrix.h"
+#include "./Numerics/ElementVector.h"
+#include "./Numerics/Vector.h"
+#include "./Numerics/Matrix.h"
+
+/*Params: */
+#include "./Params/BoolParam.h"
+#include "./Params/DoubleMatParam.h"
+#include "./Params/DoubleTransientMatParam.h"
+#include "./Params/DoubleMatArrayParam.h"
+#include "./Params/DoubleParam.h"
+#include "./Params/DoubleVecParam.h"
+#include "./Params/IntParam.h"
+#include "./Params/IntVecParam.h"
+#include "./Params/IntMatParam.h"
+#include "./Params/FileParam.h"
+#include "./Params/Param.h"
+#include "./Params/MatrixParam.h"
+#include "./Params/VectorParam.h"
+#include "./Params/StringArrayParam.h"
+#include "./Params/StringParam.h"
+#include "./Params/TransientParam.h"
+
+/*C objects: */
+#include "./Contour.h"
+#include "./FemModel.h"
+#include "./OptArgs.h"
+#include "./OptPars.h"
+
+/*Bamg: */
+#include "./Bamg/BamgOpts.h"
+#include "./Bamg/BamgGeom.h"
+#include "./Bamg/BamgMesh.h"
+#include "./Bamg/Metric.h"
+#include "./Bamg/DoubleAndInt.h"
+#include "./Bamg/Direction.h"
+#include "./Bamg/BamgVertex.h"
+#include "./Bamg/AdjacentTriangle.h"
+#include "./Bamg/Edge.h"
+#include "./Bamg/GeomVertex.h"
+#include "./Bamg/GeomEdge.h"
+#include "./Bamg/Curve.h"
+#include "./Bamg/Triangle.h"
+#include "./Bamg/ListofIntersectionTriangles.h"
+#include "./Bamg/GeomSubDomain.h"
+#include "./Bamg/SubDomain.h"
+#include "./Bamg/VertexOnGeom.h"
+#include "./Bamg/VertexOnVertex.h"
+#include "./Bamg/VertexOnEdge.h"
+#include "./Bamg/CrackedEdge.h"
+#include "./Bamg/Mesh.h"
+#include "./Bamg/Geometry.h"
+#include "./Bamg/BamgQuadtree.h"
+#include "./Bamg/SetOfE4.h"
+
+/*Kriging*/
+#include "./Kriging/Variogram.h"
+#include "./Kriging/GaussianVariogram.h"
+#include "./Kriging/ExponentialVariogram.h"
+#include "./Kriging/SphericalVariogram.h"
+#include "./Kriging/PowerVariogram.h"
+#include "./Kriging/Quadtree.h"
+#include "./Kriging/Observation.h"
+
+#endif
Index: /issm/trunk-jpl/src/c/classes/objects/Contour.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Contour.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Contour.cpp	(revision 12821)
@@ -0,0 +1,95 @@
+/*! \file Contour.c
+ *  \sa Contour.h
+ */
+
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <string.h>
+#include "./objects.h"
+#include "../include/include.h"
+#include "../io/io.h"
+
+/*Contour constructors and destructors:*/
+/*FUNCTION Contour::Contour() default constructor {{{*/
+Contour::Contour(){
+	this->id=0;
+	this->nods=0;
+	this->x=NULL;
+	this->y=NULL;
+	this->closed=false;
+}
+/*}}}*/
+/*FUNCTION Contour::Contour(int pid, int nods, IssmDouble* x, IssmDouble* y,bool closed) {{{*/
+Contour::Contour(int pid,int pnods, IssmDouble* px, IssmDouble* py,bool pclosed){
+	
+	this->id=pid;
+	this->nods=pnods;
+	this->closed=pclosed;
+	if(nods){
+		this->x=xNew<IssmDouble>(nods);
+		xMemCpy<IssmDouble>(this->x,px,nods);
+		this->y=xNew<IssmDouble>(nods);
+		xMemCpy<IssmDouble>(this->y,py,nods);
+	}
+}
+/*}}}*/
+/*FUNCTION Contour::Contour() default constructor {{{*/
+Contour::~Contour(){
+	xDelete<IssmDouble>(this->x);
+	xDelete<IssmDouble>(this->y);
+}
+/*}}}*/
+
+
+/*Object virtual function resolutoin: */
+/*FUNCTION Contour::Echo(){{{*/
+void Contour::Echo(void){
+
+	int i;
+
+	_printLine_("Contour: " << id);
+	_printLine_("   nods: " << nods);
+	_printLine_("   closed: " << (closed?"true":"false"));
+	if(nods){
+	        _printLine_("   x,y:");
+		for(i=0;i<nods;i++){
+		        _printLine_(i << ": " << x[i] << "|" << y[i]);
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Contour::DeepEcho(){{{*/
+void Contour::DeepEcho(void){
+	this->Echo();
+}
+/*}}}*/
+/*FUNCTION Contour::Id(){{{*/
+int Contour::Id(void){
+	return id;
+}
+/*}}}*/
+/*FUNCTION Contour::MyRank{{{*/
+int    Contour::MyRank(void){ 
+	extern int my_rank;
+
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Contour::ObjectEnum{{{*/
+int Contour::ObjectEnum(void){
+
+	return ContourEnum;
+
+}
+/*}}}*/
+/*FUNCTION Contour::copy {{{*/
+Object* Contour::copy() {
+
+	return new Contour(*this); 
+
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/objects/Contour.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Contour.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Contour.h	(revision 12821)
@@ -0,0 +1,43 @@
+/*!\file Contour.h
+ * \brief: header file for Contour object
+ */
+
+#ifndef _CONTOUR_H_
+#define _CONTOUR_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+#include "../shared/Exceptions/exceptions.h"
+#include "../toolkits/toolkits.h"
+#include "../include/include.h"
+/*}}}*/
+
+class Contour: public Object{
+
+	public: 
+
+		int     id;
+		int	  nods;  //number of vertices in the contour
+		IssmDouble* x;
+		IssmDouble* y;
+		bool    closed; //is this contour closed?
+
+		/*Contour constructors, destructors {{{*/
+		Contour();
+		Contour(int id, int nods, IssmDouble* x, IssmDouble* y,bool closed);
+		~Contour();
+		/*}}}*/
+		/*Object virtual functions{{{*/
+		void  Echo(void);
+		void  DeepEcho(void);
+		int   Id(void);
+		int   MyRank(void);
+		int   ObjectEnum(void);
+		Object* copy(void);
+		/*}}}*/
+
+
+};
+
+#endif  /* _CONTOUR_H_ */
Index: /issm/trunk-jpl/src/c/classes/objects/Node.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Node.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Node.cpp	(revision 12821)
@@ -0,0 +1,1012 @@
+/*!\file Node.c
+ * \brief: implementation of the Node object
+ */
+
+/*Include files: {{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "./objects.h"
+#include "../Container/Container.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../include/include.h"
+#include "../modules/modules.h"
+/*}}}*/
+
+/*Node constructors and destructors:*/
+/*FUNCTION Node::Node() default constructor {{{*/
+Node::Node(){
+		 this->inputs=NULL;
+		 this->hvertex=NULL;
+		 return;
+}
+/*}}}*/
+/*FUNCTION Node::Node(int node_id,int node_sid,int vertex_id,int io_index, IoModel* iomodel,int analysis_type) {{{*/
+Node::Node(int node_id,int node_sid,int vertex_id,int io_index, IoModel* iomodel,int analysis_type){
+
+	/*Intermediary*/
+	int k,l;
+	int gsize;
+	int dim;
+
+	/*Fetch parameters: */
+	iomodel->Constant(&dim,MeshDimensionEnum);
+
+	/*id: */
+	this->id=node_id; 
+	this->sid=node_sid; 
+	this->analysis_type=analysis_type;
+
+	/*Initialize coord_system: Identity matrix by default*/
+	for(k=0;k<3;k++) for(l=0;l<3;l++) this->coord_system[k][l]=0.0;
+	for(k=0;k<3;k++) this->coord_system[k][k]=1.0;
+
+	/*indexing:*/
+	DistributeNumDofs(&this->indexing,analysis_type,iomodel->Data(FlowequationVertexEquationEnum)+io_index); //number of dofs per node
+	gsize=this->indexing.gsize;
+
+	/*Hooks*/
+	this->hvertex=new Hook(&vertex_id,1); //node id is the same as the vertex id, continuous galerkin!
+
+	//intialize inputs, and add as many inputs per element as requested: 
+	this->inputs=new Inputs();
+	if (iomodel->Data(MeshVertexonbedEnum))
+	 this->inputs->AddInput(new BoolInput(MeshVertexonbedEnum,reCast<IssmBool>(iomodel->Data(MeshVertexonbedEnum)[io_index])));
+	if (iomodel->Data(MeshVertexonsurfaceEnum))
+	 this->inputs->AddInput(new BoolInput(MeshVertexonsurfaceEnum,reCast<IssmBool>(iomodel->Data(MeshVertexonsurfaceEnum)[io_index])));
+	if (iomodel->Data(MaskVertexonfloatingiceEnum))
+	 this->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,reCast<IssmBool>(iomodel->Data(MaskVertexonfloatingiceEnum)[io_index])));
+	if (iomodel->Data(MaskVertexongroundediceEnum))
+	  this->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,reCast<IssmBool>(iomodel->Data(MaskVertexongroundediceEnum)[io_index])));
+	if (analysis_type==DiagnosticHorizAnalysisEnum)
+	 this->inputs->AddInput(new IntInput(ApproximationEnum,reCast<IssmInt>(iomodel->Data(FlowequationVertexEquationEnum)[io_index])));
+	/*set single point constraints: */
+
+	/*spc all nodes on water*/
+	if (!iomodel->Data(MaskVertexonwaterEnum)) _error2_("iomodel->nodeonwater is NULL");
+	if (reCast<IssmBool>(iomodel->Data(MaskVertexonwaterEnum)[io_index])){
+		for(k=1;k<=gsize;k++){
+			this->FreezeDof(k);
+		}
+	}
+
+	/*Diagnostic Horiz*/
+	#ifdef _HAVE_DIAGNOSTIC_
+	if (analysis_type==DiagnosticHorizAnalysisEnum){
+
+		/*Coordinate system provided, convert to coord_system matrix*/
+		_assert_(iomodel->Data(DiagnosticReferentialEnum)); 
+		XZvectorsToCoordinateSystem(&this->coord_system[0][0],iomodel->Data(DiagnosticReferentialEnum)+io_index*6);
+
+		if (dim==3){
+			/*We have a  3d mesh, we may have collapsed elements, hence dead nodes. Freeze them out: */
+			_assert_(iomodel->Data(MeshVertexonbedEnum)); 
+			_assert_(iomodel->Data(FlowequationVertexEquationEnum));
+			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealApproximationEnum && !iomodel->Data(MeshVertexonbedEnum)[io_index]){
+				for(k=1;k<=gsize;k++) this->FreezeDof(k);
+			}
+			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealPattynApproximationEnum && iomodel->Data(FlowequationBordermacayealEnum)[io_index]){
+				if(!iomodel->Data(MeshVertexonbedEnum)[io_index]){
+					for(k=1;k<=gsize;k++) this->FreezeDof(k);
+				}
+			}
+			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealStokesApproximationEnum && iomodel->Data(FlowequationBordermacayealEnum)[io_index]){
+				if(!iomodel->Data(MeshVertexonbedEnum)[io_index]){
+					for(k=1;k<=2;k++) this->FreezeDof(k);
+				}
+			}
+		}
+		/*spc all nodes on hutter*/
+		if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==HutterApproximationEnum){
+			for(k=1;k<=gsize;k++){
+				this->FreezeDof(k);
+			}
+		}
+	}
+	#endif
+
+	/*Diagnostic Hutter*/
+	if (analysis_type==DiagnosticHutterAnalysisEnum){
+		if (!iomodel->Data(FlowequationVertexEquationEnum)) _error2_("iomodel->vertices_type is NULL");
+		/*Constrain all nodes that are not Hutter*/
+		if (reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[io_index])!=HutterApproximationEnum){
+			for(k=1;k<=gsize;k++){
+				this->FreezeDof(k);
+			}
+		}
+	}
+
+	/*Prognostic/ Melting/ Slopecompute/ Balancethickness*/
+	if (
+				analysis_type==PrognosticAnalysisEnum || 
+				analysis_type==MeltingAnalysisEnum || 
+				analysis_type==BedSlopeAnalysisEnum || 
+				analysis_type==SurfaceSlopeAnalysisEnum || 
+				analysis_type==BalancethicknessAnalysisEnum
+				){
+		if (dim==3){
+			/*On a 3d mesh, we may have collapsed elements, hence dead nodes. Freeze them out: */
+			_assert_(iomodel->Data(MeshVertexonbedEnum));
+			if (!(reCast<IssmBool>(iomodel->Data(MeshVertexonbedEnum)[io_index]))){
+				for(k=1;k<=gsize;k++){
+					this->FreezeDof(k);
+				}
+			}
+		}
+	}
+
+}
+/*}}}*/
+/*FUNCTION Node::~Node(){{{*/
+Node::~Node(){
+	delete inputs;
+	delete hvertex;
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION Node::Echo{{{*/
+void Node::Echo(void){
+
+	_printLine_("Node:");
+	_printLine_("   id: " << id);
+	_printLine_("   sid: " << sid);
+	_printLine_("   analysis_type: " << EnumToStringx(analysis_type));
+	indexing.Echo();
+	_printLine_("   hvertex:     not displayed");
+	_printLine_("   inputs:      " << inputs);
+
+
+}
+/*}}}*/
+/*FUNCTION Node::DeepEcho{{{*/
+void Node::DeepEcho(void){
+
+	_printLine_("Node:");
+	_printLine_("   id: " << id);
+	_printLine_("   sid: " << sid);
+	_printLine_("   analysis_type: " << EnumToStringx(analysis_type));
+	indexing.DeepEcho();
+	_printLine_("Vertex:");
+	hvertex->DeepEcho();
+	_printLine_("   inputs");
+
+
+}
+/*}}}*/
+/*FUNCTION Node::Id{{{*/
+int    Node::Id(void){ return id; }
+/*}}}*/
+/*FUNCTION Node::MyRank{{{*/
+int    Node::MyRank(void){ 
+	extern int my_rank;
+
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Node::ObjectEnum{{{*/
+int Node::ObjectEnum(void){
+
+	return NodeEnum;
+
+}
+/*}}}*/
+
+/*Node management:*/
+/*FUNCTION Node::Configure {{{*/
+void  Node::Configure(DataSet* nodesin,Vertices* verticesin){
+
+	int i;
+
+	/*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 
+	 * datasets, using internal ids and off_sets hidden in hooks: */
+	hvertex->configure(verticesin);
+
+}
+/*FUNCTION Node::SetCurrentConfiguration {{{*/
+void  Node::SetCurrentConfiguration(DataSet* nodesin,Vertices* verticesin){
+
+}
+/*FUNCTION Node::GetDof {{{*/
+int   Node::GetDof(int dofindex,int setenum){
+
+	if(setenum==GsetEnum){
+		_assert_(dofindex>=0 && dofindex<indexing.gsize);
+		return indexing.gdoflist[dofindex];
+	}
+	else if(setenum==FsetEnum){
+		_assert_(dofindex>=0 && dofindex<indexing.fsize);
+		return indexing.fdoflist[dofindex];
+	}
+	else if(setenum==SsetEnum){
+		_assert_(dofindex>=0 && dofindex<indexing.ssize);
+		return indexing.sdoflist[dofindex];
+	}
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+
+}
+/*}}}*/
+/*FUNCTION Node::GetDofList1{{{*/
+int  Node::GetDofList1(void){
+
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)this->hvertex->delivers();
+
+	return vertex->dof;
+}
+/*}}}*/
+/*FUNCTION Node::GetDofList{{{*/
+void  Node::GetDofList(int* outdoflist,int approximation_enum,int setenum){
+	int i;
+	int count=0;
+	int count2=0;
+		
+	if(approximation_enum==NoneApproximationEnum){
+		if(setenum==GsetEnum)for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=indexing.gdoflist[i];
+		if(setenum==FsetEnum)for(i=0;i<this->indexing.fsize;i++) outdoflist[i]=indexing.fdoflist[i];
+		if(setenum==SsetEnum)for(i=0;i<this->indexing.ssize;i++) outdoflist[i]=indexing.sdoflist[i];
+	}
+	else{
+
+		if(setenum==GsetEnum){
+			if(indexing.doftype){
+				count=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.doftype[i]==approximation_enum){
+						outdoflist[count]=indexing.gdoflist[i];
+						count++;
+					}
+				}
+				_assert_(count); //at least one dof should be the approximation requested
+			}
+			else for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=indexing.gdoflist[i];
+		}
+		else if(setenum==FsetEnum){
+			if(indexing.doftype){
+				count=0;
+				count2=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.f_set[i]){
+						if(indexing.doftype[i]==approximation_enum){
+							outdoflist[count]=indexing.fdoflist[count2];
+							count++;
+						}
+						count2++;
+					}
+				}
+			}
+			else for(i=0;i<this->indexing.fsize;i++) outdoflist[i]=indexing.fdoflist[i];
+		}
+		else if(setenum==SsetEnum){
+			if(indexing.doftype){
+				count=0;
+				count2=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.s_set[i]){
+						if(indexing.doftype[i]==approximation_enum){
+							outdoflist[count]=indexing.sdoflist[count2];
+							count++;
+						}
+						count2++;
+					}
+				}
+			}
+			else for(i=0;i<this->indexing.ssize;i++) outdoflist[i]=indexing.sdoflist[i];
+		}
+		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+	}
+}
+/*}}}*/
+/*FUNCTION Node::GetSidList{{{*/
+int  Node::GetSidList(void){
+
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)this->hvertex->delivers();
+
+	return vertex->sid;
+}
+/*}}}*/
+/*FUNCTION Node::GetLocalDofList{{{*/
+void  Node::GetLocalDofList(int* outdoflist,int approximation_enum,int setenum){
+	int i;
+	int count=0;
+	int count2=0;
+		
+	if(approximation_enum==NoneApproximationEnum){
+		if(setenum==GsetEnum)for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=i;
+		else if(setenum==FsetEnum){
+			count=0;
+			for(i=0;i<this->indexing.gsize;i++){
+				if(indexing.f_set[i]){
+					outdoflist[count]=i;
+					count++;
+				}
+			}
+		}
+		else if(setenum==SsetEnum){
+			count=0;
+			for(i=0;i<this->indexing.gsize;i++){
+				if(indexing.s_set[i]){
+					outdoflist[count]=i;
+					count++;
+				}
+			}
+		}
+		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+	}
+	else{
+
+		if(setenum==GsetEnum){
+			if(indexing.doftype){
+				count=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.doftype[i]==approximation_enum){
+						outdoflist[count]=count;
+						count++;
+					}
+				}
+				_assert_(count);
+			}
+			else for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=i;
+		}
+		else if(setenum==FsetEnum){
+
+			if(indexing.doftype){
+				count=0;
+				count2=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.doftype[i]==approximation_enum){
+						if(indexing.f_set[i]){
+							outdoflist[count]=count2;
+							count++;
+						}
+						count2++;
+					}
+				}
+				_assert_(count2);
+			}
+			else{
+
+				count=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.f_set[i]){
+						outdoflist[count]=i;
+						count++;
+					}
+				}
+			}
+		}
+		else if(setenum==SsetEnum){
+			if(indexing.doftype){
+				count=0;
+				count2=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.doftype[i]==approximation_enum){
+						if(indexing.s_set[i]){
+							outdoflist[count]=count2;
+							count++;
+						}
+						count2++;
+					}
+				}
+				_assert_(count2);
+			}
+			else{
+				count=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(indexing.s_set[i]){
+						outdoflist[count]=i;
+						count++;
+					}
+				}
+			}
+		}
+		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+	}
+}
+/*}}}*/
+/*FUNCTION Node::Sid{{{*/
+int    Node::Sid(void){ return sid; }
+/*}}}*/
+/*FUNCTION Node::GetVertexId {{{*/
+int   Node::GetVertexId(void){
+
+	Vertex*  vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->id;
+}
+/*}}}*/
+/*FUNCTION Node::GetVertexDof {{{*/
+int   Node::GetVertexDof(void){
+
+	Vertex*  vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->dof;
+}
+/*}}}*/
+#ifdef _HAVE_DIAGNOSTIC_
+/*FUNCTION Node::GetCoordinateSystem{{{*/
+void Node::GetCoordinateSystem(IssmDouble* coord_system_out){
+
+	/*Copy coord_system*/
+	for(int k=0;k<3;k++) for(int l=0;l<3;l++) coord_system_out[3*k+l]=this->coord_system[k][l];
+
+}
+/*}}}*/
+#endif
+/*FUNCTION Node::SetVertexDof {{{*/
+void   Node::SetVertexDof(int in_dof){
+
+	Vertex*  vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	vertex->dof=in_dof;
+
+}
+/*}}}*/
+/*FUNCTION Node::InAnalysis{{{*/
+bool Node::InAnalysis(int in_analysis_type){
+	if (in_analysis_type==this->analysis_type) return true;
+	else return false;
+}
+/*}}}*/
+
+/*Node numerics:*/
+/*FUNCTION Node::ApplyConstraints{{{*/
+void  Node::ApplyConstraint(int dof,IssmDouble value){
+
+	int index;
+
+	/*Dof should be added in the s set, describing which 
+	 * dofs are constrained to a certain value (dirichlet boundary condition*/
+	DofInSSet(dof-1);
+	this->indexing.svalues[dof-1]=value;
+}
+/*}}}*/
+/*FUNCTION Node::RelaxConstraint{{{*/
+void  Node::RelaxConstraint(int dof){
+
+	/*Dof should be added to the f-set, and taken out of the s-set:*/
+	DofInFSet(dof-1);
+	this->indexing.svalues[dof-1]=NAN;
+}
+/*}}}*/
+/*FUNCTION Node::CreateVecSets {{{*/
+void  Node::CreateVecSets(Vector* pv_g,Vector* pv_f,Vector* pv_s){
+
+	IssmDouble gvalue=1.0; //all nodes are in the g set;
+	IssmDouble value;
+
+	int i;
+
+	for(i=0;i<this->indexing.gsize;i++){
+
+		/*g set: */
+		pv_g->SetValue(indexing.gdoflist[i],gvalue,INS_VAL);
+		
+		/*f set: */
+		value=(IssmDouble)this->indexing.f_set[i];
+		pv_f->SetValue(indexing.gdoflist[i],value,INS_VAL);
+
+		/*s set: */
+		value=(IssmDouble)this->indexing.s_set[i];
+		pv_s->SetValue(indexing.gdoflist[i],value,INS_VAL);
+
+	}
+
+
+}
+/*}}}*/
+/*FUNCTION Node::CreateNodalConstraints{{{*/
+void  Node::CreateNodalConstraints(Vector* ys){
+
+	int i;
+	IssmDouble* values=NULL;
+	int count;
+
+	/*Recover values for s set and plug them in constraints vector: */
+	if(this->indexing.ssize){
+		values=xNew<IssmDouble>(this->indexing.ssize);
+		count=0;
+		for(i=0;i<this->indexing.gsize;i++){
+			if(this->indexing.s_set[i]){
+				values[count]=this->indexing.svalues[i];
+				_assert_(!xIsNan<IssmDouble>(values[count]));
+				count++;
+			}
+		}
+		
+		/*Add values into constraint vector: */
+		ys->SetValues(this->indexing.ssize,this->indexing.sdoflist,values,INS_VAL);
+	}
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(values);
+
+
+}
+/*}}}*/
+/*FUNCTION Node::DofInSSet {{{*/
+void  Node::DofInSSet(int dof){
+
+	/*Put dof for this node into the s set (ie, this dof will be constrained 
+	 * to a fixed value during computations. */
+
+	this->indexing.f_set[dof]=0; //n splits into f (for which we solve) and s (single point constraints)
+	this->indexing.s_set[dof]=1;
+}
+/*}}}*/
+/*FUNCTION Node::DofInFSet {{{*/
+void  Node::DofInFSet(int dof){
+
+	/*Put dof for this node into the f set (ie, this dof will NOT be constrained 
+	 * to a fixed value during computations. */
+
+	this->indexing.f_set[dof]=1; 
+	this->indexing.s_set[dof]=0;
+}
+/*}}}*/
+/*FUNCTION Node::FreezeDof{{{*/
+void  Node::FreezeDof(int dof){
+	
+	DofInSSet(dof-1); //with 0 displacement for this dof.
+
+}
+/*}}}*/
+/*FUNCTION Node::GetApproximation {{{*/
+int   Node::GetApproximation(){
+
+	int approximation;
+
+	/*recover parameters: */
+	inputs->GetInputValue(&approximation,ApproximationEnum);
+
+	return approximation;
+}
+/*}}}*/
+/*FUNCTION Node::GetConnectivity {{{*/
+int Node::GetConnectivity(){
+
+	Vertex*  vertex=NULL;
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->connectivity;
+}
+/*}}}*/
+/*FUNCTION Node::GetNumberOfDofs{{{*/
+int   Node::GetNumberOfDofs(int approximation_enum,int setenum){
+
+	/*Get number of degrees of freedom in a node, for a certain set (g,f or s-set)
+	 *and for a certain approximation type: */
+	
+	int i;
+	int numdofs=0;
+
+	if(approximation_enum==NoneApproximationEnum){
+		if (setenum==GsetEnum) numdofs=this->indexing.gsize;
+		else if (setenum==FsetEnum) numdofs=this->indexing.fsize;
+		else if (setenum==SsetEnum) numdofs=this->indexing.ssize;
+		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+	}
+	else{
+		if(setenum==GsetEnum){
+			if(this->indexing.doftype){
+				numdofs=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if(this->indexing.doftype[i]==approximation_enum) numdofs++;
+				}
+			}
+			else numdofs=this->indexing.gsize;
+		}
+		else if (setenum==FsetEnum){
+			if(this->indexing.doftype){
+				numdofs=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if((this->indexing.doftype[i]==approximation_enum) && (this->indexing.f_set[i])) numdofs++;
+				}
+			}
+			else numdofs=this->indexing.fsize;
+		}
+		else if (setenum==SsetEnum){
+			if(this->indexing.doftype){
+				numdofs=0;
+				for(i=0;i<this->indexing.gsize;i++){
+					if((this->indexing.doftype[i]==approximation_enum) && (this->indexing.s_set[i])) numdofs++;
+				}
+			}
+			else numdofs=this->indexing.ssize;
+		}
+		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+	}
+	return numdofs;
+}
+/*}}}*/
+/*FUNCTION Node::GetSigma {{{*/
+IssmDouble Node::GetSigma(){
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->sigma;
+}
+/*}}}*/
+/*FUNCTION Node::GetX {{{*/
+IssmDouble Node::GetX(){
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->x;
+}
+/*}}}*/
+/*FUNCTION Node::GetY {{{*/
+IssmDouble Node::GetY(){
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->y;
+}
+/*}}}*/
+/*FUNCTION Node::GetZ {{{*/
+IssmDouble Node::GetZ(){
+	Vertex* vertex=NULL;
+
+	vertex=(Vertex*)hvertex->delivers();
+	return vertex->z;
+}
+/*}}}*/
+/*FUNCTION Node::IsClone {{{*/
+int   Node::IsClone(){
+	
+	return indexing.clone;
+
+}
+/*}}}*/
+/*FUNCTION Node::IsOnBed {{{*/
+int   Node::IsOnBed(){
+
+	bool onbed;
+
+	/*recover parameters: */
+	inputs->GetInputValue(&onbed,MeshVertexonbedEnum);
+
+	return onbed;
+}
+/*}}}*/
+/*FUNCTION Node::IsGrounded {{{*/
+int   Node::IsGrounded(){
+
+	bool onsheet;
+
+	/*recover parameters: */
+	inputs->GetInputValue(&onsheet,MaskVertexongroundediceEnum);
+
+	return onsheet;
+}		
+/*}}}*/
+/*FUNCTION Node::IsFloating {{{*/
+int   Node::IsFloating(){
+	
+	bool onshelf;
+
+	/*recover parameters: */
+	inputs->GetInputValue(&onshelf,MaskVertexonfloatingiceEnum);
+
+	return onshelf;
+}
+/*}}}*/
+/*FUNCTION Node::IsOnSurface {{{*/
+int   Node::IsOnSurface(){
+
+	bool onsurface;
+
+	/*recover parameters: */
+	inputs->GetInputValue(&onsurface,MeshVertexonsurfaceEnum);
+
+	return onsurface;
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVector(IssmDouble* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVector(IssmDouble* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVector(int* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVector(int* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVector(bool* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVector(bool* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){{{*/
+void  Node::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVectorDakota(int* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVectorDakota(int* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromVectorDakota(bool* vector, int name, int type){{{*/
+void  Node::InputUpdateFromVectorDakota(bool* vector, int name, int type){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromConstant(IssmDouble constant, int name){{{*/
+void  Node::InputUpdateFromConstant(IssmDouble constant, int name){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromConstant(int constant, int name){{{*/
+void  Node::InputUpdateFromConstant(int constant, int name){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::InputUpdateFromConstant(bool constant, int name){{{*/
+void  Node::InputUpdateFromConstant(bool constant, int name){
+
+	/*Nothing updated yet*/
+}
+/*}}}*/
+/*FUNCTION Node::UpdateSpcs {{{*/
+void   Node::UpdateSpcs(IssmDouble* ys){
+
+	int     count=0;
+	int     i;
+
+	count=0;
+	for(i=0;i<this->indexing.gsize;i++){
+		if(this->indexing.s_set[i]){
+			this->indexing.svalues[i]=ys[this->indexing.sdoflist[count]];
+			count++;
+		}
+	}
+}
+/*}}}*/
+/*FUNCTION Node::VecMerge {{{*/
+void   Node::VecMerge(Vector* ug, IssmDouble* vector_serial,int setenum){
+
+	IssmDouble* values=NULL;
+	int*    indices=NULL;
+	int     count=0;
+	int     i;
+
+	if(setenum==FsetEnum){
+		if(this->indexing.fsize){
+			indices=xNew<int>(this->indexing.fsize);
+ 			values=xNew<IssmDouble>(this->indexing.fsize);
+
+			for(i=0;i<this->indexing.gsize;i++){
+				if(this->indexing.f_set[i]){
+					_assert_(vector_serial);
+					values[count]=vector_serial[this->indexing.fdoflist[count]];
+					indices[count]=this->indexing.gdoflist[i];
+					count++;
+				}
+			}
+
+			/*Add values into ug: */
+			ug->SetValues(this->indexing.fsize,indices,values,INS_VAL);
+		}
+	}
+	else if(setenum==SsetEnum){
+		if(this->indexing.ssize){
+			indices=xNew<int>(this->indexing.ssize);
+			values=xNew<IssmDouble>(this->indexing.ssize);
+
+			for(i=0;i<this->indexing.gsize;i++){
+				if(this->indexing.s_set[i]){
+					_assert_(vector_serial);
+					values[count]=vector_serial[this->indexing.sdoflist[count]];
+					indices[count]=this->indexing.gdoflist[i];
+					count++;
+				}
+			}
+
+			/*Add values into ug: */
+			ug->SetValues(this->indexing.ssize,indices,values,INS_VAL);
+		}
+	}
+	else _error2_("VecMerge can only merge from the s or f-set onto the g-set!");
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(values);
+	xDelete<int>(indices);
+}
+/*}}}*/
+/*FUNCTION Node::VecReduce {{{*/
+void   Node::VecReduce(Vector* vector, IssmDouble* ug_serial,int setenum){
+
+	IssmDouble* values=NULL;
+	int     count=0;
+	int     i;
+
+	if(setenum==FsetEnum){
+		if(this->indexing.fsize){
+ 			values=xNew<IssmDouble>(this->indexing.fsize);
+
+			for(i=0;i<this->indexing.gsize;i++){
+				if(this->indexing.f_set[i]){
+					_assert_(ug_serial);
+					values[count]=ug_serial[this->indexing.gdoflist[i]];
+					count++;
+				}
+			}
+
+			/*Add values into ug: */
+			vector->SetValues(this->indexing.fsize,this->indexing.fdoflist,values,INS_VAL);
+		}
+	}
+	else if(setenum==SsetEnum){
+		if(this->indexing.ssize){
+			values=xNew<IssmDouble>(this->indexing.ssize);
+
+			for(i=0;i<this->indexing.gsize;i++){
+				if(this->indexing.s_set[i]){
+					_assert_(ug_serial);
+					values[count]=ug_serial[this->indexing.gdoflist[i]];
+					count++;
+				}
+			}
+
+			/*Add values into ug: */
+			vector->SetValues(this->indexing.ssize,this->indexing.sdoflist,values,INS_VAL);
+		}
+	}
+	else _error2_("VecReduce can only merge from the s or f-set onto the g-set!");
+
+	/*Free ressources:*/
+	xDelete<IssmDouble>(values);
+}
+/*}}}*/
+
+/* DofObject routines:*/
+/*FUNCTION Node::DistributeDofs{{{*/
+void  Node::DistributeDofs(int* pdofcount,int setenum){
+
+	int i;
+	extern int my_rank;
+	int dofcount;
+
+	dofcount=*pdofcount;
+
+	/*Initialize: */
+	if(setenum==FsetEnum) this->indexing.InitSet(setenum);
+	if(setenum==SsetEnum) this->indexing.InitSet(setenum);
+	
+		
+	/*For clone nodfs, don't distribute dofs, we will get them from another cpu in UpdateCloneDofs!*/
+	if(indexing.clone){
+		return;
+	}
+
+	/*This node should distribute dofs for setenum set (eg, f_set or s_set), go ahead: */
+
+	if(setenum==GsetEnum){
+		for(i=0;i<this->indexing.gsize;i++){
+			indexing.gdoflist[i]=dofcount+i;
+		}
+		dofcount+=this->indexing.gsize;
+	}
+	else if(setenum==FsetEnum){
+		for(i=0;i<this->indexing.fsize;i++){
+			indexing.fdoflist[i]=dofcount+i;
+		}
+		dofcount+=this->indexing.fsize;
+	}
+	else if(setenum==SsetEnum){
+		for(i=0;i<this->indexing.ssize;i++){
+			indexing.sdoflist[i]=dofcount+i;
+		}
+		dofcount+=this->indexing.ssize;
+	}
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+
+
+	/*Assign output pointers: */
+	*pdofcount=dofcount;
+
+}
+/*}}}*/
+/*FUNCTION Node::Off_setDofs{{{*/
+void  Node::OffsetDofs(int dofcount,int setenum){
+	
+	int i;
+	extern int my_rank;
+	
+	if(indexing.clone){
+		/*This node is a clone, don't off_set the dofs!: */
+		return;
+	}
+
+	/*This node should off_set the dofs, go ahead: */
+	if(setenum==GsetEnum){
+		for(i=0;i<this->indexing.gsize;i++) indexing.gdoflist[i]+=dofcount;
+	}
+	else if(setenum==FsetEnum){
+		for(i=0;i<this->indexing.fsize;i++) indexing.fdoflist[i]+=dofcount;
+	}
+	else if(setenum==SsetEnum){
+		for(i=0;i<this->indexing.ssize;i++) indexing.sdoflist[i]+=dofcount;
+	}
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+}
+/*}}}*/
+/*FUNCTION Node::ShowTrueDofs{{{*/
+void  Node::ShowTrueDofs(int* truedofs, int ncols,int setenum){
+
+	int j;
+	extern int my_rank;
+	
+	/*Are we a clone? : */
+	if(indexing.clone)return;
+
+	/*Ok, we are not a clone, just plug our dofs into truedofs: */
+	if(setenum==GsetEnum)for(j=0;j<this->indexing.gsize;j++)  *(truedofs+ncols*sid+j)=indexing.gdoflist[j];
+	else if(setenum==FsetEnum)for(j=0;j<this->indexing.fsize;j++)  *(truedofs+ncols*sid+j)=indexing.fdoflist[j];
+	else if(setenum==SsetEnum)for(j=0;j<this->indexing.ssize;j++)  *(truedofs+ncols*sid+j)=indexing.sdoflist[j];
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+
+}
+/*}}}*/
+/*FUNCTION Node::UpdateCloneDofs{{{*/
+void  Node::UpdateCloneDofs(int* alltruedofs,int ncols,int setenum){
+
+	int j;
+	extern int my_rank;
+	
+	/*If we are not a clone, don't update, we already have dofs!: */
+	if(indexing.clone==0)return;
+
+
+	/*Ok, we are a clone node, but we did not create the dofs for this node.
+	 *      * Therefore, our doflist is garbage right now. Go pick it up in the alltruedofs: */
+	if(setenum==GsetEnum)for(j=0;j<this->indexing.gsize;j++) indexing.gdoflist[j]=*(alltruedofs+ncols*sid+j);
+	else if(setenum==FsetEnum)for(j=0;j<this->indexing.fsize;j++) indexing.fdoflist[j]=*(alltruedofs+ncols*sid+j);
+	else if(setenum==SsetEnum)for(j=0;j<this->indexing.ssize;j++) indexing.sdoflist[j]=*(alltruedofs+ncols*sid+j);
+	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
+
+}
+/*}}}*/
+/*FUNCTION Node::SetClone {{{*/
+void  Node::SetClone(int* minranks){
+
+	extern int my_rank;
+
+	if (minranks[sid]==my_rank){
+		indexing.clone=0;
+	}
+	else{
+		/*!there is a cpu with lower rank that has the same node, 
+		therefore, I am a clone*/
+		indexing.clone=1; 	
+	}
+
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/objects/Node.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Node.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Node.h	(revision 12821)
@@ -0,0 +1,113 @@
+/*!\file Node.h
+ * \brief: header file for node object
+ */
+
+#ifndef _NODE_H_
+#define _NODE_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+#include "../shared/shared.h"
+class  Inputs;
+class  Hook;
+class  DofIndexing;
+class  IoModel;
+class  DataSet;
+class  Vertices;
+class  Vector;
+class  Matrix;
+#include "./Update.h"
+/*}}}*/
+
+class Node: public Object ,public Update{
+
+	public: 
+
+		int	    id;  //unique arbitrary id.
+		int     sid; //sid for "serial" id, ie the rank of this node in the nodes dataset, if the dataset was serial on 1 cpu.
+				
+		DofIndexing    indexing;
+		Hook*          hvertex;
+		Inputs*        inputs; //properties of this node
+		int            analysis_type;
+		IssmDouble         coord_system[3][3];
+
+		/*Node constructors, destructors {{{*/
+		Node();
+		Node(int node_id,int node_sid, int vertex_id,int io_index, IoModel* iomodel,int analysis_type);
+		~Node();
+		/*}}}*/
+		/*Object virtual functions definitions:{{{ */
+		void  Echo();
+		void  DeepEcho();
+		int   Id(); 
+		int   MyRank();
+		int   ObjectEnum();
+		Object* copy(){_error2_("Not implemented yet (similar to Elements)");};
+		/*}}}*/
+		/*Update virtual functions definitions: {{{*/
+		
+		void  InputUpdateFromVector(IssmDouble* vector, int name, int type);
+		void  InputUpdateFromVector(int* vector, int name, int type);
+		void  InputUpdateFromVector(bool* vector, int name, int type);
+		void  InputUpdateFromMatrixDakota(IssmDouble* matrix,int nrows, int ncols, int name, int type);
+		void  InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type);
+		void  InputUpdateFromVectorDakota(int* vector, int name, int type);
+		void  InputUpdateFromVectorDakota(bool* vector, int name, int type);
+		void  InputUpdateFromConstant(IssmDouble constant, int name);
+		void  InputUpdateFromConstant(int constant, int name);
+		void  InputUpdateFromConstant(bool constant, int name);
+		void  InputUpdateFromSolution(IssmDouble* solution){_error2_("Not implemented yet!");}
+		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error2_("Not implemented yet!");}
+		/*}}}*/
+		/*Node numerical routines {{{*/
+		void   Configure(DataSet* nodes,Vertices* vertices);
+		void   CreateNodalConstraints(Vector* ys);
+		void   SetCurrentConfiguration(DataSet* nodes,Vertices* vertices);
+		int    Sid(void); 
+		int    GetVertexDof(void);
+		int    GetVertexId(void);
+#ifdef _HAVE_DIAGNOSTIC_
+		void   GetCoordinateSystem(IssmDouble* coord_system_out);
+#endif
+		void   SetVertexDof(int in_dof);
+		bool   InAnalysis(int analysis_type);
+		int    GetApproximation();
+		int    GetNumberOfDofs(int approximation_enum,int setenum);
+		int    IsClone();
+		void   ApplyConstraint(int dof,IssmDouble value);
+		void   RelaxConstraint(int dof);
+		void   DofInSSet(int dof);
+		void   DofInFSet(int dof);
+		int    GetDof(int dofindex,int setenum);
+		void   CreateVecSets(Vector* pv_g,Vector* pv_f,Vector* pv_s);
+		int    GetConnectivity();
+		void   GetDofList(int* poutdoflist,int approximation_enum,int setenum);
+		void   GetLocalDofList(int* poutdoflist,int approximation_enum,int setenum);
+		int    GetDofList1(void);
+		int    GetSidList(void);
+		IssmDouble GetX();
+		IssmDouble GetY();
+		IssmDouble GetZ();
+		IssmDouble GetSigma();
+		int    IsOnBed();
+		int    IsOnSurface();
+		void   FreezeDof(int dof);
+		int    IsFloating();
+		int    IsGrounded();
+		void   UpdateSpcs(IssmDouble* ys);
+		void   VecMerge(Vector* ug, IssmDouble* vector_serial,int setenum);
+		void   VecReduce(Vector* vector, IssmDouble* ug_serial,int setnum);
+		
+		/*}}}*/
+		/*Dof Object routines {{{*/
+		void  DistributeDofs(int* pdofcount,int setenum);
+		void  OffsetDofs(int dofcount,int setenum);
+		void  ShowTrueDofs(int* truerows,int ncols,int setenum);
+		void  UpdateCloneDofs(int* alltruerows,int ncols,int setenum);
+		void  SetClone(int* minranks);
+		/*}}}*/
+};
+
+#endif  /* _NODE_H_ */
Index: /issm/trunk-jpl/src/c/classes/objects/Object.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Object.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Object.h	(revision 12821)
@@ -0,0 +1,27 @@
+/*
+ * Object.h:
+ * \brief prototype for abstract Object class
+ * \file Object.h
+ * This prototype describes the Object class. This is an abstract class, parent 
+ * to any other objects (Quad, Tria, Node , etc ...), that can be included in a 
+ * DataSet.
+ */
+
+
+#ifndef _OBJECT_H_
+#define _OBJECT_H_
+
+class Object {
+
+	public: 
+
+		virtual       ~Object() {};
+		virtual void  Echo()=0;
+		virtual void  DeepEcho()=0;
+		virtual int   Id()=0;
+		virtual int   MyRank()=0;
+		virtual int   ObjectEnum()=0;
+		virtual Object* copy()=0;
+
+};
+#endif
Index: /issm/trunk-jpl/src/c/classes/objects/Segment.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Segment.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Segment.cpp	(revision 12821)
@@ -0,0 +1,86 @@
+/*!\file Segment.c
+ * \brief: implementation of the Segment object
+ */
+
+/*Include files: {{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "./objects.h"
+#include "../Container/Container.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../include/include.h"
+/*}}}*/
+
+/*Segment constructors and destructors:*/
+/*FUNCTION Segment::Segment() default constructor {{{*/
+Segment::Segment(){
+	this->eid=UNDEF;
+	this->x1=UNDEF;
+	this->y1=UNDEF;
+	this->x2=UNDEF;
+	this->y2=UNDEF;
+}
+/*}}}*/
+/*FUNCTION Segment::Segment(int eid, IssmDouble x1,IssmDouble y1,IssmDouble x2, IssmDouble y2){{{*/
+Segment::Segment(int segment_eid, IssmDouble segment_x1,IssmDouble segment_y1,IssmDouble segment_x2, IssmDouble segment_y2){
+
+	this->eid=segment_eid;
+	this->x1=segment_x1;
+	this->y1=segment_y1;
+	this->x2=segment_x2;
+	this->y2=segment_y2;
+
+}
+/*}}}*/
+/*FUNCTION Segment::~Segment(){{{*/
+Segment::~Segment(){
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION Segment::Echo{{{*/
+void Segment::Echo(void){
+
+	_printLine_("Segment:");
+	_printLine_("   eid: " << eid);
+	_printLine_("   node 1: " << this->x1 << "|" << this->y1);
+	_printLine_("   node 2: " << this->x2 << "|" << this->y2);
+
+}
+/*}}}*/
+/*FUNCTION Segment::DeepEcho{{{*/
+void Segment::DeepEcho(void){
+	this->Echo();
+}
+/*}}}*/
+/*FUNCTION Segment::Id{{{*/
+int    Segment::Id(void){ return eid; }
+/*}}}*/
+/*FUNCTION Segment::MyRank{{{*/
+int    Segment::MyRank(void){ 
+	extern int my_rank;
+
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Segment::ObjectEnum{{{*/
+int Segment::ObjectEnum(void){
+
+	return SegmentEnum;
+
+}
+/*}}}*/
+/*FUNCTION Segment::copy {{{*/
+Object* Segment::copy() {
+	return new Segment(this->eid,this->x1,this->y1,this->x2,this->y2);
+
+}
+
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/objects/Segment.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Segment.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Segment.h	(revision 12821)
@@ -0,0 +1,37 @@
+/*!\file Segment.h
+ * \brief: header file for node object
+ */
+
+#ifndef _SEGMENT_H_
+#define _SEGMENT_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+/*}}}*/
+
+class Segment: public Object{
+
+	public:
+		int eid;
+		IssmDouble x1;
+		IssmDouble y1;
+		IssmDouble x2;
+		IssmDouble y2;
+
+		/*Segment constructors, destructors {{{*/
+		Segment();
+		Segment(int eid,IssmDouble x1,IssmDouble y1, IssmDouble x2, IssmDouble y2);
+		~Segment();
+		/*}}}*/
+		/*Object virtual functions definitions:{{{ */
+		void  Echo();
+		void  DeepEcho();
+		int   Id(); 
+		int   MyRank();
+		int   ObjectEnum();
+		Object* copy();
+		/*}}}*/
+};
+
+#endif  /* _SEGMENT_H_ */
Index: /issm/trunk-jpl/src/c/classes/objects/Vertex.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Vertex.cpp	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Vertex.cpp	(revision 12821)
@@ -0,0 +1,218 @@
+/*!\file Vertex.c
+ * \brief: implementation of the Vertex object
+ */
+
+/*Include files: {{{*/
+#ifdef HAVE_CONFIG_H
+	#include <config.h>
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include <string.h>
+#include "./objects.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+#include "../shared/shared.h"
+#include "../include/include.h"
+/*}}}*/
+
+/*Vertex constructors and destructor:*/
+/*FUNCTION Vertex::Vertex() {{{*/
+Vertex::Vertex(){
+	return;
+}
+/*}}}*/
+/*FUNCTION Vertex::Vertex(int vertex_id, IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma){{{*/
+Vertex::Vertex(int vertex_id, int vertex_sid,IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma,int vertex_connectivity){
+	this->Init(vertex_id, vertex_sid,vertex_x, vertex_y, vertex_z, vertex_sigma,vertex_connectivity);
+}
+/*}}}*/
+/*FUNCTION Vertex::Vertex(int vertex_id, int vertex_sid,int i, IoModel* iomodel) {{{*/
+Vertex::Vertex(int vertex_id, int vertex_sid,int i, IoModel* iomodel){
+
+	_assert_(iomodel->Data(MeshXEnum) && iomodel->Data(MeshYEnum) && iomodel->Data(MeshZEnum));
+	_assert_(iomodel->Data(BedEnum) && iomodel->Data(ThicknessEnum) && iomodel->numbernodetoelementconnectivity);
+
+	this->Init(vertex_id, vertex_sid, iomodel->Data(MeshXEnum)[i],iomodel->Data(MeshYEnum)[i],iomodel->Data(MeshZEnum)[i],(iomodel->Data(MeshZEnum)[i]-iomodel->Data(BedEnum)[i])/(iomodel->Data(ThicknessEnum)[i]),iomodel->numbernodetoelementconnectivity[i]);
+
+}
+/*}}}*/
+/*FUNCTION Vertex::~Vertex() {{{*/
+Vertex::~Vertex(){
+	return;
+}
+/*}}}*/
+/*FUNCTION Vertex::Init{{{*/
+void Vertex::Init(int vertex_id, int vertex_sid,IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma,int vertex_connectivity){
+
+	/*all the initialization has been done by the initializer, just fill in the id: */
+	this->id=vertex_id;
+	this->sid=vertex_sid;
+	this->x=vertex_x;
+	this->y=vertex_y;
+	this->z=vertex_z;
+	this->sigma=vertex_sigma;
+	this->connectivity=vertex_connectivity;
+	this->dof=UNDEF;
+
+	return;
+}
+/*}}}*/
+
+/*Object virtual functions definitions:*/
+/*FUNCTION Vertex::Echo{{{*/
+void Vertex::Echo(void){
+
+	_printLine_("Vertex:");
+	_printLine_("   id: " << id);
+	_printLine_("   sid: " << sid);
+	_printLine_("   x: " << x);
+	_printLine_("   y: " << y);
+	_printLine_("   z: " << z);
+	_printLine_("   sigma: " << sigma);
+	_printLine_("   connectivity: " << connectivity);
+	_printLine_("   dof: " << dof);
+	_printLine_("   clone: " << clone);
+
+	return;
+}
+/*}}}*/
+/*FUNCTION Vertex::DeepEcho{{{*/
+void Vertex::DeepEcho(void){
+	this->Echo();
+}
+/*}}}*/
+/*FUNCTION Vertex::Id{{{*/
+int    Vertex::Id(void){ return id; }
+/*}}}*/
+/*FUNCTION Vertex::MyRank {{{*/
+int    Vertex::MyRank(void){ 
+	extern int my_rank;
+	return my_rank; 
+}
+/*}}}*/
+/*FUNCTION Vertex::ObjectEnum{{{*/
+int Vertex::ObjectEnum(void){
+
+	return VertexEnum;
+
+}
+/*}}}*/
+/*FUNCTION Vertex::copy {{{*/
+Object* Vertex::copy() {
+
+	return new Vertex(*this); 
+
+}
+/*}}}*/
+
+/* DofObject routines: */
+/*FUNCTION Vertex::DistributeDofs{{{*/
+void  Vertex::DistributeDofs(int* pdofcount){
+
+	int i;
+	extern int my_rank;
+	int dofcount;
+
+	dofcount=*pdofcount;
+	
+	if(this->clone){
+		/*This vertex is a clone! Don't distribute dofs, it will get them from another cpu!*/
+		return;
+	}
+
+	/*This vertex should distribute his dof, go ahead: */
+	this->dof=dofcount;
+	dofcount++;
+
+	/*Assign output pointers: */
+	*pdofcount=dofcount;
+
+}
+/*}}}*/
+/*FUNCTION Vertex::OffsetDofs{{{*/
+void  Vertex::OffsetDofs(int dofcount){
+	
+	int i;
+	extern int my_rank;
+	
+	if(this->clone){
+		/*This vertex is a clone, don't offset the dofs!: */
+		return;
+	}
+
+	/*This vertex should offset his dof, go ahead: */
+	this->dof+=dofcount;
+}
+/*}}}*/
+/*FUNCTION Vertex::ShowTrueDofs{{{*/
+void  Vertex::ShowTrueDofs(int* truedofs){
+
+	int j;
+	extern int my_rank;
+	
+	/*Are we a clone? : */
+	if(this->clone)return;
+
+	/*Ok, we are not a clone, just plug our dof into truedofs: */
+	truedofs[this->id-1]=this->dof;
+
+}
+/*}}}*/
+/*FUNCTION Vertex::UpdateCloneDofs{{{*/
+void  Vertex::UpdateCloneDofs(int* alltruedofs){
+
+	int j;
+	extern int my_rank;
+	
+	/*If we are not a clone, don't update, we already have dofs!: */
+	if(this->clone==0)return;
+
+	/*Ok, we are a clone node, but we did not create the dof for this vertex 
+	 * Therefore, our dof is garbage right now. Go pick it up in the alltruedofs: */
+	this->dof=alltruedofs[id-1];
+}
+/*}}}*/
+/*FUNCTION Vertex::SetClone {{{*/
+void  Vertex::SetClone(int* minranks){
+
+	extern int my_rank;
+
+	if (minranks[id-1]==my_rank){
+		this->clone=0;
+	}
+	else{
+		/*!there is a cpu with lower rank that has the same vertex, 
+		therefore, I am a clone*/
+		this->clone=1; 	
+	}
+
+}
+/*}}}*/
+
+/*Vertex management: */
+/*FUNCTION Vertex::Connectivity{{{*/
+int    Vertex::Connectivity(void){return connectivity;}
+/*}}}*/
+/*FUNCTION Vertex::Sid{{{*/
+int    Vertex::Sid(void){ return sid; }
+/*}}}*/
+/*FUNCTION Vertex::UpdateVertexPosition {{{*/
+void  Vertex::UpdatePosition(Vector* vz,Parameters* parameters,IssmDouble* thickness,IssmDouble* bed){
+
+	IssmDouble oldz,newz;
+	IssmDouble dt,velz;
+
+	/*Get time stepping*/
+	parameters->FindParam(&dt,TimesteppingTimeStepEnum);
+
+	/*sigma remains constant. z=bed+sigma*thickness*/
+	oldz = this->z;
+	newz = bed[this->dof]+sigma*thickness[this->dof];
+	velz = (newz-oldz)/dt;
+	this->z = newz;
+
+	/*put vz in vector*/
+	vz->SetValue(this->dof,velz,INS_VAL);
+}
+/*}}}*/
Index: /issm/trunk-jpl/src/c/classes/objects/Vertex.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Vertex.h	(revision 12821)
+++ /issm/trunk-jpl/src/c/classes/objects/Vertex.h	(revision 12821)
@@ -0,0 +1,65 @@
+/*! \file Vertex.h 
+ *  \brief: header file for vertex object
+ */
+
+#ifndef _VERTEX_H_
+#define _VERTEX_H_
+
+/*Headers:*/
+/*{{{*/
+#include "./Object.h"
+class IoModel;
+class Vector;
+class Parameters;
+#include "../shared/Exceptions/exceptions.h"
+#include "../toolkits/toolkits.h"
+#include "../include/include.h"
+
+/*}}}*/
+
+
+class Vertex: public Object{
+
+	public: 
+
+		int    id;
+		int    sid;            //sid for "serial" id, ie the rank of this vertex in the vertices dataset, if the dataset was serial on 1 cpu.
+		IssmDouble x;
+		IssmDouble y;
+		IssmDouble z;
+		IssmDouble sigma;          //sigma coordinate: (z-bed)/thickness
+		int    connectivity;   //number of vertices connected to this vertex
+
+		/*dof management: */
+		int    clone;
+		int    dof; //dof to recover values in a vertex indexed vector
+
+		/*Vertex constructors, destructors {{{*/
+		Vertex();
+		Vertex(int id, int sid,IssmDouble x, IssmDouble y, IssmDouble z, IssmDouble sigma, int connectivity); 
+		void Init(int id, int sid, IssmDouble x, IssmDouble y, IssmDouble z, IssmDouble sigma,int connectivity);
+		Vertex(int id, int sid, int i, IoModel* iomodel);
+		~Vertex();
+		/*}}}*/
+		/*Object virtual functions definitions:{{{ */
+		void  Echo();
+		void  DeepEcho();
+		int   Id(); 
+		int   MyRank();
+		int   ObjectEnum();
+		Object* copy();
+		/*}}}*/
+		/*DofObject routines {{{*/
+		void  DistributeDofs(int* pdofcount);
+		void  OffsetDofs(int dofcount);
+		void  ShowTrueDofs(int* borderdofs);
+		void  UpdateCloneDofs(int* allborderdofs);
+		void  SetClone(int* minranks);
+		/*}}}*/
+		/*Vertex management: {{{*/
+		int   Sid(void); 
+		int   Connectivity(void); 
+		void  UpdatePosition(Vector* vz,Parameters* parameters,IssmDouble* thickness,IssmDouble* bed);
+		/*}}}*/
+};
+#endif  /* _VERTEX_H */
Index: sm/trunk-jpl/src/c/objects/Contour.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Contour.cpp	(revision 12820)
+++ 	(revision )
@@ -1,95 +1,0 @@
-/*! \file Contour.c
- *  \sa Contour.h
- */
-
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <string.h>
-#include "./objects.h"
-#include "../include/include.h"
-#include "../io/io.h"
-
-/*Contour constructors and destructors:*/
-/*FUNCTION Contour::Contour() default constructor {{{*/
-Contour::Contour(){
-	this->id=0;
-	this->nods=0;
-	this->x=NULL;
-	this->y=NULL;
-	this->closed=false;
-}
-/*}}}*/
-/*FUNCTION Contour::Contour(int pid, int nods, IssmDouble* x, IssmDouble* y,bool closed) {{{*/
-Contour::Contour(int pid,int pnods, IssmDouble* px, IssmDouble* py,bool pclosed){
-	
-	this->id=pid;
-	this->nods=pnods;
-	this->closed=pclosed;
-	if(nods){
-		this->x=xNew<IssmDouble>(nods);
-		xMemCpy<IssmDouble>(this->x,px,nods);
-		this->y=xNew<IssmDouble>(nods);
-		xMemCpy<IssmDouble>(this->y,py,nods);
-	}
-}
-/*}}}*/
-/*FUNCTION Contour::Contour() default constructor {{{*/
-Contour::~Contour(){
-	xDelete<IssmDouble>(this->x);
-	xDelete<IssmDouble>(this->y);
-}
-/*}}}*/
-
-
-/*Object virtual function resolutoin: */
-/*FUNCTION Contour::Echo(){{{*/
-void Contour::Echo(void){
-
-	int i;
-
-	_printLine_("Contour: " << id);
-	_printLine_("   nods: " << nods);
-	_printLine_("   closed: " << (closed?"true":"false"));
-	if(nods){
-	        _printLine_("   x,y:");
-		for(i=0;i<nods;i++){
-		        _printLine_(i << ": " << x[i] << "|" << y[i]);
-		}
-	}
-}
-/*}}}*/
-/*FUNCTION Contour::DeepEcho(){{{*/
-void Contour::DeepEcho(void){
-	this->Echo();
-}
-/*}}}*/
-/*FUNCTION Contour::Id(){{{*/
-int Contour::Id(void){
-	return id;
-}
-/*}}}*/
-/*FUNCTION Contour::MyRank{{{*/
-int    Contour::MyRank(void){ 
-	extern int my_rank;
-
-	return my_rank; 
-}
-/*}}}*/
-/*FUNCTION Contour::ObjectEnum{{{*/
-int Contour::ObjectEnum(void){
-
-	return ContourEnum;
-
-}
-/*}}}*/
-/*FUNCTION Contour::copy {{{*/
-Object* Contour::copy() {
-
-	return new Contour(*this); 
-
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Contour.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Contour.h	(revision 12820)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*!\file Contour.h
- * \brief: header file for Contour object
- */
-
-#ifndef _CONTOUR_H_
-#define _CONTOUR_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-#include "../shared/Exceptions/exceptions.h"
-#include "../toolkits/toolkits.h"
-#include "../include/include.h"
-/*}}}*/
-
-class Contour: public Object{
-
-	public: 
-
-		int     id;
-		int	  nods;  //number of vertices in the contour
-		IssmDouble* x;
-		IssmDouble* y;
-		bool    closed; //is this contour closed?
-
-		/*Contour constructors, destructors {{{*/
-		Contour();
-		Contour(int id, int nods, IssmDouble* x, IssmDouble* y,bool closed);
-		~Contour();
-		/*}}}*/
-		/*Object virtual functions{{{*/
-		void  Echo(void);
-		void  DeepEcho(void);
-		int   Id(void);
-		int   MyRank(void);
-		int   ObjectEnum(void);
-		Object* copy(void);
-		/*}}}*/
-
-
-};
-
-#endif  /* _CONTOUR_H_ */
Index: sm/trunk-jpl/src/c/objects/DakotaPlugin.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/DakotaPlugin.cpp	(revision 12820)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*!\file:  DakotaPlugin.cpp (see DakotaPlugin.h for explanations)
- * \brief  header file for derived DirectApplicInterface class. 
- * \sa SpwanCore.cpp and \sa qmu.cpp
- *
- * This class needs to be understood simultaneously with qmu.cpp and SpwanCore.cpp. 
- * This call is derived from the Dakota DirectApplicInterface class. This is the 
- * only way to plug ISSM's own routines into the Dakota engine. The derived class 
- * has one function called derived_map_ac, which is called by Dakota to drive the 
- * entire snesitivity analysis. 
- *
- * We use this routine (which gets variables, variable_descriptors from the Dakota 
- * engine, and requests responses from the ISSM solution sequences), to call our 
- * own solutoin cores. This routines calls the SpawnCore routine, which will drive 
- * the entire computations. 
- */ 
-
-
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-/*Standard ISSM includes: */
-#include "../shared/shared.h"
-#include "../include/include.h"
-#include "../objects/objects.h"
-#include "../modules/Dakotax/Dakotax.h"
-
-/*Standard includes: */
-#include <string>
-
-#ifdef _HAVE_DAKOTA_ //only works if dakota library has been compiled in.
-
-//Dakota headers
-#include "DakotaResponse.H"
-#include "ParamResponsePair.H"
-#include "DakotaPlugin.h"
-#include "system_defs.h"
-#include "ProblemDescDB.H"
-#include "ParallelLibrary.H"
-
-namespace SIM {
-
-//constructor
-DakotaPlugin::DakotaPlugin(const Dakota::ProblemDescDB& problem_db,void* in_femmodel):Dakota::DirectApplicInterface(problem_db){
-
-
-	femmodel=in_femmodel;
-	counter=0;
-}
-
-//destructor
-DakotaPlugin::~DakotaPlugin(){ /* Virtual destructor handles referenceCount at Interface level. */ }
-
-int DakotaPlugin::derived_map_ac(const Dakota::String& driver) {
-
-	int i;
-	IssmDouble* variables=NULL;
-	char** variable_descriptors=NULL;
-	char*  variable_descriptor=NULL;
-	IssmDouble* responses=NULL;
-
-	/*increae counter: */
-	counter++;
-
-	/*Before launching analysis, we need to transfer the dakota inputs into Issm 
-	 *readable variables: */
-
-	/*First, the variables: */
-	variables=xNew<IssmDouble>(numACV);
-	for(i=0;i<numACV;i++){
-		variables[i]=xC[i];
-	}
-	/*The descriptors: */
-	variable_descriptors=xNew<char*>(numACV);
-	for(i=0;i<numACV;i++){
-		string label=xCLabels[i];
-		variable_descriptor=xNew<char>(strlen(label.c_str())+1);
-		memcpy(variable_descriptor,label.c_str(),(strlen(label.c_str())+1)*sizeof(char));
-
-		
-		variable_descriptors[i]=variable_descriptor;
-	}
-
-	/*Initialize responses: */
-	responses=xNewZeroInit<IssmDouble>(numFns);
-
-	/*run core solution: */
-	SpawnCore(responses,numFns, variables,variable_descriptors,numACV,femmodel,counter);
-
-	/*populate responses: */
-	for(i=0;i<numFns;i++){
-		fnVals[i]=responses[i];
-	}
-
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(variables);
-	for(i=0;i<numACV;i++){
-		variable_descriptor=variable_descriptors[i];
-		xDelete<char>(variable_descriptor);
-	}
-	xDelete<char*>(variable_descriptors);
-	xDelete<IssmDouble>(responses);
-
-	return 0;
-}
-  
-
-int DakotaPlugin::GetCounter(){
-	return counter;
-}
-
-} // namespace SIM
-
-
-#endif //only works if dakota library has been compiled in.
Index: sm/trunk-jpl/src/c/objects/DakotaPlugin.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/DakotaPlugin.h	(revision 12820)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*!\file:  DakotaPlugin.h:
- */ 
-
-#ifndef _DAKOTAPLUGIN_H
-#define _DAKOTAPLUGIN_H
-
-
-#ifdef _HAVE_DAKOTA_ //only works if dakota library has been compiled in.
-
-/*Headers:*/
-/*{{{*/
-
-
-#include "DirectApplicInterface.H"
-#include "../toolkits/toolkits.h"
-#include "../objects/objects.h"
-
-/*}}}*/
-
-namespace SIM {
-
-class DakotaPlugin: public Dakota::DirectApplicInterface
-{
-public:
-
-	DakotaPlugin(const Dakota::ProblemDescDB& problem_db,void* model);
-	~DakotaPlugin();
-
-	/*these fields are used by core solutions: */
-	void* femmodel;
-
-	int counter;
-
-protected:
-
-  // execute the input filter portion of a direct evaluation invocation
-  //int derived_map_if(const Dakota::String& if_name);
-  /// execute an analysis code portion of a direct evaluation invocation
-  int derived_map_ac(const Dakota::String& ac_name);
-  // execute the output filter portion of a direct evaluation invocation
-  //int derived_map_of(const Dakota::String& of_name);
-
-  /*add for issm: */
-  int GetCounter();
-
-private:
-
-};
-
-} // namespace SIM
-
-#endif //only works if dakota library has been compiled in.
-
-
-#endif
Index: sm/trunk-jpl/src/c/objects/DofIndexing.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/DofIndexing.cpp	(revision 12820)
+++ 	(revision )
@@ -1,210 +1,0 @@
-/*!\file DofIndexing.c
- * \brief: implementation of the DofIndexing object
- */
-
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include "./objects.h"
-#include <string.h>
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../Container/Container.h"
-#include "../include/include.h"
-
-/*DofIndexing constructors and destructor*/
-/*FUNCTION DofIndexing::DofIndexing(){{{*/
-DofIndexing::DofIndexing(){
-
-	this->gsize=UNDEF;
-	this->fsize=UNDEF;
-	this->ssize=UNDEF;
-	this->clone=0;
-	this->f_set=NULL;
-	this->s_set=NULL;
-	this->svalues=NULL;
-	this->doftype=NULL;
-	this->gdoflist=NULL;
-	this->fdoflist=NULL;
-	this->sdoflist=NULL;
-
-}
-/*}}}*/
-/*FUNCTION DofIndexing::DofIndexing(int gsize){{{*/
-DofIndexing::DofIndexing(int in_gsize){
-	this->Init(in_gsize,NULL);
-}
-/*}}}*/
-/*FUNCTION DofIndexing::DofIndexing(DofIndexing* in)  -> copy{{{*/
-DofIndexing::DofIndexing(DofIndexing* in){ //copy constructor
-
-	int i;
-	this->gsize=in->gsize;
-	this->fsize=in->fsize;
-	this->ssize=in->ssize;
-	
-	this->clone=in->clone;
-
-	if(this->gsize>0){
-		this->f_set=xNew<bool>(this->gsize);
-		this->s_set=xNew<bool>(this->gsize);
-		this->svalues=xNew<IssmDouble>(this->gsize);
-		if(in->doftype)this->doftype=xNew<int>(this->gsize); 
-		this->gdoflist=xNew<int>(this->gsize); 
-	}
-	else{
-		this->f_set=NULL;
-		this->s_set=NULL;
-		this->svalues=NULL;
-		this->doftype=NULL;
-		this->gdoflist=NULL;
-	}
-	if(this->fsize>0 && this->fsize!=UNDEF)this->fdoflist=xNew<int>(this->fsize); else this->fdoflist=NULL;
-	if(this->ssize>0 && this->ssize!=UNDEF)this->sdoflist=xNew<int>(this->ssize); else this->sdoflist=NULL;
-
-	if(this->gsize>0){
-		memcpy(this->f_set,in->f_set,this->gsize*sizeof(bool));
-		memcpy(this->s_set,in->s_set,this->gsize*sizeof(bool));
-		xMemCpy<IssmDouble>(this->svalues,in->svalues,this->gsize);
-		if(this->doftype)memcpy(this->doftype,in->doftype,this->gsize*sizeof(int));
-		memcpy(this->gdoflist,in->gdoflist,this->gsize*sizeof(int));
-	}
-	if(this->fsize>0 && this->fsize!=UNDEF)memcpy(this->fdoflist,in->fdoflist,this->fsize*sizeof(int));
-	if(this->ssize>0 && this->ssize!=UNDEF)memcpy(this->sdoflist,in->sdoflist,this->ssize*sizeof(int));
-
-}
-/*}}}*/
-/*FUNCTION DofIndexing::~DofIndexing() {{{*/
-DofIndexing::~DofIndexing(){ //destructor
-
-	xDelete<bool>(f_set); 
-	xDelete<bool>(s_set); 
-	xDelete<IssmDouble>(svalues);
-	xDelete<int>(doftype); 
-	xDelete<int>(gdoflist);
-	xDelete<int>(fdoflist);
-	xDelete<int>(sdoflist);
-
-}
-/*}}}*/
-/*FUNCTION DofIndexing::Init{{{*/
-void DofIndexing::Init(int in_gsize,int* in_doftype){
-
-	int i;
-	this->gsize=in_gsize;
-	
-	this->clone=0;
-
-	/*allocate: */
-	if(this->gsize>0){
-		this->f_set=xNew<bool>(this->gsize);
-		this->s_set=xNew<bool>(this->gsize);
-		this->svalues=xNew<IssmDouble>(this->gsize);
-		if(in_doftype)this->doftype=xNew<int>(this->gsize);
-		this->gdoflist=xNew<int>(this->gsize);
-	}
-
-	for (i=0;i<this->gsize;i++){
-		/*assume dof is free, no constraints, no rigid body constraint: */
-		this->f_set[i]=true;
-		this->s_set[i]=false;
-		if(this->doftype)this->doftype[i]=in_doftype[i];
-		this->svalues[i]=0; //0 constraint is the default value
-		this->gdoflist[i]=UNDEF;
-	}
-}
-/*}}}*/
-/*FUNCTION DofIndexing::InitSet{{{*/
-void DofIndexing::InitSet(int setenum){
-
-	int i;
-	int size=0;
-
-	/*go through sets, and figure out how many dofs belong to this set, except for g-set, 
-	 * which has already been initialized: */
-	if(setenum==FsetEnum){
-		size=0;
-		for(i=0;i<this->gsize;i++) if(f_set[i])size++;
-		this->fsize=size;
-		xDelete<int>(this->fdoflist);
-		if(this->fsize)this->fdoflist=xNew<int>(size);
-		else this->fdoflist=NULL;
-	}
-	else if(setenum==SsetEnum){
-		size=0;
-		for(i=0;i<this->gsize;i++) if(s_set[i])size++;
-		this->ssize=size;
-		xDelete<int>(this->sdoflist);
-		if(this->ssize)this->sdoflist=xNew<int>(size);
-		else this->sdoflist=NULL;
-	}
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-}
-/*}}}*/
-
-/*Some of the Object functionality: */
-/*FUNCTION DofIndexing::Echo{{{*/
-void DofIndexing::Echo(void){
-
-	int i;
-
-	_printLine_("DofIndexing:");
-	_printLine_("   gsize: " << gsize);
-	_printLine_("   clone: " << clone);
-}
-/*}}}*/
-/*FUNCTION DofIndexing::DeepEcho{{{*/
-void DofIndexing::DeepEcho(void){
-
-	int i;
-
-	_printLine_("DofIndexing:");
-	_printLine_("   gsize: " << gsize);
-	_printLine_("   fsize: " << fsize);
-	_printLine_("   ssize: " << ssize);
-	_printLine_("   clone: " << clone);
-	
-	_printLine_("   set membership: f,s sets ");
-	for(i=0;i<gsize;i++){
-		_printLine_("      dof " << i << ": " <<(f_set[i]?"true":"false")<< " " <<(s_set[i]?"true":"false"));
-	}
-
-	_printString_("   svalues (" << this->ssize << "): |");
-	for(i=0;i<this->gsize;i++){
-		if(this->s_set[i])_printString_(" " << svalues[i] << " |");
-	}
-	_printLine_("");
-
-	if(doftype){
-		_printString_("   doftype: |");
-		for(i=0;i<gsize;i++){
-			_printString_(" " << doftype[i] << " |");
-		}
-		_printLine_("");
-	}
-	else _printLine_("   doftype: NULL");
-
-	_printString_("   g_doflist (" << this->gsize << "): |");
-	for(i=0;i<this->gsize;i++){
-		_printString_(" " << gdoflist[i] << " |");
-	}
-	_printLine_("");
-
-	_printString_("   f_doflist (" << this->fsize << "): |");
-	for(i=0;i<this->fsize;i++){
-		_printString_(" " << fdoflist[i] << " |");
-	}
-	_printLine_("");
-
-	_printString_("   s_doflist (" << this->ssize << "): |");
-	for(i=0;i<this->ssize;i++){
-		_printString_(" " << sdoflist[i] << " |");
-	}
-	_printLine_("");
-}		
-/*}}}*/
-
Index: sm/trunk-jpl/src/c/objects/DofIndexing.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/DofIndexing.h	(revision 12820)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*!\file: DofIndexing.h
- * \brief prototype for DofIndexing.h
- */ 
-
-#ifndef _DOFINDEXING_H_
-#define  _DOFINDEXING_H_
-
-#include "../include/include.h"
-
-class DofIndexing{
-	
-	public:
-
-		/*sizes: */
-		int gsize; //number of dofs for a node
-		int fsize; //number of dofs solver for
-		int ssize; //number of constrained dofs
-
-		/*partitioning: */
-		int     clone;   //this node is replicated from another one 
-
-		/*boundary conditions sets: */
-		bool*     f_set; //is dof on f-set (on which we solve)
-		bool*     s_set; //is dof on s-set (on which boundary conditions -dirichlet- are applied)
-		IssmDouble*   svalues; //list of constraint values. size g_size, for ease of use.
-
-		/*types of dofs: */
-		int*     doftype; //approximation type of the dofs (used only for coupling), size g_size
-		
-		/*list of degrees of freedom: */
-		int*     gdoflist; //dof list in g_set
-		int*     fdoflist; //dof list in f_set
-		int*     sdoflist; //dof list in s_set
-
-
-		/*DofIndexing constructors, destructors {{{*/
-		DofIndexing();
-		DofIndexing(int g_size);
-		void Init(int g_size,int* doftype);
-		void InitSet(int setenum);
-		DofIndexing(DofIndexing* properties);
-		~DofIndexing();
-		/*}}}*/
-		/*Object like functionality: {{{*/
-		void  Echo(void); 
-		void  DeepEcho(void); 
-		void  copy(DofIndexing* properties);
-		/*}}}*/
-		/*DofIndexing management: {{{*/
-		DofIndexing* Spawn(int* indices, int numindices);
-		/*}}}*/
-
-};
-#endif //ifndef _DOFINDEXING_H_
Index: sm/trunk-jpl/src/c/objects/FemModel.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/FemModel.cpp	(revision 12820)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*!\file FemModel.c
- * \brief: implementation of the FemModel object
- */
-
-
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include "../Container/Container.h"
-#include "../modules/ModelProcessorx/ModelProcessorx.h"
-#include "../io/io.h"
-#include "./objects.h"
-#include "../include/include.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../modules/modules.h"
-
-/*Object constructors and destructor*/
-/*FUNCTION FemModel::constructor {{{*/
-FemModel::FemModel(char* inputfilename, char* outputfilename, const int in_solution_type,const int* analyses,const int nummodels){
-
-	/*intermediary*/
-	int         i;
-	int         analysis_type;
-	FILE       *IOMODEL = NULL;
-	extern int  my_rank;
-
-	/*Open input file on cpu 0: */
-	if(my_rank==0) IOMODEL = pfopen(inputfilename ,"rb");
-
-	/*Initialize internal data: */
-	this->nummodels=nummodels;
-	this->solution_type=in_solution_type;
-	this->analysis_counter=nummodels-1; //point to last analysis_type carried out.
-	this->results=new Results(); //not initialized by CreateDataSets
-	
-	/*Dynamically allocate whatever is a list of length nummodels: */
-	analysis_type_list=xNew<int>(nummodels);
-
-	/*Initialize: */
-	for(i=0;i<nummodels;i++)analysis_type_list[i]=analyses[i];
-
-	/*create datasets for all analyses*/
-	ModelProcessorx(&this->elements,&this->nodes,&this->vertices,&this->materials,&this->constraints,&this->loads,&this->parameters,IOMODEL,this->solution_type,nummodels,analyses);
-
-	/*do the post-processing of the datasets to get an FemModel that can actually run analyses: */
-	for(i=0;i<nummodels;i++){
-
-		if(VerboseMProcessor()) _pprintLine_("   Processing finite element model of analysis " << EnumToStringx(analysis_type_list[i]) << ":");
-		analysis_type=analysis_type_list[i];
-		this->SetCurrentConfiguration(analysis_type);
-	
-		if(i==0){
-			if(VerboseMProcessor()) _pprintLine_("      creating vertex degrees of freedom");
-			VerticesDofx(vertices,parameters); //only call once, we only have one set of vertices
-		}
-
-		if(VerboseMProcessor()) _pprintLine_("      resolving node constraints");
-		SpcNodesx(nodes,constraints,parameters,analysis_type); 
-
-		if(VerboseMProcessor()) _pprintLine_("      creating nodal degrees of freedom");
-		NodesDofx(nodes,parameters,analysis_type);
-	
-		if(VerboseMProcessor()) _pprintLine_("      configuring element and loads");
-		ConfigureObjectsx(elements, loads, nodes, vertices, materials,parameters);
-	}
-	
-	/*Close input file descriptors: */
-	if(my_rank==0) pfclose(IOMODEL,inputfilename);
-
-	/*Add output file name to parameters: */
-	this->parameters->AddObject(new StringParam(OutputfilenameEnum,outputfilename));
-
-}
-
-/*}}}*/
-/*FUNCTION FemModel::destructor {{{*/
-FemModel::~FemModel(){
-
-	/*Intermediary*/
-	int i;
-
-	/*Delete all the datasets: */
-	xDelete<int>(analysis_type_list);
-	delete elements;
-	delete nodes;
-	delete vertices;
-	delete constraints;
-	delete loads;
-	delete materials;
-	delete parameters;
-	delete results;
-
-}
-/*}}}*/
-
-/*Object management*/
-/*FUNCTION FemModel::Echo {{{*/
-void FemModel::Echo(void){
-
-	_printLine_("FemModel echo: ");
-	_printLine_("   number of fem models: " << nummodels);
-	_printLine_("   analysis_type_list: ");
-	for(int i=0;i<nummodels;i++)_printLine_("     " << i << ": " << EnumToStringx(analysis_type_list[i]));
-	_printLine_("   current analysis_type: ");
-	_printLine_("     " << analysis_counter << ": " << EnumToStringx(analysis_type_list[analysis_counter]));
-
-}
-/*}}}*/
-
-/*Numerics: */
-/*FUNCTION FemModel::SetCurrentConfiguration(int configuration_type,int analysis_type){{{*/
-void FemModel::SetCurrentConfiguration(int configuration_type,int analysis_type){
-
-	/*Use configuration_type to setup the analysis counter, the configurations of objects etc ... but use 
-	 * analysis_type to drive the element numerics. This allows for use of 1 configuration_type for several 
-	 * analyses. For example: do a SurfaceSlopeX, SurfaceSlopeY, BedSlopeX and BedSlopeY analysis using the 
-	 * Slope configuration.*/
-
-	int found=-1;
-	for(int i=0;i<nummodels;i++){
-		if (analysis_type_list[i]==configuration_type){
-			found=i;
-			break;
-		}
-	}
-	if(found!=-1) analysis_counter=found;
-	else _error2_("Could not find alias for analysis_type " << EnumToStringx(configuration_type) << " in list of FemModel analyses");
-
-	/*Now, plug analysis_counter and analysis_type inside the parameters: */
-	this->parameters->SetParam(analysis_counter,AnalysisCounterEnum);
-	this->parameters->SetParam(analysis_type,AnalysisTypeEnum);
-	this->parameters->SetParam(configuration_type,ConfigurationTypeEnum);
-
-	/*configure elements, loads and nodes, for this new analysis: */
-	this->elements->SetCurrentConfiguration(elements,loads, nodes,vertices, materials,parameters);
-	this->nodes->SetCurrentConfiguration(elements,loads, nodes,vertices, materials,parameters);
-	this->loads->SetCurrentConfiguration(elements, loads, nodes,vertices, materials,parameters);
-
-	#ifdef _HAVE_PETSC_
-	/*take care of petsc options, that depend on this analysis type (present only after model processor)*/
-	if(this->parameters->Exist(PetscOptionsStringsEnum)){
-		PetscOptionsFromAnalysis(this->parameters,analysis_type);
-		if(VerboseSolver()) _pprintLine_("      petsc Options set for analysis type: " << EnumToStringx(analysis_type));
-	}
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION FemModel::SetCurrentConfiguration(int configuration_type){{{*/
-void FemModel::SetCurrentConfiguration(int configuration_type){
-
-	/*overload: analysis_type = configuration_type: */
-	this->SetCurrentConfiguration(configuration_type,configuration_type);
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/FemModel.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/FemModel.h	(revision 12820)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * FemModel.h: 
- */
-
-#ifndef _FEMMODEL_H_
-#define _FEMMODEL_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-#include "../toolkits/toolkits.h"
-class DataSet;
-class Parameters;
-class NodeSets;
-/*}}}*/
-
-
-class FemModel {
-
-	/*no private members, as we need access to these datasets quite often!:*/
-
-	public:
-
-		int                 nummodels;
-		int                 solution_type;
-		int*                analysis_type_list; //list of analyses this femmodel is going to carry out
-		int                 analysis_counter; //counter into analysis_type_list
-		
-		Elements*           elements; //elements (one set for all analyses)
-		Nodes*              nodes; //one set of nodes
-		Vertices*           vertices; //one set of vertices
-		Constraints*        constraints; //one set of constraints. each constraint knows which analysis_type it handles
-		Loads*              loads;  //one set of constraints. each constraint knows which analysis_type it handles
-		Materials*          materials;  //one set of materials, for each element
-		Parameters*         parameters; //one set of parameters, independent of the analysis_type
-		Results*            results; //results that cannot be fit into the elements (such as one time constants, arrays, strings, etc ...)
-
-		/*constructors, destructors: */
-		FemModel(char* inputfilename, char* outputfilename, const int solution_type,const int* analyses,const int nummodels);
-		~FemModel();
-
-		/*Methods: */
-		void Echo();
-
-		/*Fem: */
-		void  SetCurrentConfiguration(int configuration_type);
-		void  SetCurrentConfiguration(int configuration_type,int analysis_type);
-
-};
-
-#endif
Index: sm/trunk-jpl/src/c/objects/Hook.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Hook.cpp	(revision 12820)
+++ 	(revision )
@@ -1,266 +1,0 @@
-/*!\file Hook.cpp
- * \brief: implementation of the Hook object: see Hook.h for more explanations.
- */
-
-
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "./objects.h"
-#include "../Container/Container.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../include/include.h"
-
-
-/*Constructor/Destructors*/
-/*FUNCTION Hook::Hook(){{{*/
-Hook::Hook(){
-	this->num=0;
-	this->objects=NULL;
-	this->ids=NULL;
-	this->offsets=NULL;
-	return;
-}
-/*}}}*/
-/*FUNCTION Hook::Hook(int* ids, int num){{{*/
-Hook::Hook(int* in_ids, int in_num){
-
-	/*Intermediaries*/
-	int i;
-
-	/*Get number of objects to hook*/
-	this->num=in_num;
-
-	/*Get out if num=0*/
-	if (num==0){
-		/*Empty hook*/
-		this->ids=NULL;
-		this->objects=NULL;
-		this->offsets=NULL;
-	}
-	else{
-		/*Allocate: */
-		this->objects=xNew<Object*>(this->num);
-		this->ids=xNew<int>(this->num);
-		this->offsets=xNew<int>(this->num);
-
-		/*Copy ids: */
-		for (i=0;i<this->num;i++){
-			this->ids[i]=in_ids[i];
-			this->objects[i]=NULL;
-			this->offsets[i]=0;
-		}
-	}
-}
-/*}}}*/
-/*FUNCTION Hook::~Hook(){{{*/
-Hook::~Hook(){
-	/*deallocate: */
-	xDelete<Object*>(this->objects);
-	xDelete<int>(this->ids);
-	xDelete<int>(this->offsets);
-	return;
-}
-/*}}}*/
-
-/*Some of the Object functionality: */
-/*FUNCTION Hook::Echo{{{*/
-void Hook::Echo(void){
-
-	int i;
-	if (num){
-		_printLine_("   Hook: ");
-		_printLine_("      num=" << this->num);
-		_printString_("      ids: ");
-		for (i=0;i<this->num;i++) _printString_(this->ids[i] << " ");
-		_printLine_("");
-		_printString_("      offsets: ");
-		for (i=0;i<this->num;i++) _printString_(this->offsets[i] << " ");
-		_printLine_("");
-	}
-	else{
-		_printLine_("   Hook: num=0 ");
-	}
-}
-/*}}}*/
-/*FUNCTION Hook::DeepEcho{{{*/
-void Hook::DeepEcho(void){
-
-	int i;
-	if (num){
-		_printLine_("   Hook: ");
-		_printLine_("      num=" << this->num);
-		_printString_("      ids: ");
-		for (i=0;i<this->num;i++) _printString_(this->ids[i] << " ");
-		_printLine_("");
-		_printString_("      offsets: ");
-		for (i=0;i<this->num;i++) _printString_(this->offsets[i] << " ");
-		_printLine_("");
-		if (!objects) _printLine_("      warning: object not hooked yet");
-		else{
-			_printString_("      objects:\n   ");
-			for (i=0;i<this->num;i++){
-				_printLine_("         object " << i);
-				if(objects[i]) objects[i]->DeepEcho();
-				else           _printLine_("            no object hooked yet (not configured)");
-			}
-		}
-	}
-	else{
-		_printLine_("   Hook: num=0 ");
-	}
-}
-/*}}}*/
-/*FUNCTION Hook::copy {{{*/
-Object* Hook::copy(void){
-
-	int i;
-
-	/*output: */
-	Hook* output=NULL;
-
-	/*initalize output: */
-	output=new Hook();
-
-	/*copy in the fields: */
-	output->num=this->num;
-	if(output->num){
-		output->objects=xNew<Object*>(output->num);
-		output->ids=xNew<int>(output->num);
-		output->offsets=xNew<int>(output->num);
-	}
-	
-	for(i=0;i<output->num;i++){
-		output->objects[i]=this->objects[i];
-		output->offsets[i]=this->offsets[i];
-		output->ids[i]=this->ids[i];
-	}
-
-	return (Object*)output;
-}
-/*}}}*/
-
-/*Hook management: */
-/*FUNCTION Hook::configure{{{*/
-void Hook::configure(DataSet* dataset){
-
-	/*intermediary: */
-	Object* object=NULL;
-	int i;
-
-	/*Checks if debugging mode*/
-	_assert_(this->num==0 || this->ids!=NULL);
-
-	for(i=0;i<this->num;i++){
-
-		/*is this object id -1? If so, drop this search, it was not requested: */
-		if (this->ids[i]==-1) continue;
-
-		/*Check whether existing this->objects are correct: */
-		if(this->objects[i]){
-			if(this->objects[i]->Id()==this->ids[i]) continue; //this node is good.
-			else this->objects[i]=NULL; //this node was incorrect, reset it.
-		}
-
-		/*May be the object this->offsets into this->objects are valid?: */
-		if(this->offsets[i]!=UNDEF){
-			/* Look at the this->offsets[i]'th node in the nodes dataset. If it has the correct id, 
-			 * we are good: */
-			object=(Object*)dataset->GetObjectByOffset(this->offsets[i]);
-			if (object->Id()==this->ids[i]){
-				this->objects[i]=object;
-				continue;
-			}
-			else this->offsets[i]=UNDEF; //object offset was wrong, reset it.
-		}
-
-		/*Now, for this->objects that did not get resolved, and for which we have no offset, chase them in the dataset, by id: */
-		if(this->objects[i]==NULL){
-			this->objects[i]=(Object*)dataset->GetObjectById(this->offsets+i,this->ids[i]); //remember the offset for later on.
-			/*check the id is correct!: */
-			if (this->objects[i]->Id()!=this->ids[i]) _error2_("wrong id: " << this->objects[i]->Id() << " vs " << this->ids[i] << "  in resolved pointer!");
-		}
-	}
-}
-/*}}}*/
-/*FUNCTION Hook::delivers{{{*/
-Object* Hook::delivers(void){
-	
-	/*first, check that we only have one T object in our object list: */
-	if (this->num!=1) _error2_("trying to delivery a single hook object when hook holds " << this->num << " objects" << "\n");
-
-	/*check NULL: */
-	if (this->objects==NULL) _error2_("hook is not pointing to any object, objects pointer is NULL");
-
-	return *objects;
-}
-
-/*}}}*/
-/*FUNCTION Hook::deliverp{{{*/
-Object** Hook::deliverp(void){
-	return objects;
-}
-/*}}}*/
-/*FUNCTION Hook::Ids{{{*/
-int* Hook::Ids(void){
-	return this->ids;
-}
-/*}}}*/
-/*FUNCTION Hook::GetNum{{{*/
-int Hook::GetNum(void){
-	return this->num;
-}
-/*}}}*/
-/*FUNCTION Hook::GetObjects{{{*/
-Object** Hook::GetObjects(void){
-	return this->objects;
-}
-/*}}}*/
-/*FUNCTION Hook::GetOffsets{{{*/
-int* Hook::GetOffsets(void){
-	return this->offsets;
-}
-/*}}}*/
-/*FUNCTION Hook::Spawn{{{*/
-Hook* Hook::Spawn(int* indices, int numindices){
-
-	int i;
-
-	/*output: */
-	Hook* output=NULL;
-
-	/*allocate: */
-	output=new Hook();
-
-	/*If this Hook is empty, simply return*/
-	if(this->num==0){
-		output->num=0;
-		return output;
-	}
-
-	/*Else, check that we are requesting a half of num*/
-	if (numindices>this->num) _error2_("Cannot spawn hook with " << numindices << " objects from a Hook of " << this->num << " objects");
-
-	/*go pickup the correct objects, ids and offsets :*/
-	output->num=numindices;
-	if(output->num<1) _error2_("Trying to spawn an empty ElementProperties!");
-
-	output->objects=xNew<Object*>(output->num);
-	output->ids=xNew<int>(output->num);
-	output->offsets=xNew<int>(output->num);
-
-	for(i=0;i<output->num;i++){
-		output->objects[i]=this->objects[indices[i]];
-		output->ids[i]=this->ids[indices[i]];
-		output->offsets[i]=this->offsets[indices[i]];
-	}
-
-	return output;
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Hook.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Hook.h	(revision 12820)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*!\file Hook.h
- * \brief: header file for hook object.
- * A hook is a class  that can store the id, offset, and object corresponding to this id and offset into a dataset.
- * For example, an element has a hook to its nodes. A node has a hook to its vertex.  The hook abstracts the need for having
- * ids and offsets (necesarry for proper configuration of an object) in our objects. 
- */
-
-#ifndef _HOOK_H_
-#define _HOOK_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-class DataSet;
-/*}}}*/
-
-class Hook{
-
-	private: 
-
-		int	   num; //number of objects being hooked onto
-		Object**	   objects; //list of object pointers. we do not allocate objects, just a list a pointers, that will get to point to the real objects from a dataset.
-		int*   ids;     //list of object ids, to go look for them in datasets.
-		int*   offsets;  //list of object offsets into datasets, to speed up lookup.
-
-	public:
-
-		/*Hook constructors, destructors: {{{*/
-		Hook();
-		Hook(int* ids, int num);
-		~Hook();
-		/*}}}*/
-		/*Object like functionality:{{{*/
-		void       Echo(void);
-		void       DeepEcho(void);
-		Object*    copy(void);
-		/*}}}*/
-		/*Hook management: {{{*/
-		Object*    delivers(void); //single object deliver
-		Object**   deliverp(void); //deliver all objects
-		void       configure(DataSet* dataset);
-		Hook*      Spawn(int* indices, int numindices);
-		Object**   GetObjects(void);
-		int*       Ids(void);
-		int*       GetOffsets(void);
-		int        GetNum(void);
-		/*}}}*/
-};
-
-#endif  /* _HOOK_H_ */
Index: sm/trunk-jpl/src/c/objects/Node.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Node.cpp	(revision 12820)
+++ 	(revision )
@@ -1,1012 +1,0 @@
-/*!\file Node.c
- * \brief: implementation of the Node object
- */
-
-/*Include files: {{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "./objects.h"
-#include "../Container/Container.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../include/include.h"
-#include "../modules/modules.h"
-/*}}}*/
-
-/*Node constructors and destructors:*/
-/*FUNCTION Node::Node() default constructor {{{*/
-Node::Node(){
-		 this->inputs=NULL;
-		 this->hvertex=NULL;
-		 return;
-}
-/*}}}*/
-/*FUNCTION Node::Node(int node_id,int node_sid,int vertex_id,int io_index, IoModel* iomodel,int analysis_type) {{{*/
-Node::Node(int node_id,int node_sid,int vertex_id,int io_index, IoModel* iomodel,int analysis_type){
-
-	/*Intermediary*/
-	int k,l;
-	int gsize;
-	int dim;
-
-	/*Fetch parameters: */
-	iomodel->Constant(&dim,MeshDimensionEnum);
-
-	/*id: */
-	this->id=node_id; 
-	this->sid=node_sid; 
-	this->analysis_type=analysis_type;
-
-	/*Initialize coord_system: Identity matrix by default*/
-	for(k=0;k<3;k++) for(l=0;l<3;l++) this->coord_system[k][l]=0.0;
-	for(k=0;k<3;k++) this->coord_system[k][k]=1.0;
-
-	/*indexing:*/
-	DistributeNumDofs(&this->indexing,analysis_type,iomodel->Data(FlowequationVertexEquationEnum)+io_index); //number of dofs per node
-	gsize=this->indexing.gsize;
-
-	/*Hooks*/
-	this->hvertex=new Hook(&vertex_id,1); //node id is the same as the vertex id, continuous galerkin!
-
-	//intialize inputs, and add as many inputs per element as requested: 
-	this->inputs=new Inputs();
-	if (iomodel->Data(MeshVertexonbedEnum))
-	 this->inputs->AddInput(new BoolInput(MeshVertexonbedEnum,reCast<IssmBool>(iomodel->Data(MeshVertexonbedEnum)[io_index])));
-	if (iomodel->Data(MeshVertexonsurfaceEnum))
-	 this->inputs->AddInput(new BoolInput(MeshVertexonsurfaceEnum,reCast<IssmBool>(iomodel->Data(MeshVertexonsurfaceEnum)[io_index])));
-	if (iomodel->Data(MaskVertexonfloatingiceEnum))
-	 this->inputs->AddInput(new BoolInput(MaskVertexonfloatingiceEnum,reCast<IssmBool>(iomodel->Data(MaskVertexonfloatingiceEnum)[io_index])));
-	if (iomodel->Data(MaskVertexongroundediceEnum))
-	  this->inputs->AddInput(new BoolInput(MaskVertexongroundediceEnum,reCast<IssmBool>(iomodel->Data(MaskVertexongroundediceEnum)[io_index])));
-	if (analysis_type==DiagnosticHorizAnalysisEnum)
-	 this->inputs->AddInput(new IntInput(ApproximationEnum,reCast<IssmInt>(iomodel->Data(FlowequationVertexEquationEnum)[io_index])));
-	/*set single point constraints: */
-
-	/*spc all nodes on water*/
-	if (!iomodel->Data(MaskVertexonwaterEnum)) _error2_("iomodel->nodeonwater is NULL");
-	if (reCast<IssmBool>(iomodel->Data(MaskVertexonwaterEnum)[io_index])){
-		for(k=1;k<=gsize;k++){
-			this->FreezeDof(k);
-		}
-	}
-
-	/*Diagnostic Horiz*/
-	#ifdef _HAVE_DIAGNOSTIC_
-	if (analysis_type==DiagnosticHorizAnalysisEnum){
-
-		/*Coordinate system provided, convert to coord_system matrix*/
-		_assert_(iomodel->Data(DiagnosticReferentialEnum)); 
-		XZvectorsToCoordinateSystem(&this->coord_system[0][0],iomodel->Data(DiagnosticReferentialEnum)+io_index*6);
-
-		if (dim==3){
-			/*We have a  3d mesh, we may have collapsed elements, hence dead nodes. Freeze them out: */
-			_assert_(iomodel->Data(MeshVertexonbedEnum)); 
-			_assert_(iomodel->Data(FlowequationVertexEquationEnum));
-			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealApproximationEnum && !iomodel->Data(MeshVertexonbedEnum)[io_index]){
-				for(k=1;k<=gsize;k++) this->FreezeDof(k);
-			}
-			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealPattynApproximationEnum && iomodel->Data(FlowequationBordermacayealEnum)[io_index]){
-				if(!iomodel->Data(MeshVertexonbedEnum)[io_index]){
-					for(k=1;k<=gsize;k++) this->FreezeDof(k);
-				}
-			}
-			if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==MacAyealStokesApproximationEnum && iomodel->Data(FlowequationBordermacayealEnum)[io_index]){
-				if(!iomodel->Data(MeshVertexonbedEnum)[io_index]){
-					for(k=1;k<=2;k++) this->FreezeDof(k);
-				}
-			}
-		}
-		/*spc all nodes on hutter*/
-		if (iomodel->Data(FlowequationVertexEquationEnum)[io_index]==HutterApproximationEnum){
-			for(k=1;k<=gsize;k++){
-				this->FreezeDof(k);
-			}
-		}
-	}
-	#endif
-
-	/*Diagnostic Hutter*/
-	if (analysis_type==DiagnosticHutterAnalysisEnum){
-		if (!iomodel->Data(FlowequationVertexEquationEnum)) _error2_("iomodel->vertices_type is NULL");
-		/*Constrain all nodes that are not Hutter*/
-		if (reCast<int>(iomodel->Data(FlowequationVertexEquationEnum)[io_index])!=HutterApproximationEnum){
-			for(k=1;k<=gsize;k++){
-				this->FreezeDof(k);
-			}
-		}
-	}
-
-	/*Prognostic/ Melting/ Slopecompute/ Balancethickness*/
-	if (
-				analysis_type==PrognosticAnalysisEnum || 
-				analysis_type==MeltingAnalysisEnum || 
-				analysis_type==BedSlopeAnalysisEnum || 
-				analysis_type==SurfaceSlopeAnalysisEnum || 
-				analysis_type==BalancethicknessAnalysisEnum
-				){
-		if (dim==3){
-			/*On a 3d mesh, we may have collapsed elements, hence dead nodes. Freeze them out: */
-			_assert_(iomodel->Data(MeshVertexonbedEnum));
-			if (!(reCast<IssmBool>(iomodel->Data(MeshVertexonbedEnum)[io_index]))){
-				for(k=1;k<=gsize;k++){
-					this->FreezeDof(k);
-				}
-			}
-		}
-	}
-
-}
-/*}}}*/
-/*FUNCTION Node::~Node(){{{*/
-Node::~Node(){
-	delete inputs;
-	delete hvertex;
-	return;
-}
-/*}}}*/
-
-/*Object virtual functions definitions:*/
-/*FUNCTION Node::Echo{{{*/
-void Node::Echo(void){
-
-	_printLine_("Node:");
-	_printLine_("   id: " << id);
-	_printLine_("   sid: " << sid);
-	_printLine_("   analysis_type: " << EnumToStringx(analysis_type));
-	indexing.Echo();
-	_printLine_("   hvertex:     not displayed");
-	_printLine_("   inputs:      " << inputs);
-
-
-}
-/*}}}*/
-/*FUNCTION Node::DeepEcho{{{*/
-void Node::DeepEcho(void){
-
-	_printLine_("Node:");
-	_printLine_("   id: " << id);
-	_printLine_("   sid: " << sid);
-	_printLine_("   analysis_type: " << EnumToStringx(analysis_type));
-	indexing.DeepEcho();
-	_printLine_("Vertex:");
-	hvertex->DeepEcho();
-	_printLine_("   inputs");
-
-
-}
-/*}}}*/
-/*FUNCTION Node::Id{{{*/
-int    Node::Id(void){ return id; }
-/*}}}*/
-/*FUNCTION Node::MyRank{{{*/
-int    Node::MyRank(void){ 
-	extern int my_rank;
-
-	return my_rank; 
-}
-/*}}}*/
-/*FUNCTION Node::ObjectEnum{{{*/
-int Node::ObjectEnum(void){
-
-	return NodeEnum;
-
-}
-/*}}}*/
-
-/*Node management:*/
-/*FUNCTION Node::Configure {{{*/
-void  Node::Configure(DataSet* nodesin,Vertices* verticesin){
-
-	int i;
-
-	/*Take care of hooking up all objects for this element, ie links the objects in the hooks to their respective 
-	 * datasets, using internal ids and off_sets hidden in hooks: */
-	hvertex->configure(verticesin);
-
-}
-/*FUNCTION Node::SetCurrentConfiguration {{{*/
-void  Node::SetCurrentConfiguration(DataSet* nodesin,Vertices* verticesin){
-
-}
-/*FUNCTION Node::GetDof {{{*/
-int   Node::GetDof(int dofindex,int setenum){
-
-	if(setenum==GsetEnum){
-		_assert_(dofindex>=0 && dofindex<indexing.gsize);
-		return indexing.gdoflist[dofindex];
-	}
-	else if(setenum==FsetEnum){
-		_assert_(dofindex>=0 && dofindex<indexing.fsize);
-		return indexing.fdoflist[dofindex];
-	}
-	else if(setenum==SsetEnum){
-		_assert_(dofindex>=0 && dofindex<indexing.ssize);
-		return indexing.sdoflist[dofindex];
-	}
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-
-}
-/*}}}*/
-/*FUNCTION Node::GetDofList1{{{*/
-int  Node::GetDofList1(void){
-
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)this->hvertex->delivers();
-
-	return vertex->dof;
-}
-/*}}}*/
-/*FUNCTION Node::GetDofList{{{*/
-void  Node::GetDofList(int* outdoflist,int approximation_enum,int setenum){
-	int i;
-	int count=0;
-	int count2=0;
-		
-	if(approximation_enum==NoneApproximationEnum){
-		if(setenum==GsetEnum)for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=indexing.gdoflist[i];
-		if(setenum==FsetEnum)for(i=0;i<this->indexing.fsize;i++) outdoflist[i]=indexing.fdoflist[i];
-		if(setenum==SsetEnum)for(i=0;i<this->indexing.ssize;i++) outdoflist[i]=indexing.sdoflist[i];
-	}
-	else{
-
-		if(setenum==GsetEnum){
-			if(indexing.doftype){
-				count=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.doftype[i]==approximation_enum){
-						outdoflist[count]=indexing.gdoflist[i];
-						count++;
-					}
-				}
-				_assert_(count); //at least one dof should be the approximation requested
-			}
-			else for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=indexing.gdoflist[i];
-		}
-		else if(setenum==FsetEnum){
-			if(indexing.doftype){
-				count=0;
-				count2=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.f_set[i]){
-						if(indexing.doftype[i]==approximation_enum){
-							outdoflist[count]=indexing.fdoflist[count2];
-							count++;
-						}
-						count2++;
-					}
-				}
-			}
-			else for(i=0;i<this->indexing.fsize;i++) outdoflist[i]=indexing.fdoflist[i];
-		}
-		else if(setenum==SsetEnum){
-			if(indexing.doftype){
-				count=0;
-				count2=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.s_set[i]){
-						if(indexing.doftype[i]==approximation_enum){
-							outdoflist[count]=indexing.sdoflist[count2];
-							count++;
-						}
-						count2++;
-					}
-				}
-			}
-			else for(i=0;i<this->indexing.ssize;i++) outdoflist[i]=indexing.sdoflist[i];
-		}
-		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-	}
-}
-/*}}}*/
-/*FUNCTION Node::GetSidList{{{*/
-int  Node::GetSidList(void){
-
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)this->hvertex->delivers();
-
-	return vertex->sid;
-}
-/*}}}*/
-/*FUNCTION Node::GetLocalDofList{{{*/
-void  Node::GetLocalDofList(int* outdoflist,int approximation_enum,int setenum){
-	int i;
-	int count=0;
-	int count2=0;
-		
-	if(approximation_enum==NoneApproximationEnum){
-		if(setenum==GsetEnum)for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=i;
-		else if(setenum==FsetEnum){
-			count=0;
-			for(i=0;i<this->indexing.gsize;i++){
-				if(indexing.f_set[i]){
-					outdoflist[count]=i;
-					count++;
-				}
-			}
-		}
-		else if(setenum==SsetEnum){
-			count=0;
-			for(i=0;i<this->indexing.gsize;i++){
-				if(indexing.s_set[i]){
-					outdoflist[count]=i;
-					count++;
-				}
-			}
-		}
-		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-	}
-	else{
-
-		if(setenum==GsetEnum){
-			if(indexing.doftype){
-				count=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.doftype[i]==approximation_enum){
-						outdoflist[count]=count;
-						count++;
-					}
-				}
-				_assert_(count);
-			}
-			else for(i=0;i<this->indexing.gsize;i++) outdoflist[i]=i;
-		}
-		else if(setenum==FsetEnum){
-
-			if(indexing.doftype){
-				count=0;
-				count2=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.doftype[i]==approximation_enum){
-						if(indexing.f_set[i]){
-							outdoflist[count]=count2;
-							count++;
-						}
-						count2++;
-					}
-				}
-				_assert_(count2);
-			}
-			else{
-
-				count=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.f_set[i]){
-						outdoflist[count]=i;
-						count++;
-					}
-				}
-			}
-		}
-		else if(setenum==SsetEnum){
-			if(indexing.doftype){
-				count=0;
-				count2=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.doftype[i]==approximation_enum){
-						if(indexing.s_set[i]){
-							outdoflist[count]=count2;
-							count++;
-						}
-						count2++;
-					}
-				}
-				_assert_(count2);
-			}
-			else{
-				count=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(indexing.s_set[i]){
-						outdoflist[count]=i;
-						count++;
-					}
-				}
-			}
-		}
-		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-	}
-}
-/*}}}*/
-/*FUNCTION Node::Sid{{{*/
-int    Node::Sid(void){ return sid; }
-/*}}}*/
-/*FUNCTION Node::GetVertexId {{{*/
-int   Node::GetVertexId(void){
-
-	Vertex*  vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->id;
-}
-/*}}}*/
-/*FUNCTION Node::GetVertexDof {{{*/
-int   Node::GetVertexDof(void){
-
-	Vertex*  vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->dof;
-}
-/*}}}*/
-#ifdef _HAVE_DIAGNOSTIC_
-/*FUNCTION Node::GetCoordinateSystem{{{*/
-void Node::GetCoordinateSystem(IssmDouble* coord_system_out){
-
-	/*Copy coord_system*/
-	for(int k=0;k<3;k++) for(int l=0;l<3;l++) coord_system_out[3*k+l]=this->coord_system[k][l];
-
-}
-/*}}}*/
-#endif
-/*FUNCTION Node::SetVertexDof {{{*/
-void   Node::SetVertexDof(int in_dof){
-
-	Vertex*  vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	vertex->dof=in_dof;
-
-}
-/*}}}*/
-/*FUNCTION Node::InAnalysis{{{*/
-bool Node::InAnalysis(int in_analysis_type){
-	if (in_analysis_type==this->analysis_type) return true;
-	else return false;
-}
-/*}}}*/
-
-/*Node numerics:*/
-/*FUNCTION Node::ApplyConstraints{{{*/
-void  Node::ApplyConstraint(int dof,IssmDouble value){
-
-	int index;
-
-	/*Dof should be added in the s set, describing which 
-	 * dofs are constrained to a certain value (dirichlet boundary condition*/
-	DofInSSet(dof-1);
-	this->indexing.svalues[dof-1]=value;
-}
-/*}}}*/
-/*FUNCTION Node::RelaxConstraint{{{*/
-void  Node::RelaxConstraint(int dof){
-
-	/*Dof should be added to the f-set, and taken out of the s-set:*/
-	DofInFSet(dof-1);
-	this->indexing.svalues[dof-1]=NAN;
-}
-/*}}}*/
-/*FUNCTION Node::CreateVecSets {{{*/
-void  Node::CreateVecSets(Vector* pv_g,Vector* pv_f,Vector* pv_s){
-
-	IssmDouble gvalue=1.0; //all nodes are in the g set;
-	IssmDouble value;
-
-	int i;
-
-	for(i=0;i<this->indexing.gsize;i++){
-
-		/*g set: */
-		pv_g->SetValue(indexing.gdoflist[i],gvalue,INS_VAL);
-		
-		/*f set: */
-		value=(IssmDouble)this->indexing.f_set[i];
-		pv_f->SetValue(indexing.gdoflist[i],value,INS_VAL);
-
-		/*s set: */
-		value=(IssmDouble)this->indexing.s_set[i];
-		pv_s->SetValue(indexing.gdoflist[i],value,INS_VAL);
-
-	}
-
-
-}
-/*}}}*/
-/*FUNCTION Node::CreateNodalConstraints{{{*/
-void  Node::CreateNodalConstraints(Vector* ys){
-
-	int i;
-	IssmDouble* values=NULL;
-	int count;
-
-	/*Recover values for s set and plug them in constraints vector: */
-	if(this->indexing.ssize){
-		values=xNew<IssmDouble>(this->indexing.ssize);
-		count=0;
-		for(i=0;i<this->indexing.gsize;i++){
-			if(this->indexing.s_set[i]){
-				values[count]=this->indexing.svalues[i];
-				_assert_(!xIsNan<IssmDouble>(values[count]));
-				count++;
-			}
-		}
-		
-		/*Add values into constraint vector: */
-		ys->SetValues(this->indexing.ssize,this->indexing.sdoflist,values,INS_VAL);
-	}
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(values);
-
-
-}
-/*}}}*/
-/*FUNCTION Node::DofInSSet {{{*/
-void  Node::DofInSSet(int dof){
-
-	/*Put dof for this node into the s set (ie, this dof will be constrained 
-	 * to a fixed value during computations. */
-
-	this->indexing.f_set[dof]=0; //n splits into f (for which we solve) and s (single point constraints)
-	this->indexing.s_set[dof]=1;
-}
-/*}}}*/
-/*FUNCTION Node::DofInFSet {{{*/
-void  Node::DofInFSet(int dof){
-
-	/*Put dof for this node into the f set (ie, this dof will NOT be constrained 
-	 * to a fixed value during computations. */
-
-	this->indexing.f_set[dof]=1; 
-	this->indexing.s_set[dof]=0;
-}
-/*}}}*/
-/*FUNCTION Node::FreezeDof{{{*/
-void  Node::FreezeDof(int dof){
-	
-	DofInSSet(dof-1); //with 0 displacement for this dof.
-
-}
-/*}}}*/
-/*FUNCTION Node::GetApproximation {{{*/
-int   Node::GetApproximation(){
-
-	int approximation;
-
-	/*recover parameters: */
-	inputs->GetInputValue(&approximation,ApproximationEnum);
-
-	return approximation;
-}
-/*}}}*/
-/*FUNCTION Node::GetConnectivity {{{*/
-int Node::GetConnectivity(){
-
-	Vertex*  vertex=NULL;
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->connectivity;
-}
-/*}}}*/
-/*FUNCTION Node::GetNumberOfDofs{{{*/
-int   Node::GetNumberOfDofs(int approximation_enum,int setenum){
-
-	/*Get number of degrees of freedom in a node, for a certain set (g,f or s-set)
-	 *and for a certain approximation type: */
-	
-	int i;
-	int numdofs=0;
-
-	if(approximation_enum==NoneApproximationEnum){
-		if (setenum==GsetEnum) numdofs=this->indexing.gsize;
-		else if (setenum==FsetEnum) numdofs=this->indexing.fsize;
-		else if (setenum==SsetEnum) numdofs=this->indexing.ssize;
-		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-	}
-	else{
-		if(setenum==GsetEnum){
-			if(this->indexing.doftype){
-				numdofs=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if(this->indexing.doftype[i]==approximation_enum) numdofs++;
-				}
-			}
-			else numdofs=this->indexing.gsize;
-		}
-		else if (setenum==FsetEnum){
-			if(this->indexing.doftype){
-				numdofs=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if((this->indexing.doftype[i]==approximation_enum) && (this->indexing.f_set[i])) numdofs++;
-				}
-			}
-			else numdofs=this->indexing.fsize;
-		}
-		else if (setenum==SsetEnum){
-			if(this->indexing.doftype){
-				numdofs=0;
-				for(i=0;i<this->indexing.gsize;i++){
-					if((this->indexing.doftype[i]==approximation_enum) && (this->indexing.s_set[i])) numdofs++;
-				}
-			}
-			else numdofs=this->indexing.ssize;
-		}
-		else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-	}
-	return numdofs;
-}
-/*}}}*/
-/*FUNCTION Node::GetSigma {{{*/
-IssmDouble Node::GetSigma(){
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->sigma;
-}
-/*}}}*/
-/*FUNCTION Node::GetX {{{*/
-IssmDouble Node::GetX(){
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->x;
-}
-/*}}}*/
-/*FUNCTION Node::GetY {{{*/
-IssmDouble Node::GetY(){
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->y;
-}
-/*}}}*/
-/*FUNCTION Node::GetZ {{{*/
-IssmDouble Node::GetZ(){
-	Vertex* vertex=NULL;
-
-	vertex=(Vertex*)hvertex->delivers();
-	return vertex->z;
-}
-/*}}}*/
-/*FUNCTION Node::IsClone {{{*/
-int   Node::IsClone(){
-	
-	return indexing.clone;
-
-}
-/*}}}*/
-/*FUNCTION Node::IsOnBed {{{*/
-int   Node::IsOnBed(){
-
-	bool onbed;
-
-	/*recover parameters: */
-	inputs->GetInputValue(&onbed,MeshVertexonbedEnum);
-
-	return onbed;
-}
-/*}}}*/
-/*FUNCTION Node::IsGrounded {{{*/
-int   Node::IsGrounded(){
-
-	bool onsheet;
-
-	/*recover parameters: */
-	inputs->GetInputValue(&onsheet,MaskVertexongroundediceEnum);
-
-	return onsheet;
-}		
-/*}}}*/
-/*FUNCTION Node::IsFloating {{{*/
-int   Node::IsFloating(){
-	
-	bool onshelf;
-
-	/*recover parameters: */
-	inputs->GetInputValue(&onshelf,MaskVertexonfloatingiceEnum);
-
-	return onshelf;
-}
-/*}}}*/
-/*FUNCTION Node::IsOnSurface {{{*/
-int   Node::IsOnSurface(){
-
-	bool onsurface;
-
-	/*recover parameters: */
-	inputs->GetInputValue(&onsurface,MeshVertexonsurfaceEnum);
-
-	return onsurface;
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVector(IssmDouble* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVector(IssmDouble* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVector(int* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVector(int* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVector(bool* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVector(bool* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){{{*/
-void  Node::InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVectorDakota(int* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVectorDakota(int* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromVectorDakota(bool* vector, int name, int type){{{*/
-void  Node::InputUpdateFromVectorDakota(bool* vector, int name, int type){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromConstant(IssmDouble constant, int name){{{*/
-void  Node::InputUpdateFromConstant(IssmDouble constant, int name){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromConstant(int constant, int name){{{*/
-void  Node::InputUpdateFromConstant(int constant, int name){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::InputUpdateFromConstant(bool constant, int name){{{*/
-void  Node::InputUpdateFromConstant(bool constant, int name){
-
-	/*Nothing updated yet*/
-}
-/*}}}*/
-/*FUNCTION Node::UpdateSpcs {{{*/
-void   Node::UpdateSpcs(IssmDouble* ys){
-
-	int     count=0;
-	int     i;
-
-	count=0;
-	for(i=0;i<this->indexing.gsize;i++){
-		if(this->indexing.s_set[i]){
-			this->indexing.svalues[i]=ys[this->indexing.sdoflist[count]];
-			count++;
-		}
-	}
-}
-/*}}}*/
-/*FUNCTION Node::VecMerge {{{*/
-void   Node::VecMerge(Vector* ug, IssmDouble* vector_serial,int setenum){
-
-	IssmDouble* values=NULL;
-	int*    indices=NULL;
-	int     count=0;
-	int     i;
-
-	if(setenum==FsetEnum){
-		if(this->indexing.fsize){
-			indices=xNew<int>(this->indexing.fsize);
- 			values=xNew<IssmDouble>(this->indexing.fsize);
-
-			for(i=0;i<this->indexing.gsize;i++){
-				if(this->indexing.f_set[i]){
-					_assert_(vector_serial);
-					values[count]=vector_serial[this->indexing.fdoflist[count]];
-					indices[count]=this->indexing.gdoflist[i];
-					count++;
-				}
-			}
-
-			/*Add values into ug: */
-			ug->SetValues(this->indexing.fsize,indices,values,INS_VAL);
-		}
-	}
-	else if(setenum==SsetEnum){
-		if(this->indexing.ssize){
-			indices=xNew<int>(this->indexing.ssize);
-			values=xNew<IssmDouble>(this->indexing.ssize);
-
-			for(i=0;i<this->indexing.gsize;i++){
-				if(this->indexing.s_set[i]){
-					_assert_(vector_serial);
-					values[count]=vector_serial[this->indexing.sdoflist[count]];
-					indices[count]=this->indexing.gdoflist[i];
-					count++;
-				}
-			}
-
-			/*Add values into ug: */
-			ug->SetValues(this->indexing.ssize,indices,values,INS_VAL);
-		}
-	}
-	else _error2_("VecMerge can only merge from the s or f-set onto the g-set!");
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(values);
-	xDelete<int>(indices);
-}
-/*}}}*/
-/*FUNCTION Node::VecReduce {{{*/
-void   Node::VecReduce(Vector* vector, IssmDouble* ug_serial,int setenum){
-
-	IssmDouble* values=NULL;
-	int     count=0;
-	int     i;
-
-	if(setenum==FsetEnum){
-		if(this->indexing.fsize){
- 			values=xNew<IssmDouble>(this->indexing.fsize);
-
-			for(i=0;i<this->indexing.gsize;i++){
-				if(this->indexing.f_set[i]){
-					_assert_(ug_serial);
-					values[count]=ug_serial[this->indexing.gdoflist[i]];
-					count++;
-				}
-			}
-
-			/*Add values into ug: */
-			vector->SetValues(this->indexing.fsize,this->indexing.fdoflist,values,INS_VAL);
-		}
-	}
-	else if(setenum==SsetEnum){
-		if(this->indexing.ssize){
-			values=xNew<IssmDouble>(this->indexing.ssize);
-
-			for(i=0;i<this->indexing.gsize;i++){
-				if(this->indexing.s_set[i]){
-					_assert_(ug_serial);
-					values[count]=ug_serial[this->indexing.gdoflist[i]];
-					count++;
-				}
-			}
-
-			/*Add values into ug: */
-			vector->SetValues(this->indexing.ssize,this->indexing.sdoflist,values,INS_VAL);
-		}
-	}
-	else _error2_("VecReduce can only merge from the s or f-set onto the g-set!");
-
-	/*Free ressources:*/
-	xDelete<IssmDouble>(values);
-}
-/*}}}*/
-
-/* DofObject routines:*/
-/*FUNCTION Node::DistributeDofs{{{*/
-void  Node::DistributeDofs(int* pdofcount,int setenum){
-
-	int i;
-	extern int my_rank;
-	int dofcount;
-
-	dofcount=*pdofcount;
-
-	/*Initialize: */
-	if(setenum==FsetEnum) this->indexing.InitSet(setenum);
-	if(setenum==SsetEnum) this->indexing.InitSet(setenum);
-	
-		
-	/*For clone nodfs, don't distribute dofs, we will get them from another cpu in UpdateCloneDofs!*/
-	if(indexing.clone){
-		return;
-	}
-
-	/*This node should distribute dofs for setenum set (eg, f_set or s_set), go ahead: */
-
-	if(setenum==GsetEnum){
-		for(i=0;i<this->indexing.gsize;i++){
-			indexing.gdoflist[i]=dofcount+i;
-		}
-		dofcount+=this->indexing.gsize;
-	}
-	else if(setenum==FsetEnum){
-		for(i=0;i<this->indexing.fsize;i++){
-			indexing.fdoflist[i]=dofcount+i;
-		}
-		dofcount+=this->indexing.fsize;
-	}
-	else if(setenum==SsetEnum){
-		for(i=0;i<this->indexing.ssize;i++){
-			indexing.sdoflist[i]=dofcount+i;
-		}
-		dofcount+=this->indexing.ssize;
-	}
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-
-
-	/*Assign output pointers: */
-	*pdofcount=dofcount;
-
-}
-/*}}}*/
-/*FUNCTION Node::Off_setDofs{{{*/
-void  Node::OffsetDofs(int dofcount,int setenum){
-	
-	int i;
-	extern int my_rank;
-	
-	if(indexing.clone){
-		/*This node is a clone, don't off_set the dofs!: */
-		return;
-	}
-
-	/*This node should off_set the dofs, go ahead: */
-	if(setenum==GsetEnum){
-		for(i=0;i<this->indexing.gsize;i++) indexing.gdoflist[i]+=dofcount;
-	}
-	else if(setenum==FsetEnum){
-		for(i=0;i<this->indexing.fsize;i++) indexing.fdoflist[i]+=dofcount;
-	}
-	else if(setenum==SsetEnum){
-		for(i=0;i<this->indexing.ssize;i++) indexing.sdoflist[i]+=dofcount;
-	}
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-}
-/*}}}*/
-/*FUNCTION Node::ShowTrueDofs{{{*/
-void  Node::ShowTrueDofs(int* truedofs, int ncols,int setenum){
-
-	int j;
-	extern int my_rank;
-	
-	/*Are we a clone? : */
-	if(indexing.clone)return;
-
-	/*Ok, we are not a clone, just plug our dofs into truedofs: */
-	if(setenum==GsetEnum)for(j=0;j<this->indexing.gsize;j++)  *(truedofs+ncols*sid+j)=indexing.gdoflist[j];
-	else if(setenum==FsetEnum)for(j=0;j<this->indexing.fsize;j++)  *(truedofs+ncols*sid+j)=indexing.fdoflist[j];
-	else if(setenum==SsetEnum)for(j=0;j<this->indexing.ssize;j++)  *(truedofs+ncols*sid+j)=indexing.sdoflist[j];
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-
-}
-/*}}}*/
-/*FUNCTION Node::UpdateCloneDofs{{{*/
-void  Node::UpdateCloneDofs(int* alltruedofs,int ncols,int setenum){
-
-	int j;
-	extern int my_rank;
-	
-	/*If we are not a clone, don't update, we already have dofs!: */
-	if(indexing.clone==0)return;
-
-
-	/*Ok, we are a clone node, but we did not create the dofs for this node.
-	 *      * Therefore, our doflist is garbage right now. Go pick it up in the alltruedofs: */
-	if(setenum==GsetEnum)for(j=0;j<this->indexing.gsize;j++) indexing.gdoflist[j]=*(alltruedofs+ncols*sid+j);
-	else if(setenum==FsetEnum)for(j=0;j<this->indexing.fsize;j++) indexing.fdoflist[j]=*(alltruedofs+ncols*sid+j);
-	else if(setenum==SsetEnum)for(j=0;j<this->indexing.ssize;j++) indexing.sdoflist[j]=*(alltruedofs+ncols*sid+j);
-	else _error2_("set of enum type " << EnumToStringx(setenum) << " not supported yet!");
-
-}
-/*}}}*/
-/*FUNCTION Node::SetClone {{{*/
-void  Node::SetClone(int* minranks){
-
-	extern int my_rank;
-
-	if (minranks[sid]==my_rank){
-		indexing.clone=0;
-	}
-	else{
-		/*!there is a cpu with lower rank that has the same node, 
-		therefore, I am a clone*/
-		indexing.clone=1; 	
-	}
-
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Node.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Node.h	(revision 12820)
+++ 	(revision )
@@ -1,113 +1,0 @@
-/*!\file Node.h
- * \brief: header file for node object
- */
-
-#ifndef _NODE_H_
-#define _NODE_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-#include "../shared/shared.h"
-class  Inputs;
-class  Hook;
-class  DofIndexing;
-class  IoModel;
-class  DataSet;
-class  Vertices;
-class  Vector;
-class  Matrix;
-#include "./Update.h"
-/*}}}*/
-
-class Node: public Object ,public Update{
-
-	public: 
-
-		int	    id;  //unique arbitrary id.
-		int     sid; //sid for "serial" id, ie the rank of this node in the nodes dataset, if the dataset was serial on 1 cpu.
-				
-		DofIndexing    indexing;
-		Hook*          hvertex;
-		Inputs*        inputs; //properties of this node
-		int            analysis_type;
-		IssmDouble         coord_system[3][3];
-
-		/*Node constructors, destructors {{{*/
-		Node();
-		Node(int node_id,int node_sid, int vertex_id,int io_index, IoModel* iomodel,int analysis_type);
-		~Node();
-		/*}}}*/
-		/*Object virtual functions definitions:{{{ */
-		void  Echo();
-		void  DeepEcho();
-		int   Id(); 
-		int   MyRank();
-		int   ObjectEnum();
-		Object* copy(){_error2_("Not implemented yet (similar to Elements)");};
-		/*}}}*/
-		/*Update virtual functions definitions: {{{*/
-		
-		void  InputUpdateFromVector(IssmDouble* vector, int name, int type);
-		void  InputUpdateFromVector(int* vector, int name, int type);
-		void  InputUpdateFromVector(bool* vector, int name, int type);
-		void  InputUpdateFromMatrixDakota(IssmDouble* matrix,int nrows, int ncols, int name, int type);
-		void  InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type);
-		void  InputUpdateFromVectorDakota(int* vector, int name, int type);
-		void  InputUpdateFromVectorDakota(bool* vector, int name, int type);
-		void  InputUpdateFromConstant(IssmDouble constant, int name);
-		void  InputUpdateFromConstant(int constant, int name);
-		void  InputUpdateFromConstant(bool constant, int name);
-		void  InputUpdateFromSolution(IssmDouble* solution){_error2_("Not implemented yet!");}
-		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error2_("Not implemented yet!");}
-		/*}}}*/
-		/*Node numerical routines {{{*/
-		void   Configure(DataSet* nodes,Vertices* vertices);
-		void   CreateNodalConstraints(Vector* ys);
-		void   SetCurrentConfiguration(DataSet* nodes,Vertices* vertices);
-		int    Sid(void); 
-		int    GetVertexDof(void);
-		int    GetVertexId(void);
-#ifdef _HAVE_DIAGNOSTIC_
-		void   GetCoordinateSystem(IssmDouble* coord_system_out);
-#endif
-		void   SetVertexDof(int in_dof);
-		bool   InAnalysis(int analysis_type);
-		int    GetApproximation();
-		int    GetNumberOfDofs(int approximation_enum,int setenum);
-		int    IsClone();
-		void   ApplyConstraint(int dof,IssmDouble value);
-		void   RelaxConstraint(int dof);
-		void   DofInSSet(int dof);
-		void   DofInFSet(int dof);
-		int    GetDof(int dofindex,int setenum);
-		void   CreateVecSets(Vector* pv_g,Vector* pv_f,Vector* pv_s);
-		int    GetConnectivity();
-		void   GetDofList(int* poutdoflist,int approximation_enum,int setenum);
-		void   GetLocalDofList(int* poutdoflist,int approximation_enum,int setenum);
-		int    GetDofList1(void);
-		int    GetSidList(void);
-		IssmDouble GetX();
-		IssmDouble GetY();
-		IssmDouble GetZ();
-		IssmDouble GetSigma();
-		int    IsOnBed();
-		int    IsOnSurface();
-		void   FreezeDof(int dof);
-		int    IsFloating();
-		int    IsGrounded();
-		void   UpdateSpcs(IssmDouble* ys);
-		void   VecMerge(Vector* ug, IssmDouble* vector_serial,int setenum);
-		void   VecReduce(Vector* vector, IssmDouble* ug_serial,int setnum);
-		
-		/*}}}*/
-		/*Dof Object routines {{{*/
-		void  DistributeDofs(int* pdofcount,int setenum);
-		void  OffsetDofs(int dofcount,int setenum);
-		void  ShowTrueDofs(int* truerows,int ncols,int setenum);
-		void  UpdateCloneDofs(int* alltruerows,int ncols,int setenum);
-		void  SetClone(int* minranks);
-		/*}}}*/
-};
-
-#endif  /* _NODE_H_ */
Index: sm/trunk-jpl/src/c/objects/Numerics/ElementMatrix.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/ElementMatrix.cpp	(revision 12820)
+++ 	(revision )
@@ -1,496 +1,0 @@
-/*!\file ElementMatrix.cpp
- * \brief: implementation of the ElementMatrix object, used to plug values from element into global stiffness matrix
- */
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "../objects.h"
-#include "../../shared/shared.h"
-#include "../../Container/Container.h"
-#include "../../include/include.h"
-/*}}}*/
-
-/*ElementMatrix constructors and destructor*/
-/*FUNCTION ElementMatrix::ElementMatrix(){{{*/
-ElementMatrix::ElementMatrix(){
-
-	this->nrows=0;
-	this->ncols=0;
-	this->values=NULL;
-	this->dofsymmetrical=false;
-
-	this->row_fsize=0;
-	this->row_flocaldoflist=NULL;
-	this->row_fglobaldoflist=NULL;
-	this->row_ssize=0;
-	this->row_slocaldoflist=NULL;
-	this->row_sglobaldoflist=NULL;
-
-	this->col_fsize=0;
-	this->col_flocaldoflist=NULL;
-	this->col_fglobaldoflist=NULL;
-	this->col_ssize=0;
-	this->col_slocaldoflist=NULL;
-	this->col_sglobaldoflist=NULL;
-
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke){{{*/
-ElementMatrix::ElementMatrix(ElementMatrix* Ke){
-
-	if(!Ke) _error2_("Input Element Matrix is a NULL pointer");
-	this->Init(Ke);
-	return;
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2){{{*/
-ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2){
-
-	/*intermediaries*/
-	int i,j,counter;
-	int gsize,fsize,ssize;
-	int* P=NULL;
-	bool found;
-
-	/*If one of the two matrix is NULL, we copy the other one*/
-	if(!Ke1 && !Ke2){
-		_error2_("Two input element matrices are NULL");
-	}
-	else if(!Ke1){
-		this->Init(Ke2);
-		return;
-	}
-	else if(!Ke2){
-		this->Init(Ke1);
-		return;
-	}
-
-	/*General Case: Ke1 and Ke2 are not empty*/
-	if(!Ke1->dofsymmetrical || !Ke2->dofsymmetrical) _error2_("merging 2 non dofsymmetrical matrices not implemented yet");
-
-	/*Initialize itransformation matrix Ke[P[i]] = Ke2[i]*/
-	P=xNew<int>(Ke2->nrows);
-
-	/*1: Get the new numbering of Ke2 and get size of the new matrix*/
-	gsize=Ke1->nrows;
-	for(i=0;i<Ke2->nrows;i++){
-		found=false;
-		for(j=0;j<Ke1->nrows;j++){
-			if(Ke2->gglobaldoflist[i]==Ke1->gglobaldoflist[j]){
-				found=true; P[i]=j; break;
-			}
-		}
-		if(!found){
-			P[i]=gsize; gsize++;
-		}
-	}
-
-	/*2: Initialize static fields*/
-	this->nrows=gsize;
-	this->ncols=gsize;
-	this->dofsymmetrical=true;
-
-	/*Gset and values*/
-	this->gglobaldoflist=xNew<int>(this->nrows);
-	this->values=xNewZeroInit<IssmDouble>(this->nrows*this->ncols);
-	for(i=0;i<Ke1->nrows;i++){
-		for(j=0;j<Ke1->ncols;j++){
-			this->values[i*this->ncols+j] += Ke1->values[i*Ke1->ncols+j];
-		}
-		this->gglobaldoflist[i]=Ke1->gglobaldoflist[i];
-	}
-	for(i=0;i<Ke2->nrows;i++){
-		for(j=0;j<Ke2->ncols;j++){
-			this->values[P[i]*this->ncols+P[j]] += Ke2->values[i*Ke2->ncols+j];
-		}
-		this->gglobaldoflist[P[i]]=Ke2->gglobaldoflist[i];
-	}
-
-	/*Fset*/
-	fsize=Ke1->row_fsize;
-	for(i=0;i<Ke2->row_fsize;i++){
-		if(P[Ke2->row_flocaldoflist[i]] >= Ke1->nrows) fsize++;
-	}
-	this->row_fsize=fsize;
-	if(fsize){
-		this->row_flocaldoflist =xNew<int>(fsize);
-		this->row_fglobaldoflist=xNew<int>(fsize);
-		for(i=0;i<Ke1->row_fsize;i++){
-			this->row_flocaldoflist[i] =Ke1->row_flocaldoflist[i];
-			this->row_fglobaldoflist[i]=Ke1->row_fglobaldoflist[i];
-		}
-		counter=Ke1->row_fsize;
-		for(i=0;i<Ke2->row_fsize;i++){
-			if(P[Ke2->row_flocaldoflist[i]] >= Ke1->nrows){
-				this->row_flocaldoflist[counter] =P[Ke2->row_flocaldoflist[i]];
-				this->row_fglobaldoflist[counter]=Ke2->row_fglobaldoflist[i];
-				counter++;
-			}
-		}
-	}
-	else{
-		this->row_flocaldoflist=NULL;
-		this->row_fglobaldoflist=NULL;
-	}
-
-	/*Sset*/
-	ssize=Ke1->row_ssize;
-	for(i=0;i<Ke2->row_ssize;i++){
-		if(P[Ke2->row_slocaldoflist[i]] >= Ke1->nrows) ssize++;
-	}
-	this->row_ssize=ssize;
-	if(ssize){
-		this->row_slocaldoflist =xNew<int>(ssize);
-		this->row_sglobaldoflist=xNew<int>(ssize);
-		for(i=0;i<Ke1->row_ssize;i++){
-			this->row_slocaldoflist[i] =Ke1->row_slocaldoflist[i];
-			this->row_sglobaldoflist[i]=Ke1->row_sglobaldoflist[i];
-		}
-		counter=Ke1->row_ssize;
-		for(i=0;i<Ke2->row_ssize;i++){
-			if(P[Ke2->row_slocaldoflist[i]] >= Ke1->nrows){
-				this->row_slocaldoflist[counter] =P[Ke2->row_slocaldoflist[i]];
-				this->row_sglobaldoflist[counter]=Ke2->row_sglobaldoflist[i];
-				counter++;
-			}
-		}
-	}
-	else{
-		this->row_slocaldoflist=NULL;
-		this->row_sglobaldoflist=NULL;
-	}
-
-	/*don't do cols, we can pick them up from the rows: */
-	this->col_fsize=0;
-	this->col_flocaldoflist=NULL;
-	this->col_fglobaldoflist=NULL;
-	this->col_ssize=0;
-	this->col_slocaldoflist=NULL;
-	this->col_sglobaldoflist=NULL;
-
-	/*clean-up*/
-	xDelete<int>(P);
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2,ElementMatrix* Ke3){{{*/
-ElementMatrix::ElementMatrix(ElementMatrix* Ke1, ElementMatrix* Ke2,ElementMatrix* Ke3){
-
-	/*Concatenate all matrices*/
-	ElementMatrix* Ke12 =new ElementMatrix(Ke1,Ke2);
-	ElementMatrix* Ke123=new ElementMatrix(Ke12,Ke3);
-
-	/*Initialize current object with this matrix*/
-	this->Init(Ke123);
-
-	/*clean-up*/
-	delete Ke12;
-	delete Ke123;
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation){{{*/
-ElementMatrix::ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation){
-
-	/*get Matrix size and properties*/
-	this->dofsymmetrical=true;
-	this->nrows=GetNumberOfDofs(nodes,numnodes,GsetEnum,approximation);
-	this->ncols=this->nrows;
-
-	/*fill values with 0: */
-	this->values=xNewZeroInit<IssmDouble>(this->nrows*this->ncols);
-
-	/*g list*/
-	this->gglobaldoflist=GetGlobalDofList(nodes,numnodes,GsetEnum,approximation);
-
-	/*get dof lists for f and s set: */
-	this->row_fsize=GetNumberOfDofs(nodes,numnodes,FsetEnum,approximation);
-	this->row_flocaldoflist =GetLocalDofList( nodes,numnodes,FsetEnum,approximation);
-	this->row_fglobaldoflist=GetGlobalDofList(nodes,numnodes,FsetEnum,approximation);
-	this->row_ssize=GetNumberOfDofs(nodes,numnodes,SsetEnum,approximation);
-	this->row_slocaldoflist =GetLocalDofList( nodes,numnodes,SsetEnum,approximation);
-	this->row_sglobaldoflist=GetGlobalDofList(nodes,numnodes,SsetEnum,approximation);
-
-	/*Because this matrix is "dofsymmetrical" don't do cols, we can pick them up from the rows: */
-	this->col_fsize=0;
-	this->col_flocaldoflist=NULL;
-	this->col_fglobaldoflist=NULL;
-	this->col_ssize=0;
-	this->col_slocaldoflist=NULL;
-	this->col_sglobaldoflist=NULL;
-
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::~ElementMatrix(){{{*/
-ElementMatrix::~ElementMatrix(){
-	
-	xDelete<IssmDouble>(this->values);
-	xDelete<int>(this->gglobaldoflist);
-	xDelete<int>(this->row_flocaldoflist);
-	xDelete<int>(this->row_fglobaldoflist);
-	xDelete<int>(this->row_slocaldoflist);
-	xDelete<int>(this->row_sglobaldoflist);
-	xDelete<int>(this->col_flocaldoflist);
-	xDelete<int>(this->col_fglobaldoflist);
-	xDelete<int>(this->col_slocaldoflist);
-	xDelete<int>(this->col_sglobaldoflist);
-}
-/*}}}*/
-
-/*ElementMatrix specific routines: */
-/*FUNCTION ElementMatrix::AddToGlobal(Matrix* Kff, Matrix* Kfs){{{*/
-void ElementMatrix::AddToGlobal(Matrix* Kff, Matrix* Kfs){
-
-	int i,j;
-	IssmDouble* localvalues=NULL;
-
-	/*If Kfs is not provided, call the other function*/
-	if(!Kfs){
-		this->AddToGlobal(Kff);
-		return;
-	}
-
-	/*In debugging mode, check consistency (no NaN, and values not too big)*/
-	this->CheckConsistency();
-
-	if(this->dofsymmetrical){
-		/*only use row dofs to add values into global matrices: */
-
-		if(this->row_fsize){
-			/*first, retrieve values that are in the f-set from the g-set values matrix: */
-			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_fsize);
-			for(i=0;i<this->row_fsize;i++){
-				for(j=0;j<this->row_fsize;j++){
-					*(localvalues+this->row_fsize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_flocaldoflist[j]);
-				}
-			}
-			/*add local values into global  matrix, using the fglobaldoflist: */
-			Kff->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_fsize,this->row_fglobaldoflist,localvalues,ADD_VAL);
-
-			/*Free ressources:*/
-			xDelete<IssmDouble>(localvalues);
-		}
-
-
-		if((this->row_ssize!=0) && (this->row_fsize!=0)){
-			/*first, retrieve values that are in the f and s-set from the g-set values matrix: */
-			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_ssize);
-			for(i=0;i<this->row_fsize;i++){
-				for(j=0;j<this->row_ssize;j++){
-					*(localvalues+this->row_ssize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_slocaldoflist[j]);
-				}
-			}
-			/*add local values into global  matrix, using the fglobaldoflist: */
-			Kfs->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_ssize,this->row_sglobaldoflist,localvalues,ADD_VAL);
-
-			/*Free ressources:*/
-			xDelete<IssmDouble>(localvalues);
-		}
-	}
-	else{
-		_error2_("non dofsymmetrical matrix AddToGlobal routine not support yet!");
-	}
-
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::AddToGlobal(Matrix* Jff){{{*/
-void ElementMatrix::AddToGlobal(Matrix* Jff){
-
-	int i,j;
-	IssmDouble* localvalues=NULL;
-
-	/*Check that Jff is not NULL*/
-	_assert_(Jff); 
-
-	/*In debugging mode, check consistency (no NaN, and values not too big)*/
-	this->CheckConsistency();
-
-	if(this->dofsymmetrical){
-		/*only use row dofs to add values into global matrices: */
-
-		if(this->row_fsize){
-			/*first, retrieve values that are in the f-set from the g-set values matrix: */
-			localvalues=xNew<IssmDouble>(this->row_fsize*this->row_fsize);
-			for(i=0;i<this->row_fsize;i++){
-				for(j=0;j<this->row_fsize;j++){
-					*(localvalues+this->row_fsize*i+j)=*(this->values+this->ncols*this->row_flocaldoflist[i]+this->row_flocaldoflist[j]);
-				}
-			}
-			/*add local values into global  matrix, using the fglobaldoflist: */
-			Jff->SetValues(this->row_fsize,this->row_fglobaldoflist,this->row_fsize,this->row_fglobaldoflist,localvalues,ADD_VAL);
-
-			/*Free ressources:*/
-			xDelete<IssmDouble>(localvalues);
-		}
-
-	}
-	else{
-		_error2_("non dofsymmetrical matrix AddToGlobal routine not support yet!");
-	}
-
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::CheckConsistency{{{*/
-void ElementMatrix::CheckConsistency(void){
-	/*Check element matrix values, only in debugging mode*/
-	#ifdef _ISSM_DEBUG_ 
-	for (int i=0;i<this->nrows;i++){
-		for(int j=0;j<this->ncols;j++){
-			if (xIsNan<IssmDouble>(this->values[i*this->ncols+j])) _error2_("NaN found in Element Matrix");
-			if (fabs(this->values[i*this->ncols+j])>1.e+50) _error2_("Element Matrix values exceeds 1.e+50");
-		}
-	}
-	#endif
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::Transpose{{{*/
-void ElementMatrix::Transpose(void){
-
-	/*Intermediaries*/
-	ElementMatrix* Ke_copy=new ElementMatrix(this);
-
-	/*Update sizes*/
-	this->nrows=Ke_copy->ncols;
-	this->ncols=Ke_copy->nrows;
-
-	/*Transpose values*/
-	for (int i=0;i<this->nrows;i++) for(int j=0;j<this->ncols;j++) this->values[i*this->ncols+j]=Ke_copy->values[j*Ke_copy->ncols+i];
-
-	/*Transpose indices*/
-	if(!dofsymmetrical){
-		_error2_("not supported yet");
-	}
-
-	/*Clean up and return*/
-	delete Ke_copy;
-	return;
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::Echo{{{*/
-void ElementMatrix::Echo(void){
-
-	int i,j;
-	_printLine_("Element Matrix echo:");
-	_printLine_("   nrows: " << nrows);
-	_printLine_("   ncols: " << nrows);
-	_printLine_("   dofsymmetrical: " << (dofsymmetrical?"true":"false"));
-
-	_printLine_("   values:");
-	for(i=0;i<nrows;i++){
-		_printString_(setw(4) << right << i << ": ");
-		for(j=0;j<ncols;j++) _printString_( " " << setw(11) << setprecision (5) << right << values[i*ncols+j]);
-		_printLine_("");
-	}
-
-	_printString_("   gglobaldoflist (" << gglobaldoflist << "): ");
-	if(gglobaldoflist) for(i=0;i<nrows;i++) _printString_(" " << gglobaldoflist[i]); _printLine_("");
-
-	_printLine_("   row_fsize: " << row_fsize);
-	_printString_("   row_flocaldoflist  (" << row_flocaldoflist << "): ");
-	if(row_flocaldoflist) for(i=0;i<row_fsize;i++) _printString_(" " << row_flocaldoflist[i]); _printLine_(" ");
-	_printString_("   row_fglobaldoflist  (" << row_fglobaldoflist << "): ");
-	if(row_fglobaldoflist) for(i=0;i<row_fsize;i++) _printString_(" " << row_fglobaldoflist[i]); _printLine_(" ");
-
-	_printLine_("   row_ssize: " << row_ssize);
-	_printString_("   row_slocaldoflist  (" << row_slocaldoflist << "): ");
-	if(row_slocaldoflist) for(i=0;i<row_ssize;i++) _printString_(" " << row_slocaldoflist[i]); _printLine_(" ");
-	_printString_("   row_sglobaldoflist  (" << row_sglobaldoflist << "): ");
-	if(row_sglobaldoflist) for(i=0;i<row_ssize;i++) _printString_(" " << row_sglobaldoflist[i]); _printLine_(" ");
-
-	if(!dofsymmetrical){
-		_printLine_("   col_fsize: " << col_fsize);
-		_printString_("   col_flocaldoflist  (" << col_flocaldoflist << "): ");
-		if(col_flocaldoflist) for(i=0;i<col_fsize;i++) _printString_(" " << col_flocaldoflist[i]); _printLine_(" ");
-		_printString_("   col_fglobaldoflist  (" << col_fglobaldoflist << "): ");
-		if(col_fglobaldoflist) for(i=0;i<col_fsize;i++) _printString_(" " << col_fglobaldoflist[i]); _printLine_(" ");
-
-		_printLine_("   col_ssize: " << col_ssize);
-		_printString_("   col_slocaldoflist  (" << col_slocaldoflist << "): ");
-		if(col_slocaldoflist) for(i=0;i<col_ssize;i++) _printString_(" " << col_slocaldoflist[i]); _printLine_(" ");
-		_printString_("   col_sglobaldoflist  (" << col_sglobaldoflist << "): ");
-		if(col_sglobaldoflist) for(i=0;i<col_ssize;i++) _printString_(" " << col_sglobaldoflist[i]); _printLine_(" ");
-	}
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::Init{{{*/
-void ElementMatrix::Init(ElementMatrix* Ke){
-
-	_assert_(Ke);
-
-	this->nrows =Ke->nrows;
-	this->ncols =Ke->ncols;
-	this->dofsymmetrical=Ke->dofsymmetrical;
-
-	this->values=xNew<IssmDouble>(this->nrows*this->ncols);
-	xMemCpy<IssmDouble>(this->values,Ke->values,this->nrows*this->ncols);
-
-	this->gglobaldoflist=xNew<int>(this->nrows);
-	xMemCpy<int>(this->gglobaldoflist,Ke->gglobaldoflist,this->nrows);
-
-	this->row_fsize=Ke->row_fsize;
-	if(this->row_fsize){
-		this->row_flocaldoflist=xNew<int>(this->row_fsize);
-		xMemCpy<int>(this->row_flocaldoflist,Ke->row_flocaldoflist,this->row_fsize);
-		this->row_fglobaldoflist=xNew<int>(this->row_fsize);
-		xMemCpy<int>(this->row_fglobaldoflist,Ke->row_fglobaldoflist,this->row_fsize);
-	}
-	else{
-		this->row_flocaldoflist=NULL;
-		this->row_fglobaldoflist=NULL;
-	}
-
-	this->row_ssize=Ke->row_ssize;
-	if(this->row_ssize){
-		this->row_slocaldoflist=xNew<int>(this->row_ssize);
-		xMemCpy<int>(this->row_slocaldoflist,Ke->row_slocaldoflist,this->row_ssize);
-		this->row_sglobaldoflist=xNew<int>(this->row_ssize);
-		xMemCpy<int>(this->row_sglobaldoflist,Ke->row_sglobaldoflist,this->row_ssize);
-	}
-	else{
-		this->row_slocaldoflist=NULL;
-		this->row_sglobaldoflist=NULL;
-	}
-
-	this->col_fsize=Ke->col_fsize;
-	if(this->col_fsize){
-		this->col_flocaldoflist=xNew<int>(this->col_fsize);
-		xMemCpy<int>(this->col_flocaldoflist,Ke->col_flocaldoflist,this->col_fsize);
-		this->col_fglobaldoflist=xNew<int>(this->col_fsize);
-		xMemCpy<int>(this->col_fglobaldoflist,Ke->col_fglobaldoflist,this->col_fsize);
-	}
-	else{
-		this->col_flocaldoflist=NULL;
-		this->col_fglobaldoflist=NULL;
-	}
-
-	this->col_ssize=Ke->col_ssize;
-	if(this->col_ssize){
-		this->col_slocaldoflist=xNew<int>(this->col_ssize);
-		xMemCpy<int>(this->col_slocaldoflist,Ke->col_slocaldoflist,this->col_ssize);
-		this->col_sglobaldoflist=xNew<int>(this->col_ssize);
-		xMemCpy<int>(this->col_sglobaldoflist,Ke->col_sglobaldoflist,this->col_ssize);
-	}
-	else{
-		this->col_slocaldoflist=NULL;
-		this->col_sglobaldoflist=NULL;
-	}
-}
-/*}}}*/
-/*FUNCTION ElementMatrix::SetDiag{{{*/
-void ElementMatrix::SetDiag(IssmDouble scalar){
-
-	int i;
-
-	if(this->nrows!=this->ncols)_error2_("need square matrix in input!");
-
-	for(i=0;i<this->nrows;i++){
-		this->values[this->ncols*i+i]=scalar;
-	}
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Numerics/ElementMatrix.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/ElementMatrix.h	(revision 12820)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*!\file:  ElementMatrix.h
- * \brief container for information needed to plug element matrix generated by elements 
- * into the Kff and Kfs global matrices. 
- * This object will hold the element matrix on the g-set, the local as well as global 
- * dof lists in the f and s sets.
- */ 
-
-#ifndef _ELEMENT_MATRIX_H_
-#define _ELEMENT_MATRIX_H_
-
-/*Headers:*/
-/*{{{*/
-#include "../Object.h"
-#include "../../toolkits/toolkits.h"
-#include "../../EnumDefinitions/EnumDefinitions.h"
-class Node;
-/*}}}*/
-
-class ElementMatrix{
-
-	public:
-	
-		int      nrows;
-		int      ncols;
-		bool     dofsymmetrical;
-		IssmDouble*  values;
-
-		//gset
-		int*     gglobaldoflist;
-
-		/*row wise: */
-		//fset
-		int      row_fsize;
-		int*     row_flocaldoflist;
-		int*     row_fglobaldoflist;
-		//sset
-		int      row_ssize;
-		int*     row_slocaldoflist;
-		int*     row_sglobaldoflist;
-
-		/*column wise: */
-		//fset
-		int      col_fsize;
-		int*     col_flocaldoflist;
-		int*     col_fglobaldoflist;
-		//sset
-		int      col_ssize;
-		int*     col_slocaldoflist;
-		int*     col_sglobaldoflist;
-
-		/*ElementMatrix constructors, destructors {{{*/
-		ElementMatrix();
-		ElementMatrix(ElementMatrix* Ke);
-		ElementMatrix(ElementMatrix* Ke1,ElementMatrix* Ke2);
-		ElementMatrix(ElementMatrix* Ke1,ElementMatrix* Ke2,ElementMatrix* Ke3);
-		ElementMatrix(Node** nodes,int numnodes,Parameters* parameters,int approximation=NoneApproximationEnum);
-		~ElementMatrix();
-		/*}}}*/
-		/*ElementMatrix specific routines {{{*/
-		void AddToGlobal(Matrix* Kff, Matrix* Kfs);
-		void AddToGlobal(Matrix* Jff);
-		void Echo(void);
-		void CheckConsistency(void);
-		void Transpose(void);
-		void Init(ElementMatrix* Ke);
-		void SetDiag(IssmDouble scalar);
-		/*}}}*/
-};
-#endif //#ifndef _ELEMENT_MATRIX_H_
Index: sm/trunk-jpl/src/c/objects/Numerics/ElementVector.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/ElementVector.cpp	(revision 12820)
+++ 	(revision )
@@ -1,276 +1,0 @@
-/*!\file ElementVector.cpp
- * \brief: implementation of the ElementVector object, used to plug values from element into global load
- */
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "../objects.h"
-#include "../../shared/shared.h"
-#include "../../Container/Container.h"
-#include "../../include/include.h"
-/*}}}*/
-
-/*ElementVector constructors and destructor*/
-/*FUNCTION ElementVector::ElementVector(){{{*/
-ElementVector::ElementVector(){
-
-	this->nrows=0;
-	this->values=NULL;
-	this->fsize=0;
-	this->flocaldoflist=NULL;
-	this->fglobaldoflist=NULL;
-
-}
-/*}}}*/
-/*FUNCTION ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2){{{*/
-ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2){
-
-	/*intermediaries*/
-	int i,j,counter;
-	int gsize,fsize,ssize;
-	int* P=NULL;
-	bool found;
-
-	/*If one of the two matrix is NULL, we copy the other one*/
-	if(!pe1 && !pe2){
-		_error2_("Two input element matrices are NULL");
-	}
-	else if(!pe1){
-		this->Init(pe2);
-		return;
-	}
-	else if(!pe2){
-		this->Init(pe1);
-		return;
-	}
-
-	/*Initialize itransformation matrix pe[P[i]] = pe2[i]*/
-	P=xNew<int>(pe2->nrows);
-
-	/*1: Get the new numbering of pe2 and get size of the new matrix*/
-	gsize=pe1->nrows;
-	for(i=0;i<pe2->nrows;i++){
-		found=false;
-		for(j=0;j<pe1->nrows;j++){
-			if(pe2->gglobaldoflist[i]==pe1->gglobaldoflist[j]){
-				found=true; P[i]=j; break;
-			}
-		}
-		if(!found){
-			P[i]=gsize; gsize++;
-		}
-	}
-
-	/*2: Initialize static fields*/
-	this->nrows=gsize;
-
-	/*Gset and values*/
-	this->gglobaldoflist=xNew<int>(this->nrows);
-	this->values=xNewZeroInit<IssmDouble>(this->nrows);
-	for(i=0;i<pe1->nrows;i++){
-		this->values[i] += pe1->values[i];
-		this->gglobaldoflist[i]=pe1->gglobaldoflist[i];
-	}
-	for(i=0;i<pe2->nrows;i++){
-		this->values[P[i]] += pe2->values[i];
-		this->gglobaldoflist[P[i]]=pe2->gglobaldoflist[i];
-	}
-
-	/*Fset*/
-	fsize=pe1->fsize;
-	for(i=0;i<pe2->fsize;i++){
-		if(P[pe2->flocaldoflist[i]] >= pe1->nrows) fsize++;
-	}
-	this->fsize=fsize;
-	if(fsize){
-		this->flocaldoflist =xNew<int>(fsize);
-		this->fglobaldoflist=xNew<int>(fsize);
-		for(i=0;i<pe1->fsize;i++){
-			this->flocaldoflist[i] =pe1->flocaldoflist[i];
-			this->fglobaldoflist[i]=pe1->fglobaldoflist[i];
-		}
-		counter=pe1->fsize;
-		for(i=0;i<pe2->fsize;i++){
-			if(P[pe2->flocaldoflist[i]] >= pe1->nrows){
-				this->flocaldoflist[counter] =P[pe2->flocaldoflist[i]];
-				this->fglobaldoflist[counter]=pe2->fglobaldoflist[i];
-				counter++;
-			}
-		}
-	}
-	else{
-		this->flocaldoflist=NULL;
-		this->fglobaldoflist=NULL;
-	}
-
-	/*clean-up*/
-	xDelete<int>(P);
-}
-/*}}}*/
-/*FUNCTION ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2,ElementVector* pe3){{{*/
-ElementVector::ElementVector(ElementVector* pe1, ElementVector* pe2,ElementVector* pe3){
-
-	/*Concatenate all matrices*/
-	ElementVector* pe12 =new ElementVector(pe1,pe2);
-	ElementVector* pe123=new ElementVector(pe12,pe3);
-
-	/*Initialize current object with this matrix*/
-	this->Init(pe123);
-
-	/*clean-up*/
-	delete pe12;
-	delete pe123;
-}
-/*}}}*/
-/*FUNCTION ElementVector::ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation){{{*/
-ElementVector::ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation){
-
-	/*get Vector size and properties*/
-	this->nrows=GetNumberOfDofs(nodes,numnodes,GsetEnum,approximation);
-
-	/*fill values with 0: */
-	this->values=xNewZeroInit<IssmDouble>(this->nrows);
-	
-	/*g list*/
-	this->gglobaldoflist=GetGlobalDofList(nodes,numnodes,GsetEnum,approximation);
-
-	/*Get fsize*/
-	this->fsize=GetNumberOfDofs(nodes,numnodes,FsetEnum,approximation);
-	this->flocaldoflist =GetLocalDofList( nodes,numnodes,FsetEnum,approximation);
-	this->fglobaldoflist=GetGlobalDofList(nodes,numnodes,FsetEnum,approximation);
-}
-/*}}}*/
-/*FUNCTION ElementVector::~ElementVector(){{{*/
-ElementVector::~ElementVector(){
-	
-	xDelete<IssmDouble>(this->values);
-	xDelete<int>(this->gglobaldoflist);
-	xDelete<int>(this->flocaldoflist);
-	xDelete<int>(this->fglobaldoflist);
-}
-/*}}}*/
-
-/*ElementVector specific routines: */
-/*FUNCTION ElementVector::AddToGlobal(Vector* pf){{{*/
-void ElementVector::AddToGlobal(Vector* pf){
-
-	int i;
-	IssmDouble* localvalues=NULL;
-
-	/*In debugging mode, check consistency (no NaN, and values not too big)*/
-	this->CheckConsistency();
-
-	if(this->fsize){
-		/*first, retrieve values that are in the f-set from the g-set values vector: */
-		localvalues=xNew<IssmDouble>(this->fsize);
-		for(i=0;i<this->fsize;i++){
-			localvalues[i]=this->values[this->flocaldoflist[i]];
-		}
-		/*add local values into global  vector, using the fglobaldoflist: */
-		pf->SetValues(this->fsize,this->fglobaldoflist,localvalues,ADD_VAL);
-
-		/*Free ressources:*/
-		xDelete<IssmDouble>(localvalues);
-	}
-	
-}
-/*}}}*/
-/*FUNCTION ElementVector::InsertIntoGlobal(Vector* pf){{{*/
-void ElementVector::InsertIntoGlobal(Vector* pf){
-
-	int i;
-	IssmDouble* localvalues=NULL;
-
-	if(this->fsize){
-		/*first, retrieve values that are in the f-set from the g-set values vector: */
-		localvalues=xNew<IssmDouble>(this->fsize);
-		for(i=0;i<this->fsize;i++){
-			localvalues[i]=this->values[this->flocaldoflist[i]];
-		}
-		/*add local values into global  vector, using the fglobaldoflist: */
-		pf->SetValues(this->fsize,this->fglobaldoflist,localvalues,INS_VAL);
-
-		/*Free ressources:*/
-		xDelete<IssmDouble>(localvalues);
-	}
-
-}
-/*}}}*/
-/*FUNCTION ElementVector::CheckConsistency{{{*/
-void ElementVector::CheckConsistency(void){
-	/*Check element matrix values, only in debugging mode*/
-#ifdef _ISSM_DEBUG_ 
-	for (int i=0;i<this->nrows;i++){
-		if (xIsNan<IssmDouble>(this->values[i])) _error2_("NaN found in Element Vector");
-		if (fabs( this->values[i])>1.e+50) _error2_("Element Vector values exceeds 1.e+50");
-	}
-#endif
-}
-/*}}}*/
-/*FUNCTION ElementVector::Echo{{{*/
-void ElementVector::Echo(void){
-
-	int i,j;
-	_printLine_("Element Vector echo:");
-	_printLine_("   nrows: " << nrows);
-	_printLine_("   values:");
-	for(i=0;i<nrows;i++){
-		_printLine_(setw(4) << right << i << ": " << setw(10) << values[i]);
-	}
-
-	_printString_("   gglobaldoflist (" << gglobaldoflist << "): ");
-	if(gglobaldoflist) for(i=0;i<nrows;i++) _printString_(" " << gglobaldoflist[i] );
-	_printLine_(" ");
-
-	_printLine_("   fsize: " << fsize);
-	_printString_("   flocaldoflist  (" << flocaldoflist << "): ");
-	if(flocaldoflist) for(i=0;i<fsize;i++) _printString_(" " << flocaldoflist[i] );
-	_printLine_(" ");
-	_printString_("   fglobaldoflist (" << fglobaldoflist << "): ");
-	if(fglobaldoflist) for(i=0;i<fsize;i++) _printString_(" " << fglobaldoflist[i] );
-	_printLine_(" ");
-}
-/*}}}*/
-/*FUNCTION ElementVector::Init{{{*/
-void ElementVector::Init(ElementVector* pe){
-
-	_assert_(pe);
-
-	this->nrows =pe->nrows;
-
-	this->values=xNew<IssmDouble>(this->nrows);
-	xMemCpy<IssmDouble>(this->values,pe->values,this->nrows);
-
-	this->gglobaldoflist=xNew<int>(this->nrows);
-	xMemCpy<int>(this->gglobaldoflist,pe->gglobaldoflist,this->nrows);
-
-	this->fsize=pe->fsize;
-	if(this->fsize){
-		this->flocaldoflist=xNew<int>(this->fsize);
-		xMemCpy<int>(this->flocaldoflist,pe->flocaldoflist,this->fsize);
-		this->fglobaldoflist=xNew<int>(this->fsize);
-		xMemCpy<int>(this->fglobaldoflist,pe->fglobaldoflist,this->fsize);
-	}
-	else{
-		this->flocaldoflist=NULL;
-		this->fglobaldoflist=NULL;
-	}
-}
-/*}}}*/
-/*FUNCTION ElementVector::SetValue{{{*/
-void ElementVector::SetValue(IssmDouble scalar){
-
-	int i;
-
-	for(i=0;i<this->nrows;i++)this->values[i]=scalar;
-
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Numerics/ElementVector.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/ElementVector.h	(revision 12820)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*!\file:  ElementVector.h
- * \brief container for information needed to plug element vector generated by elements 
- * into the pf global load vector. 
- * This object will hold the element vector on the g-set, the local as well as global 
- * dof lists in the f set
- */ 
-
-#ifndef _ELEMENT_VECTOR_H_
-#define _ELEMENT_VECTOR_H_
-
-/*Headers:*/
-/*{{{*/
-#include "../Object.h"
-#include "../../toolkits/toolkits.h"
-#include "../../EnumDefinitions/EnumDefinitions.h"
-class Node;
-/*}}}*/
-
-class ElementVector{
-
-	public:
-	
-		int      nrows;
-		IssmDouble*  values;
-		
-		//gset
-		int*     gglobaldoflist;
-
-		//fset
-		int      fsize;
-		int*     flocaldoflist;
-		int*     fglobaldoflist;
-		
-		/*ElementVector constructors, destructors {{{*/
-		ElementVector();
-		ElementVector(ElementVector* pe1,ElementVector* pe2);
-		ElementVector(ElementVector* pe1,ElementVector* pe2,ElementVector* pe3);
-		ElementVector(Node** nodes,int numnodes,Parameters* parameters,int approximation=NoneApproximationEnum);
-		~ElementVector();
-		/*}}}*/
-		/*ElementVector specific routines {{{*/
-		void AddToGlobal(Vector* pf);
-		void InsertIntoGlobal(Vector* pf);
-		void Echo(void);
-		void CheckConsistency(void);
-		void Init(ElementVector* pe);
-		void SetValue(IssmDouble scalar);
-		/*}}}*/
-};
-#endif //#ifndef _ELEMENT_VECTOR_H_
-
Index: sm/trunk-jpl/src/c/objects/Numerics/Matrix.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/Matrix.cpp	(revision 12820)
+++ 	(revision )
@@ -1,253 +1,0 @@
-/*!\file Matrix.cpp
- * \brief: implementation of the Matrix object
- */
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "../objects.h"
-#include "../../shared/shared.h"
-#include "../../Container/Container.h"
-#include "../../include/include.h"
-#include "../../toolkits/toolkits.h"
-#include "./Matrix.h"
-	
-/*}}}*/
-
-/*Matrix constructors and destructor*/
-/*FUNCTION Matrix::Matrix(){{{*/
-Matrix::Matrix(){
-
-	#ifdef _HAVE_PETSC_
-	this->matrix=NULL;
-	#else
-	this->matrix=NULL;
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->amatrix=NULL;
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Matrix(int M,int N){{{*/
-Matrix::Matrix(int M,int N){
-
-	#ifdef _HAVE_PETSC_
-	this->matrix=NewMat(M,N);
-	#else
-	this->matrix=new SeqMat(M,N);
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->amatrix=xNew<IssmDouble>(M*N);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Matrix(int M,int N,IssmDouble sparsity){{{*/
-Matrix::Matrix(int M,int N,IssmDouble sparsity){
-
-	#ifdef _HAVE_PETSC_
-	this->matrix=NewMat(M,N,sparsity);
-	#else
-	this->matrix=new SeqMat(M,N,sparsity);
-	#endif
-	#ifdef _HAVE_ADOLC_
- 	this->amatrix=xNew<IssmDouble>(M*N);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Matrix(IssmDouble* serial_mat, int M,int N,IssmDouble sparsity){{{*/
-Matrix::Matrix(IssmDouble* serial_mat, int M,int N,IssmDouble sparsity){
-
-	#ifdef _HAVE_PETSC_
-	int     i;
-
-
-	int* idxm=xNew<int>(M);
-	int* idxn=xNew<int>(N);
-	for(i=0;i<M;i++)idxm[i]=i;
-	for(i=0;i<N;i++)idxn[i]=i;
-
-	this->matrix=NewMat(M,N,sparsity);
-	MatSetValues(this->matrix,M,idxm,N,idxn,serial_mat,INSERT_VALUES);
-	MatAssemblyBegin(this->matrix,MAT_FINAL_ASSEMBLY);
-	MatAssemblyEnd(this->matrix,MAT_FINAL_ASSEMBLY);
-
-	xDelete<int>(idxm);
-	xDelete<int>(idxn);
-	#else
-	this->matrix=new SeqMat(serial_mat,M,N,sparsity);
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->amatrix=xNew<IssmDouble>(M*N);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Matrix(int M,int N,int connectivity,int numberofdofspernode){{{*/
-Matrix::Matrix(int M,int N,int connectivity,int numberofdofspernode){
-	
-	#ifdef _HAVE_PETSC_
-	this->matrix=NewMat(M,N,connectivity,numberofdofspernode);
-	#else
-	this->matrix=new SeqMat(M,N,connectivity,numberofdofspernode);
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->amatrix=xNew<IssmDouble>(M*N);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::~Matrix(){{{*/
-Matrix::~Matrix(){
-
- 	#ifdef _HAVE_PETSC_
-	MatFree(&this->matrix);
-	#else
-	delete this->matrix;
-	#endif
-	#ifdef _HAVE_ADOLC_
-	xDelete<IssmDouble>(this->amatrix);
-	#endif
-}
-/*}}}*/
-
-/*Matrix specific routines: */
-/*FUNCTION Matrix::Echo{{{*/
-void Matrix::Echo(void){
-
-	int i,j;
-
-	#ifdef _HAVE_PETSC_
-	MatView(this->matrix,PETSC_VIEWER_STDOUT_WORLD);
-	#else
-	this->matrix->Echo();
-	#endif
-
-	#ifdef _HAVE_ADOLC_
-	/*Not sure about that one. Should we use the overloaded operator >>?*/
-	_printString_("ADOLC Matrix equivalent:" );
-//	for(i=0;i<M;i++){
-//		for(j=0;j<N;j++){
-//			_printString_(*(amatrix+N*i+j) << " ");
-//		}
-//		_printLine_("");
-//	}
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Assemble{{{*/
-void Matrix::Assemble(void){
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		MatAssemblyBegin(this->matrix,MAT_FINAL_ASSEMBLY);
-		MatAssemblyEnd(this->matrix,MAT_FINAL_ASSEMBLY);
-		#if _PETSC_MAJOR_ == 2 
-			MatCompress(this->matrix);
-		#endif
-	#else
-		this->matrix->Assemble();
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Matrix::Norm{{{*/
-IssmDouble Matrix::Norm(NormMode norm_type){
-	
-	IssmDouble norm=0;
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		MatNorm(this->matrix,ISSMToPetscNormMode(norm_type),&norm);
-	#else
-		norm=this->matrix->Norm(norm_type);
-	#endif
-	return norm;
-}
-/*}}}*/
-/*FUNCTION Matrix::GetSize{{{*/
-void Matrix::GetSize(int* pM,int* pN){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		MatGetSize(this->matrix,pM,pN);
-	#else
-		this->matrix->GetSize(pM,pN);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::GetLocalSize{{{*/
-void Matrix::GetLocalSize(int* pM,int* pN){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		MatGetLocalSize(this->matrix,pM,pN);
-	#else
-		this->matrix->GetLocalSize(pM,pN);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::MatMult{{{*/
-void Matrix::MatMult(Vector* X,Vector* AX){
-
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		_assert_(X->vector);
-		MatMultPatch(this->matrix,X->vector,AX->vector);
-	#else
-		this->matrix->MatMult(X->vector,AX->vector);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Duplicate{{{*/
-Matrix* Matrix::Duplicate(void){
-
-	Matrix* output=NULL;
-
-	output=new Matrix();
-
-	#ifdef _HAVE_PETSC_
-		_assert_(this->matrix);
-		MatDuplicate(this->matrix,MAT_COPY_VALUES,&output->matrix);
-	#else
-		output->matrix=this->matrix->Duplicate();
-	#endif
-	
-	return output;
-}
-/*}}}*/
-/*FUNCTION Matrix::ToSerial{{{*/
-IssmDouble* Matrix::ToSerial(void){
-
-	IssmDouble* output=NULL;
-
-	#ifdef _HAVE_PETSC_
-		MatToSerial(&output,this->matrix);
-	#else
-		output=this->matrix->ToSerial();
-	#endif
-	return output;
-}
-/*}}}*/
-/*FUNCTION Matrix::SetValues{{{*/
-void Matrix::SetValues(int m,int* idxm,int n,int* idxn,IssmDouble* values,InsMode mode){
-
-	#ifdef _HAVE_PETSC_
-		MatSetValues(this->matrix,m,idxm,n,idxn,values,ISSMToPetscInsertMode(mode));
-	#else
-		this->matrix->SetValues(m,idxm,n,idxn,values,mode);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Matrix::Convert{{{*/
-void Matrix::Convert(MatrixType type){
-
-	#ifdef _HAVE_PETSC_
-		MatConvert(this->matrix,ISSMToPetscMatrixType(type),MAT_REUSE_MATRIX,&this->matrix);
-	#else
-		this->matrix->Convert(type);
-	#endif
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Numerics/Matrix.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/Matrix.h	(revision 12820)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*!\file:  Matrix.h
- * \brief wrapper to matrix objects. The goal is to control which API (PETSc,Scalpack, Plapack?) 
- * implements our underlying matrix format.
- */ 
-
-#ifndef _MATRIX_H_
-#define _MATRIX_H_
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-#include "../../toolkits/toolkits.h"
-#include "../../EnumDefinitions/EnumDefinitions.h"
-
-class Vector;
-
-/*}}}*/
-
-class Matrix{
-
-	public:
-	
-		#ifdef _HAVE_PETSC_
-		Mat matrix; 
-		#else
-		SeqMat* matrix; 
-		#endif
-		#ifdef _HAVE_ADOLC_
-		IssmDouble* amatrix;
-		#endif
-
-		/*Matrix constructors, destructors {{{*/
-		Matrix();
-		Matrix(int M,int N);
-		Matrix(int M,int N,IssmDouble sparsity);
-		Matrix(IssmDouble* serial_mat,int M,int N,IssmDouble sparsity);
-		Matrix(int M,int N,int connectivity,int numberofdofspernode);
-		~Matrix();
-		/*}}}*/
-		/*Matrix specific routines {{{*/
-		void Echo(void);
-		void Assemble(void);
-		IssmDouble Norm(NormMode norm_type);
-		void GetSize(int* pM,int* pN);
-		void GetLocalSize(int* pM,int* pN);
-		void MatMult(Vector* X,Vector* AX);
-		Matrix* Duplicate(void);
-		IssmDouble* ToSerial(void);
-		void SetValues(int m,int* idxm,int n,int* idxn,IssmDouble* values,InsMode mode);
-		void Convert(MatrixType type);
-		/*}}}*/
-
-};
-
-#endif //#ifndef _MATRIX_H_
Index: sm/trunk-jpl/src/c/objects/Numerics/Vector.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/Vector.cpp	(revision 12820)
+++ 	(revision )
@@ -1,347 +1,0 @@
-/*!\file Vector.cpp
- * \brief: implementation of the Vector object
- */
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "../objects.h"
-#include "../../shared/shared.h"
-#include "../../Container/Container.h"
-#include "../../include/include.h"
-#include "../../toolkits/toolkits.h"
-#include "./Vector.h"
-/*}}}*/
-
-/*Vector constructors and destructor*/
-/*FUNCTION Vector::Vector(){{{*/
-Vector::Vector(){
-
-	#ifdef _HAVE_PETSC_
-	this->vector=NULL;
-	#else
-	this->vector=NULL;
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->avector=NULL;
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::Vector(int M,bool fromlocalsize){{{*/
-Vector::Vector(int pM,bool fromlocalsize){
-
-	#ifdef _HAVE_PETSC_
-	this->vector=NewVec(pM,fromlocalsize);
-	#else
-	this->vector=new SeqVec(pM,fromlocalsize);
-	#endif
-	#ifdef _HAVE_ADOLC_
-	this->avector=xNew<IssmDouble>(pM);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::Vector(IssmDouble* serial_vec,int M){{{*/
-Vector::Vector(IssmDouble* serial_vec,int M){
-
-	#ifdef _HAVE_PETSC_
-		int* idxm=xNew<int>(M);
-		for(int i=0;i<M;i++) idxm[i]=i;
-
-		this->vector=NewVec(M);
-		VecSetValues(this->vector,M,idxm,serial_vec,INSERT_VALUES);
-		VecAssemblyBegin(this->vector);
-		VecAssemblyEnd(this->vector);
-
-		xDelete<int>(idxm);
-	#else
-		this->vector=new SeqVec(serial_vec,M);
-	#endif
-	#ifdef _HAVE_ADOLC_
-		this->avector=xNew<IssmDouble>(M);
-	#endif
-}
-/*}}}*/
-#ifdef _HAVE_PETSC_
-/*FUNCTION Vector::Vector(Vec petsc_vec){{{*/
-Vector::Vector(Vec petsc_vec){
-
-	if(petsc_vec==NULL){
-		this->vector=NewVec(0);
-	}
-	else{
-		/*copy vector*/
-		VecDuplicate(petsc_vec,&this->vector);
-		VecCopy(petsc_vec,this->vector);
-	}
-
-}
-/*}}}*/
-#endif
-#if defined(_HAVE_GSL_) && !defined(_HAVE_PETSC_)
-/*FUNCTION Vector::Vector(SeqVec* seq_vec){{{*/
-Vector::Vector(SeqVec*  seq_vec){
-
-	if(seq_vec==NULL){
-		this->vector=NULL;
-	}
-	else{
-		/*copy vector*/
-		this->vector=seq_vec->Duplicate();
-	}
-}
-/*}}}*/
-#endif
-
-		/*FUNCTION Vector::~Vector(){{{*/
-Vector::~Vector(){
-
- 	#ifdef _HAVE_PETSC_
-	VecFree(&this->vector);
-	#else
-	delete this->vector;
-	#endif
-	#ifdef _HAVE_ADOLC_
-	xDelete<IssmDouble>(this->avector);
-	#endif
-}
-/*}}}*/
-
-/*Vector specific routines: */
-/*FUNCTION Vector::Echo{{{*/
-void Vector::Echo(void){
-
-	int i;
-
-	#ifdef _HAVE_PETSC_
-	_assert_(this->vector);
-	VecView(this->vector,PETSC_VIEWER_STDOUT_WORLD);
-	#else
-	this->vector->Echo();
-	#endif
-
-	#ifdef _HAVE_ADOLC_
-	/*do nothing for now: */
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::Assemble{{{*/
-void Vector::Assemble(void){
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecAssemblyBegin(this->vector); 
-		VecAssemblyEnd(this->vector);
-	#else
-		this->vector->Assemble();
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::SetValues{{{*/
-void Vector::SetValues(int ssize, int* list, IssmDouble* values, InsMode mode){
-		
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecSetValues(this->vector,ssize,list,values,ISSMToPetscInsertMode(mode));
-	#else
-		this->vector->SetValues(ssize,list,values,mode);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::SetValue{{{*/
-void Vector::SetValue(int dof, IssmDouble value, InsMode mode){
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecSetValues(this->vector,1,&dof,&value,ISSMToPetscInsertMode(mode));
-	#else
-		this->vector->SetValue(dof,value,mode);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::GetValue{{{*/
-void Vector::GetValue(IssmDouble* pvalue,int dof){
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecGetValues(this->vector,1,&dof,pvalue);
-	#else
-	this->vector->GetValue(pvalue,dof);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::GetSize{{{*/
-void Vector::GetSize(int* pM){
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecGetSize(this->vector,pM);
-	#else
-		this->vector->GetSize(pM);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::IsEmpty{{{*/
-bool Vector::IsEmpty(void){
-
-	int M;
-
-	_assert_(this->vector);
-	this->GetSize(&M);
-
-	if(M==0) 
-	 return true;
-	else
-	 return false;
-}
-/*}}}*/
-/*FUNCTION Vector::GetLocalSize{{{*/
-void Vector::GetLocalSize(int* pM){
-		
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecGetLocalSize(this->vector,pM);
-	#else
-		this->vector->GetLocalSize(pM);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::Duplicate{{{*/
-Vector* Vector::Duplicate(void){
-	
-	Vector* output=NULL;
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		Vec vec_output=NULL;
-		VecDuplicate(this->vector,&vec_output);
-		output=new Vector(vec_output);
-		VecFree(&vec_output);
-	#else
-		output=new Vector();
-		output->vector=this->vector->Duplicate();
-	#endif
-	return output;
-
-}
-/*}}}*/
-/*FUNCTION Vector::Set{{{*/
-void Vector::Set(IssmDouble value){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecSet(this->vector,value);
-	#else
-		this->vector->Set(value);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::AXPY{{{*/
-void Vector::AXPY(Vector* X, IssmDouble a){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecAXPY(this->vector,a,X->vector);
-	#else
-		this->vector->AXPY(X->vector,a);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::AYPX{{{*/
-void Vector::AYPX(Vector* X, IssmDouble a){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecAYPX(this->vector,a,X->vector);
-	#else
-		this->vector->AYPX(X->vector,a);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::ToMPISerial{{{*/
-IssmDouble* Vector::ToMPISerial(void){
-
-	IssmDouble* vec_serial=NULL;
-
-	#ifdef _HAVE_PETSC_
-		VecToMPISerial(&vec_serial, this->vector);
-	#else
-		vec_serial=this->vector->ToMPISerial();
-	#endif
-
-	return vec_serial;
-
-}
-/*}}}*/
-/*FUNCTION Vector::Copy{{{*/
-void Vector::Copy(Vector* to){
-
-	#ifdef _HAVE_PETSC_
-		if(this->vector) VecCopy(this->vector,to->vector);
-	#else
-		this->vector->Copy(to->vector);
-	#endif
-
-}
-/*}}}*/
-/*FUNCTION Vector::Norm{{{*/
-IssmDouble Vector::Norm(NormMode norm_type){
-	
-	IssmDouble norm=0;
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecNorm(this->vector,ISSMToPetscNormMode(norm_type),&norm);
-	#else
-		norm=this->vector->Norm(norm_type);
-	#endif
-	return norm;
-}
-/*}}}*/
-/*FUNCTION Vector::Scale{{{*/
-void Vector::Scale(IssmDouble scale_factor){
-	
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecScale(this->vector,scale_factor); 
-	#else
-		this->vector->Scale(scale_factor);
-	#endif
-}
-/*}}}*/
-/*FUNCTION Vector::Dot{{{*/
-IssmDouble Vector::Dot(Vector* vector){
-
-	IssmDouble dot;
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecDot(this->vector,vector->vector,&dot);
-	#else
-		dot=this->vector->Dot(vector->vector);
-	#endif
-	return dot;
-}
-/*}}}*/
-/*FUNCTION Vector::PointwiseDivide{{{*/
-void Vector::PointwiseDivide(Vector* x,Vector* y){
-
-	#ifdef _HAVE_PETSC_
-		_assert_(this->vector);
-		VecPointwiseDivide(this->vector,x->vector,y->vector);
-	#else
-		this->vector->PointwiseDivide(x->vector,y->vector);
-	#endif
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Numerics/Vector.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Numerics/Vector.h	(revision 12820)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*!\file:  Vector.h
- * \brief wrapper to vector objects. The goal is to control which API (PETSc,Scalpack, Plapack?) 
- * implements our underlying vector format.
- */ 
-
-#ifndef _VECTOR_H_
-#define _VECTOR_H_
-
-/*Headers:*/
-/*{{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-#include "../../toolkits/toolkits.h"
-#include "../../EnumDefinitions/EnumDefinitions.h"
-
-/*}}}*/
-
-class Vector{
-
-	public:
-	
-		#ifdef _HAVE_PETSC_
-			Vec vector; 
-		#else
-			SeqVec* vector;
-		#endif
-		#ifdef _HAVE_ADOLC_
-			IssmDouble* avector;
-		#endif
-
-		/*Vector constructors, destructors {{{*/
-		Vector();
-		Vector(int M,bool fromlocalsize=false);
-		Vector(IssmDouble* serial_vec,int pM);
-		#ifdef _HAVE_PETSC_
-		Vector(Vec petsc_vec);
-		#endif
-		#if defined(_HAVE_GSL_) && !defined(_HAVE_PETSC_)
-		Vector(SeqVec*  seq_vec);
-		#endif
-		~Vector();
-		/*}}}*/
-		/*Vector specific routines {{{*/
-		void Echo(void);
-		void    AXPY(Vector *X, IssmDouble a);
-		void    AYPX(Vector *X, IssmDouble a);
-		void    Assemble(void);
-		void    Copy(Vector *to);
-		IssmDouble  Dot(Vector *vector);
-		Vector *Duplicate(void);
-		void    GetValue(IssmDouble *pvalue, int dof);
-		void    GetSize(int *pM);
-		void    GetLocalSize(int *pM);
-		bool    IsEmpty(void);
-		IssmDouble  Norm(NormMode norm_type);
-		void    PointwiseDivide(Vector  *x,Vector*y);
-		void    Scale(IssmDouble scale_factor);
-		void    Set(IssmDouble value);
-		void    SetValues(int ssize, int *list, IssmDouble*values, InsMode mode);
-		void    SetValue(int dof, IssmDouble value, InsMode mode);
-		IssmDouble *ToMPISerial(void);
-		/*}}}*/
-};
-
-
-#endif //#ifndef _VECTOR_H_
Index: sm/trunk-jpl/src/c/objects/Object.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Object.h	(revision 12820)
+++ 	(revision )
@@ -1,27 +1,0 @@
-/*
- * Object.h:
- * \brief prototype for abstract Object class
- * \file Object.h
- * This prototype describes the Object class. This is an abstract class, parent 
- * to any other objects (Quad, Tria, Node , etc ...), that can be included in a 
- * DataSet.
- */
-
-
-#ifndef _OBJECT_H_
-#define _OBJECT_H_
-
-class Object {
-
-	public: 
-
-		virtual       ~Object() {};
-		virtual void  Echo()=0;
-		virtual void  DeepEcho()=0;
-		virtual int   Id()=0;
-		virtual int   MyRank()=0;
-		virtual int   ObjectEnum()=0;
-		virtual Object* copy()=0;
-
-};
-#endif
Index: sm/trunk-jpl/src/c/objects/Patch.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Patch.cpp	(revision 12820)
+++ 	(revision )
@@ -1,175 +1,0 @@
-/*!\file Patch.c
- * \brief: implementation of the Patch object
- */
-
-/*Include files: {{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include "./objects.h"
-#include "../Container/Container.h"
-#include "../io/io.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../include/include.h"
-/*}}}*/
-
-/*Object constructors and destructors:*/
-/*FUNCTION Patch::Patch() default constructor {{{*/
-Patch::Patch(){
-	this->numrows=0;
-	this->numcols=0;
-	this->maxvertices=0;
-	this->maxnodes=0;
-	this->values=NULL;
-}
-/*}}}*/
-/*FUNCTION Patch::Patch(int numrows, int maxvertices, int maxnodes){{{*/
-Patch::Patch(int in_numrows, int in_maxvertices, int in_maxnodes){
-
-	int i,j;
-	this->numrows=in_numrows;
-	this->maxvertices=in_maxvertices;
-	this->maxnodes=in_maxnodes;
-    
-	this->numcols=1  //enum_type
-		+1           //step
-		+1           //time 
-		+1           //element id
-		+1           //interpolation type
-		+maxvertices //vertices
-		+maxnodes;   //nodes
-
-	//Allocate values and fill with NaN:
-	if (this->numcols*this->numrows==0){
-		this->values=NULL;
-	}
-	else{
-	        this->values=xNew<IssmDouble>(this->numcols*this->numrows);
-		for(i=0;i<this->numrows;i++){
-			for(j=0;j<this->numcols;j++){
-				this->values[i*this->numcols+j]=NAN;
-			}
-		}
-	}
-
-}
-/*}}}*/
-/*FUNCTION Patch::~Patch(){{{*/
-Patch::~Patch(){
-	xDelete<IssmDouble>(values);
-}
-/*}}}*/
-
-/*Object methods*/
-/*FUNCTION Patch::fillelementinfo{{{*/
-void Patch::fillelementinfo(int count, int element_id, int* vertices_ids, int num_vertices){
-
-	int i;
-	IssmDouble* row=NULL;
-
-	/*point to the start of the row: */
-	row=this->values+count*this->numcols;
-
-	/*Let's remember what is on a row: 
-	 enum_type step time element_id interpolation vertices_ids nodal_values
-	 */
-	row[3]=element_id;
-	for(i=0;i<num_vertices;i++){
-		row[5+i]=vertices_ids[i];
-	}
-
-}
-/*}}}*/
-/*FUNCTION Patch::fillresultinfo{{{*/
-void Patch::fillresultinfo(int count,int enum_type,int step, IssmDouble time, int interpolation, IssmDouble* nodal_values, int num_nodes){
-
-	int i;
-	IssmDouble* row=NULL;
-
-	/*point to the start of the row: */
-	row=this->values+count*this->numcols;
-
-	/*Let's remember what is on a row: 
-	 enum_type step time element_id interpolation vertices_ids nodal_values
-	 */
-	row[0]=enum_type;
-	row[1]=(IssmDouble)step;
-	row[2]=time;
-	row[4]=interpolation;
-	for(i=0;i<num_nodes;i++){
-		row[5+this->maxvertices+i]=nodal_values[i];
-	}
-
-}
-/*}}}*/
-/*FUNCTION Patch::Gather{{{*/
-void Patch::Gather(void){
-
-	int         i;
-	int         count;
-	extern int  my_rank;
-	extern int  num_procs;
-	int         total_numrows;
-	int         node_numrows;
-	IssmDouble     *total_values  = NULL;
-	#ifdef _HAVE_MPI_
-	MPI_Status  status;
-	#endif
-
-	/*First, figure out total number of rows combining all the cpus: */
-	#ifdef _HAVE_MPI_
-	MPI_Reduce(&this->numrows,&total_numrows,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD );
-	MPI_Bcast(&total_numrows,1,MPI_INT,0,MPI_COMM_WORLD);
-	#else
-	total_numrows=this->numrows;
-	#endif
-
-	/*return if patch empty*/
-	if(total_numrows==0) return;
-
-	/*Now, allocate buffer to holds all the values, on node 0: */
-	if(my_rank==0)total_values=xNew<IssmDouble>(this->numcols*total_numrows);
-
-	/*Start by copying node 0 values onto total_values: */
-	if(my_rank==0){
-		count=0;
-		xMemCpy<IssmDouble>(total_values+count,this->values,this->numcols*this->numrows);
-		count+=this->numrows*this->numcols;
-	}
-
-	/*Now, ask other nodes to send their values: */
-	#ifdef _HAVE_MPI_
-	for (i=1;i<num_procs;i++){
-		if (my_rank==i){ 
-			MPI_Send(&this->numrows,1,MPI_INT,0,1,MPI_COMM_WORLD);   
-			if (this->numrows)MPI_Send(this->values,this->numrows*this->numcols,MPI_DOUBLE,0,1,MPI_COMM_WORLD); 
-		}
-		if (my_rank==0){
-			MPI_Recv(&node_numrows,1,MPI_INT,i,1,MPI_COMM_WORLD,&status); 
-			if (node_numrows)MPI_Recv(total_values+count,node_numrows*this->numcols,MPI_DOUBLE,i,1,MPI_COMM_WORLD,&status);
-			count+=node_numrows*this->numcols;
-		}
-	}	
-	#endif
-
-	/*Now, node 0 has total_values, of size total_numrows*this->numcols. Update the fields in the patch, to reflect this new 
-	 * reality. For other cpus, no point in keeping their data anymore: */
-	if(my_rank==0){
-		this->numrows=total_numrows;
-		xDelete<IssmDouble>(this->values);
-		this->values=total_values;
-	}
-	#ifdef _HAVE_MPI_
-	else{
-		this->numrows=0;
-		xDelete<IssmDouble>(this->values);
-	}
-	#endif
-}/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Patch.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Patch.h	(revision 12820)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*!\file: Patch.h
- * \brief prototypes for Patch.h
- */ 
-
-/*A Patch object is used to store all results held in elements, in a serial way, and to dump them to disk. 
-	
-	Each row of the Patch object is made of the following information: 
-	- the result enum_type, 
-	- the step and time, 
-	- the id of the element, 
-	- the interpolation type, 
-	- the vertices ids, 
-	- and the values at the nodes (could be different from the vertices).
-	
-	For ex: 
-	1. on a Beam element, Vx, at step 1, time .5, element id 1, interpolation type P0 (constant), vertices ids 1 and 2, one constant value 4.5
-	   VxEnum 1  .5  1 P0  1 2       4.5 NaN  NaN
-	2. on a Tria element, Vz, at step 2, time .8, element id 2, interpolation type P1 (linear), vertices ids 1 3 and 4, with values at 3 nodes 4.5, 3.2, 2.5
-	   VzEnum 2  .8  2 P1  1 3 4     4.5 3.2  2.5
-*/
-
-
-#ifndef _PATCH_H_
-#define  _PATCH_H_
-
-/*Headers:*/
-class Patch{
-
-	public:
-
-		int     numrows; //number of results held in Patch object
-		int     numcols; //number of columns
-		int     maxvertices; //maxvertices corresponds to largest amount of vertices on a given element, determined by the geometry.
-		int     maxnodes;    // maxnodes corresponds to the largest amout of nodes on a given element, determined by the interpolation type.
-		
-		IssmDouble* values;  //result values
-
-		Patch();
-		Patch(int numrows, int maxvertices, int maxnodes);
-		~Patch();
-		void fillelementinfo(int row, int element_id, int* vertices_ids, int num_vertices);
-		void fillresultinfo(int row,int enum_type,int step, IssmDouble time, int interpolation, IssmDouble* nodal_values, int num_nodes);
-		void Gather(void);
-
-};
-#endif //ifndef _PATCH_H_
Index: sm/trunk-jpl/src/c/objects/Segment.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Segment.cpp	(revision 12820)
+++ 	(revision )
@@ -1,86 +1,0 @@
-/*!\file Segment.c
- * \brief: implementation of the Segment object
- */
-
-/*Include files: {{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include "./objects.h"
-#include "../Container/Container.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../include/include.h"
-/*}}}*/
-
-/*Segment constructors and destructors:*/
-/*FUNCTION Segment::Segment() default constructor {{{*/
-Segment::Segment(){
-	this->eid=UNDEF;
-	this->x1=UNDEF;
-	this->y1=UNDEF;
-	this->x2=UNDEF;
-	this->y2=UNDEF;
-}
-/*}}}*/
-/*FUNCTION Segment::Segment(int eid, IssmDouble x1,IssmDouble y1,IssmDouble x2, IssmDouble y2){{{*/
-Segment::Segment(int segment_eid, IssmDouble segment_x1,IssmDouble segment_y1,IssmDouble segment_x2, IssmDouble segment_y2){
-
-	this->eid=segment_eid;
-	this->x1=segment_x1;
-	this->y1=segment_y1;
-	this->x2=segment_x2;
-	this->y2=segment_y2;
-
-}
-/*}}}*/
-/*FUNCTION Segment::~Segment(){{{*/
-Segment::~Segment(){
-}
-/*}}}*/
-
-/*Object virtual functions definitions:*/
-/*FUNCTION Segment::Echo{{{*/
-void Segment::Echo(void){
-
-	_printLine_("Segment:");
-	_printLine_("   eid: " << eid);
-	_printLine_("   node 1: " << this->x1 << "|" << this->y1);
-	_printLine_("   node 2: " << this->x2 << "|" << this->y2);
-
-}
-/*}}}*/
-/*FUNCTION Segment::DeepEcho{{{*/
-void Segment::DeepEcho(void){
-	this->Echo();
-}
-/*}}}*/
-/*FUNCTION Segment::Id{{{*/
-int    Segment::Id(void){ return eid; }
-/*}}}*/
-/*FUNCTION Segment::MyRank{{{*/
-int    Segment::MyRank(void){ 
-	extern int my_rank;
-
-	return my_rank; 
-}
-/*}}}*/
-/*FUNCTION Segment::ObjectEnum{{{*/
-int Segment::ObjectEnum(void){
-
-	return SegmentEnum;
-
-}
-/*}}}*/
-/*FUNCTION Segment::copy {{{*/
-Object* Segment::copy() {
-	return new Segment(this->eid,this->x1,this->y1,this->x2,this->y2);
-
-}
-
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Segment.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Segment.h	(revision 12820)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*!\file Segment.h
- * \brief: header file for node object
- */
-
-#ifndef _SEGMENT_H_
-#define _SEGMENT_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-/*}}}*/
-
-class Segment: public Object{
-
-	public:
-		int eid;
-		IssmDouble x1;
-		IssmDouble y1;
-		IssmDouble x2;
-		IssmDouble y2;
-
-		/*Segment constructors, destructors {{{*/
-		Segment();
-		Segment(int eid,IssmDouble x1,IssmDouble y1, IssmDouble x2, IssmDouble y2);
-		~Segment();
-		/*}}}*/
-		/*Object virtual functions definitions:{{{ */
-		void  Echo();
-		void  DeepEcho();
-		int   Id(); 
-		int   MyRank();
-		int   ObjectEnum();
-		Object* copy();
-		/*}}}*/
-};
-
-#endif  /* _SEGMENT_H_ */
Index: sm/trunk-jpl/src/c/objects/Update.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Update.h	(revision 12820)
+++ 	(revision )
@@ -1,35 +1,0 @@
-/*!\file: Update.h: abstract class used by some objects to update their properties
- * \brief prototypes for Update.h
- */ 
-
-#ifndef _UPDATE_H_
-#define  _UPDATE_H_
-
-/*Headers:*/
-/*{{{*/
-#include "../shared/shared.h"
-/*}}}*/
-
-class Update{
-
-	public:
-
-		virtual void  InputUpdateFromVector(IssmDouble* vector, int name, int type)=0;
-		virtual void  InputUpdateFromVector(int* vector, int name, int type)=0;
-		virtual void  InputUpdateFromVector(bool* vector, int name, int type)=0; 
-		#ifdef _HAVE_DAKOTA_
-		virtual void  InputUpdateFromMatrixDakota(IssmDouble* matrix, int rows, int ncols, int name, int type)=0;
-		virtual void  InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type)=0;
-		virtual void  InputUpdateFromVectorDakota(int* vector, int name, int type)=0;
-		virtual void  InputUpdateFromVectorDakota(bool* vector, int name, int type)=0;
-		#endif
-		virtual void  InputUpdateFromConstant(IssmDouble constant, int name)=0;
-		virtual void  InputUpdateFromConstant(int constant, int name)=0;
-		virtual void  InputUpdateFromConstant(bool constant, int name)=0;
-		virtual void  InputUpdateFromSolution(IssmDouble* solution)=0;
-		virtual void  InputUpdateFromIoModel(int index, IoModel* iomodel)=0;
-
-};
-
-#endif //ifndef _UPDATE_H_
-
Index: sm/trunk-jpl/src/c/objects/Vertex.cpp
===================================================================
--- /issm/trunk-jpl/src/c/objects/Vertex.cpp	(revision 12820)
+++ 	(revision )
@@ -1,218 +1,0 @@
-/*!\file Vertex.c
- * \brief: implementation of the Vertex object
- */
-
-/*Include files: {{{*/
-#ifdef HAVE_CONFIG_H
-	#include <config.h>
-#else
-#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
-#endif
-
-#include <string.h>
-#include "./objects.h"
-#include "../EnumDefinitions/EnumDefinitions.h"
-#include "../shared/shared.h"
-#include "../include/include.h"
-/*}}}*/
-
-/*Vertex constructors and destructor:*/
-/*FUNCTION Vertex::Vertex() {{{*/
-Vertex::Vertex(){
-	return;
-}
-/*}}}*/
-/*FUNCTION Vertex::Vertex(int vertex_id, IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma){{{*/
-Vertex::Vertex(int vertex_id, int vertex_sid,IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma,int vertex_connectivity){
-	this->Init(vertex_id, vertex_sid,vertex_x, vertex_y, vertex_z, vertex_sigma,vertex_connectivity);
-}
-/*}}}*/
-/*FUNCTION Vertex::Vertex(int vertex_id, int vertex_sid,int i, IoModel* iomodel) {{{*/
-Vertex::Vertex(int vertex_id, int vertex_sid,int i, IoModel* iomodel){
-
-	_assert_(iomodel->Data(MeshXEnum) && iomodel->Data(MeshYEnum) && iomodel->Data(MeshZEnum));
-	_assert_(iomodel->Data(BedEnum) && iomodel->Data(ThicknessEnum) && iomodel->numbernodetoelementconnectivity);
-
-	this->Init(vertex_id, vertex_sid, iomodel->Data(MeshXEnum)[i],iomodel->Data(MeshYEnum)[i],iomodel->Data(MeshZEnum)[i],(iomodel->Data(MeshZEnum)[i]-iomodel->Data(BedEnum)[i])/(iomodel->Data(ThicknessEnum)[i]),iomodel->numbernodetoelementconnectivity[i]);
-
-}
-/*}}}*/
-/*FUNCTION Vertex::~Vertex() {{{*/
-Vertex::~Vertex(){
-	return;
-}
-/*}}}*/
-/*FUNCTION Vertex::Init{{{*/
-void Vertex::Init(int vertex_id, int vertex_sid,IssmDouble vertex_x, IssmDouble vertex_y, IssmDouble vertex_z, IssmDouble vertex_sigma,int vertex_connectivity){
-
-	/*all the initialization has been done by the initializer, just fill in the id: */
-	this->id=vertex_id;
-	this->sid=vertex_sid;
-	this->x=vertex_x;
-	this->y=vertex_y;
-	this->z=vertex_z;
-	this->sigma=vertex_sigma;
-	this->connectivity=vertex_connectivity;
-	this->dof=UNDEF;
-
-	return;
-}
-/*}}}*/
-
-/*Object virtual functions definitions:*/
-/*FUNCTION Vertex::Echo{{{*/
-void Vertex::Echo(void){
-
-	_printLine_("Vertex:");
-	_printLine_("   id: " << id);
-	_printLine_("   sid: " << sid);
-	_printLine_("   x: " << x);
-	_printLine_("   y: " << y);
-	_printLine_("   z: " << z);
-	_printLine_("   sigma: " << sigma);
-	_printLine_("   connectivity: " << connectivity);
-	_printLine_("   dof: " << dof);
-	_printLine_("   clone: " << clone);
-
-	return;
-}
-/*}}}*/
-/*FUNCTION Vertex::DeepEcho{{{*/
-void Vertex::DeepEcho(void){
-	this->Echo();
-}
-/*}}}*/
-/*FUNCTION Vertex::Id{{{*/
-int    Vertex::Id(void){ return id; }
-/*}}}*/
-/*FUNCTION Vertex::MyRank {{{*/
-int    Vertex::MyRank(void){ 
-	extern int my_rank;
-	return my_rank; 
-}
-/*}}}*/
-/*FUNCTION Vertex::ObjectEnum{{{*/
-int Vertex::ObjectEnum(void){
-
-	return VertexEnum;
-
-}
-/*}}}*/
-/*FUNCTION Vertex::copy {{{*/
-Object* Vertex::copy() {
-
-	return new Vertex(*this); 
-
-}
-/*}}}*/
-
-/* DofObject routines: */
-/*FUNCTION Vertex::DistributeDofs{{{*/
-void  Vertex::DistributeDofs(int* pdofcount){
-
-	int i;
-	extern int my_rank;
-	int dofcount;
-
-	dofcount=*pdofcount;
-	
-	if(this->clone){
-		/*This vertex is a clone! Don't distribute dofs, it will get them from another cpu!*/
-		return;
-	}
-
-	/*This vertex should distribute his dof, go ahead: */
-	this->dof=dofcount;
-	dofcount++;
-
-	/*Assign output pointers: */
-	*pdofcount=dofcount;
-
-}
-/*}}}*/
-/*FUNCTION Vertex::OffsetDofs{{{*/
-void  Vertex::OffsetDofs(int dofcount){
-	
-	int i;
-	extern int my_rank;
-	
-	if(this->clone){
-		/*This vertex is a clone, don't offset the dofs!: */
-		return;
-	}
-
-	/*This vertex should offset his dof, go ahead: */
-	this->dof+=dofcount;
-}
-/*}}}*/
-/*FUNCTION Vertex::ShowTrueDofs{{{*/
-void  Vertex::ShowTrueDofs(int* truedofs){
-
-	int j;
-	extern int my_rank;
-	
-	/*Are we a clone? : */
-	if(this->clone)return;
-
-	/*Ok, we are not a clone, just plug our dof into truedofs: */
-	truedofs[this->id-1]=this->dof;
-
-}
-/*}}}*/
-/*FUNCTION Vertex::UpdateCloneDofs{{{*/
-void  Vertex::UpdateCloneDofs(int* alltruedofs){
-
-	int j;
-	extern int my_rank;
-	
-	/*If we are not a clone, don't update, we already have dofs!: */
-	if(this->clone==0)return;
-
-	/*Ok, we are a clone node, but we did not create the dof for this vertex 
-	 * Therefore, our dof is garbage right now. Go pick it up in the alltruedofs: */
-	this->dof=alltruedofs[id-1];
-}
-/*}}}*/
-/*FUNCTION Vertex::SetClone {{{*/
-void  Vertex::SetClone(int* minranks){
-
-	extern int my_rank;
-
-	if (minranks[id-1]==my_rank){
-		this->clone=0;
-	}
-	else{
-		/*!there is a cpu with lower rank that has the same vertex, 
-		therefore, I am a clone*/
-		this->clone=1; 	
-	}
-
-}
-/*}}}*/
-
-/*Vertex management: */
-/*FUNCTION Vertex::Connectivity{{{*/
-int    Vertex::Connectivity(void){return connectivity;}
-/*}}}*/
-/*FUNCTION Vertex::Sid{{{*/
-int    Vertex::Sid(void){ return sid; }
-/*}}}*/
-/*FUNCTION Vertex::UpdateVertexPosition {{{*/
-void  Vertex::UpdatePosition(Vector* vz,Parameters* parameters,IssmDouble* thickness,IssmDouble* bed){
-
-	IssmDouble oldz,newz;
-	IssmDouble dt,velz;
-
-	/*Get time stepping*/
-	parameters->FindParam(&dt,TimesteppingTimeStepEnum);
-
-	/*sigma remains constant. z=bed+sigma*thickness*/
-	oldz = this->z;
-	newz = bed[this->dof]+sigma*thickness[this->dof];
-	velz = (newz-oldz)/dt;
-	this->z = newz;
-
-	/*put vz in vector*/
-	vz->SetValue(this->dof,velz,INS_VAL);
-}
-/*}}}*/
Index: sm/trunk-jpl/src/c/objects/Vertex.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/Vertex.h	(revision 12820)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*! \file Vertex.h 
- *  \brief: header file for vertex object
- */
-
-#ifndef _VERTEX_H_
-#define _VERTEX_H_
-
-/*Headers:*/
-/*{{{*/
-#include "./Object.h"
-class IoModel;
-class Vector;
-class Parameters;
-#include "../shared/Exceptions/exceptions.h"
-#include "../toolkits/toolkits.h"
-#include "../include/include.h"
-
-/*}}}*/
-
-
-class Vertex: public Object{
-
-	public: 
-
-		int    id;
-		int    sid;            //sid for "serial" id, ie the rank of this vertex in the vertices dataset, if the dataset was serial on 1 cpu.
-		IssmDouble x;
-		IssmDouble y;
-		IssmDouble z;
-		IssmDouble sigma;          //sigma coordinate: (z-bed)/thickness
-		int    connectivity;   //number of vertices connected to this vertex
-
-		/*dof management: */
-		int    clone;
-		int    dof; //dof to recover values in a vertex indexed vector
-
-		/*Vertex constructors, destructors {{{*/
-		Vertex();
-		Vertex(int id, int sid,IssmDouble x, IssmDouble y, IssmDouble z, IssmDouble sigma, int connectivity); 
-		void Init(int id, int sid, IssmDouble x, IssmDouble y, IssmDouble z, IssmDouble sigma,int connectivity);
-		Vertex(int id, int sid, int i, IoModel* iomodel);
-		~Vertex();
-		/*}}}*/
-		/*Object virtual functions definitions:{{{ */
-		void  Echo();
-		void  DeepEcho();
-		int   Id(); 
-		int   MyRank();
-		int   ObjectEnum();
-		Object* copy();
-		/*}}}*/
-		/*DofObject routines {{{*/
-		void  DistributeDofs(int* pdofcount);
-		void  OffsetDofs(int dofcount);
-		void  ShowTrueDofs(int* borderdofs);
-		void  UpdateCloneDofs(int* allborderdofs);
-		void  SetClone(int* minranks);
-		/*}}}*/
-		/*Vertex management: {{{*/
-		int   Sid(void); 
-		int   Connectivity(void); 
-		void  UpdatePosition(Vector* vz,Parameters* parameters,IssmDouble* thickness,IssmDouble* bed);
-		/*}}}*/
-};
-#endif  /* _VERTEX_H */
Index: sm/trunk-jpl/src/c/objects/objects.h
===================================================================
--- /issm/trunk-jpl/src/c/objects/objects.h	(revision 12820)
+++ 	(revision )
@@ -1,185 +1,0 @@
-/* \file objects.h
- * \brief: prototype header for all objects.
- */
-
-#ifndef ALL_OBJECTS_H_
-#define ALL_OBJECTS_H_
-
-/*Abstract classes: */
-#include "./Object.h"
-
-/*Objects: */
-#include "./Hook.h"
-#include "./DofIndexing.h"
-#include "./Vertex.h"
-#include "./Node.h"
-#include "./Segment.h"
-#include "./IoModel.h"
-#include "./Patch.h"
-#include "./Update.h"
-
-/*Constraints: */
-#include "./Constraints/Constraint.h"
-#include "./Constraints/SpcStatic.h"
-#include "./Constraints/SpcTransient.h"
-#include "./Constraints/SpcDynamic.h"
-
-/*Gauss*/
-#include "./Gauss/GaussTria.h"
-#include "./Gauss/GaussPenta.h"
-
-/*Loads: */
-#include "./Loads/Load.h"
-#include "./Loads/Friction.h"
-#include "./Loads/Icefront.h"
-#include "./Loads/Numericalflux.h"
-#include "./Loads/Riftfront.h"
-#include "./Loads/Penpair.h"
-#include "./Loads/Pengrid.h"
-
-/*Elements: */
-#include "./Elements/Element.h"
-#include "./Elements/Penta.h"
-#include "./Elements/PentaHook.h"
-#include "./Elements/PentaRef.h"
-#include "./Elements/Tria.h"
-#include "./Elements/TriaHook.h"
-#include "./Elements/TriaRef.h"
-
-/*KML parsing objects: */
-#include "./KML/KML_Attribute.h"
-#include "./KML/KML_Comment.h"
-#include "./KML/KML_ColorStyle.h"
-#include "./KML/KML_Container.h"
-#include "./KML/KML_Document.h"
-#include "./KML/KML_Feature.h"
-#include "./KML/KML_File.h"
-#include "./KML/KML_Folder.h"
-#include "./KML/KML_Geometry.h"
-#include "./KML/KML_GroundOverlay.h"
-#include "./KML/KML_Icon.h"
-#include "./KML/KML_LatLonBox.h"
-#include "./KML/KML_LinearRing.h"
-#include "./KML/KML_LineString.h"
-#include "./KML/KML_LineStyle.h"
-#include "./KML/KML_MultiGeometry.h"
-#include "./KML/KML_Object.h"
-#include "./KML/KML_Overlay.h"
-#include "./KML/KML_Point.h"
-#include "./KML/KML_Placemark.h"
-#include "./KML/KML_Polygon.h"
-#include "./KML/KML_PolyStyle.h"
-#include "./KML/KML_Style.h"
-#include "./KML/KML_StyleSelector.h"
-#include "./KML/KML_SubStyle.h"
-#include "./KML/KML_Unknown.h"
-#include "./KML/KMLFileReadUtils.h"
-
-/*Option parsing objects: */
-#include "./Options/Option.h"
-#include "./Options/OptionDouble.h"
-#include "./Options/OptionLogical.h"
-#include "./Options/OptionChar.h"
-#include "./Options/OptionStruct.h"
-#include "./Options/OptionCell.h"
-#include "./Options/OptionUtilities.h"
-
-/*Inputs: */
-#include "./Inputs/Input.h"
-#include "./Inputs/BoolInput.h"
-#include "./Inputs/DoubleInput.h"
-#include "./Inputs/IntInput.h"
-#include "./Inputs/PentaP1Input.h"
-#include "./Inputs/TriaP1Input.h"
-#include "./Inputs/ControlInput.h"
-#include "./Inputs/DatasetInput.h"
-#include "./Inputs/TransientInput.h"
-
-/*ElementResults: */
-#include "./ElementResults/ElementResult.h"
-#include "./ElementResults/DoubleElementResult.h"
-#include "./ElementResults/TriaP1ElementResult.h"
-#include "./ElementResults/PentaP1ElementResult.h" 
-#include "./ElementResults/BoolElementResult.h"
-
-/*ExternalResults: */
-#include "./ExternalResults/ExternalResult.h"
-#include "./ExternalResults/BoolExternalResult.h"
-#include "./ExternalResults/DoubleExternalResult.h"
-#include "./ExternalResults/DoubleVecExternalResult.h"
-#include "./ExternalResults/DoubleMatExternalResult.h"
-#include "./ExternalResults/IntExternalResult.h"
-#include "./ExternalResults/PetscVecExternalResult.h"
-#include "./ExternalResults/StringExternalResult.h"
-
-/*Materials: */
-#include "./Materials/Material.h"
-#include "./Materials/Matice.h"
-#include "./Materials/Matpar.h"
-
-/*Numerics:*/
-#include "./Numerics/ElementMatrix.h"
-#include "./Numerics/ElementVector.h"
-#include "./Numerics/Vector.h"
-#include "./Numerics/Matrix.h"
-
-/*Params: */
-#include "./Params/BoolParam.h"
-#include "./Params/DoubleMatParam.h"
-#include "./Params/DoubleTransientMatParam.h"
-#include "./Params/DoubleMatArrayParam.h"
-#include "./Params/DoubleParam.h"
-#include "./Params/DoubleVecParam.h"
-#include "./Params/IntParam.h"
-#include "./Params/IntVecParam.h"
-#include "./Params/IntMatParam.h"
-#include "./Params/FileParam.h"
-#include "./Params/Param.h"
-#include "./Params/MatrixParam.h"
-#include "./Params/VectorParam.h"
-#include "./Params/StringArrayParam.h"
-#include "./Params/StringParam.h"
-#include "./Params/TransientParam.h"
-
-/*C objects: */
-#include "./Contour.h"
-#include "./FemModel.h"
-#include "./OptArgs.h"
-#include "./OptPars.h"
-
-/*Bamg: */
-#include "./Bamg/BamgOpts.h"
-#include "./Bamg/BamgGeom.h"
-#include "./Bamg/BamgMesh.h"
-#include "./Bamg/Metric.h"
-#include "./Bamg/DoubleAndInt.h"
-#include "./Bamg/Direction.h"
-#include "./Bamg/BamgVertex.h"
-#include "./Bamg/AdjacentTriangle.h"
-#include "./Bamg/Edge.h"
-#include "./Bamg/GeomVertex.h"
-#include "./Bamg/GeomEdge.h"
-#include "./Bamg/Curve.h"
-#include "./Bamg/Triangle.h"
-#include "./Bamg/ListofIntersectionTriangles.h"
-#include "./Bamg/GeomSubDomain.h"
-#include "./Bamg/SubDomain.h"
-#include "./Bamg/VertexOnGeom.h"
-#include "./Bamg/VertexOnVertex.h"
-#include "./Bamg/VertexOnEdge.h"
-#include "./Bamg/CrackedEdge.h"
-#include "./Bamg/Mesh.h"
-#include "./Bamg/Geometry.h"
-#include "./Bamg/BamgQuadtree.h"
-#include "./Bamg/SetOfE4.h"
-
-/*Kriging*/
-#include "./Kriging/Variogram.h"
-#include "./Kriging/GaussianVariogram.h"
-#include "./Kriging/ExponentialVariogram.h"
-#include "./Kriging/SphericalVariogram.h"
-#include "./Kriging/PowerVariogram.h"
-#include "./Kriging/Quadtree.h"
-#include "./Kriging/Observation.h"
-
-#endif
