Index: /issm/trunk-jpl/src/m/array/ArrayOperations.js
===================================================================
--- /issm/trunk-jpl/src/m/array/ArrayOperations.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/array/ArrayOperations.js	(revision 19721)
@@ -15,4 +15,9 @@
 function ArrayMin(array){ //{{{
 	return Math.min.apply(null,array);
+} //}}}
+function ArraySum(array){ //{{{
+	var sum=0;
+	for(var i=0;i<array.length;i++)sum+=array[i];
+	return sum;
 } //}}}
 function ArrayMin2D(array){ //{{{
@@ -47,6 +52,6 @@
 	var list= new Array(width*length);
 
-	for (i=0;i<length;i++){
-		for(j=0;j<width;j++){
+	for(var i=0;i<length;i++){
+		for(var j=0;j<width;j++){
 			list[i*width+j]=matrix[i][j];
 		}
@@ -68,4 +73,11 @@
 	for (i=0;i<array.length;i++)notarray[i]=-array[i];
 	return notarray;
+} //}}}
+function ArrayAnyNaN(array) { //{{{
+
+	for(var i=0;i<array.length;i++){
+		if (isNaN(array[i])) return 1;
+	}
+	return 0;
 } //}}}
 function ArrayAnd(array1,array2) { //{{{
@@ -98,2 +110,30 @@
 	return indices;
 } //}}}
+function ArrayFindNot(array,value) { //{{{
+	
+	//find number of indices
+	var count=0;
+	for (i=0;i<array.length;i++)if(array[i]!=value)count++;
+
+	//allocate:
+	var indices= NewArrayFill(count,0);
+
+	//fill in:
+	count=0;
+	for (i=0;i<array.length;i++){
+		if(array[i]!=value){
+			indices[count]=i;
+			count++;
+		}
+	}
+	return indices;
+} //}}}
+function Create2DArray(rows,cols) { //{{{
+	var arr = [];
+
+	for (var i=0;i<rows;i++) {
+		arr[i] = new Array(cols);
+	}
+
+	return arr;
+} //}}}
Index: /issm/trunk-jpl/src/m/classes/mesh2d.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/mesh2d.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/classes/mesh2d.js	(revision 19721)
@@ -44,4 +44,13 @@
 			fielddisplay(this,"epsg","EPSG code (ex: 3413 for UPS Greenland, 3031 for UPS Antarctica)");
 		} //}}}
+		this.domaintype=function (){ // {{{
+			return '2Dhorizontal';
+		} // }}}
+		this.dimension = function () { //{{{
+			return 2;
+		} //}}}
+		this.elementtype = function() {//{{{
+			return 'Tria';
+		} // }}}
 	//properties 
 	// {{{
Index: /issm/trunk-jpl/src/m/classes/pairoptions.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/pairoptions.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/classes/pairoptions.js	(revision 19721)
@@ -0,0 +1,269 @@
+//PAIROPTIONS class definition
+//
+//   Usage:
+//      pairoptions=pairoptions();
+//      pairoptions=pairoptions('module',true,'solver',false);
+
+function pairoptions(args) { 
+
+
+	//methods
+	this.constructor = function (args) {// {{{
+
+		//initialize list
+		if (args.length==0){
+			this.list=[];
+		}
+		else{
+
+			//check length of input
+			if (args.length % 2){
+				throw Error('pairoptions error message: invalid parameter/value pair arguments') 
+			}
+			numoptions = args.length/2;
+
+			//Allocate memory
+			this.list= Create2DArray(numoptions,3);
+
+			//go through args and build list of obj
+			for (i=0;i<numoptions;i++){
+				if (typeof args[2*i] === 'string'){
+					this.list[i][0]=args[2*i];
+					this.list[i][1]=args[2*i+1];
+					this.list[i][2]=false;  //used?
+				}
+				else{
+					//option is not a string, ignore it
+					console.log(sprintf('%s%i%s\n','WARNING: option number ',i,' is not a string, it will be ignored'));
+					this.list[i][0]=[];
+					this.list[i][1]=[];
+					this.list[i][2]=[];
+					continue
+				}
+			}
+		}
+	}// }}}
+	this.addfield = function (field, value){ // {{{
+		if (typeof field === 'string'){
+			this.list.push([field,value,false]);
+		}
+	}// }}}
+	this.numoptions = function (){ // {{{
+		return this.list.length;
+	}// }}}
+	this.addfielddefault = function (field,value){ // {{{
+		//ADDFIELDDEFAULT - add a field to an options list if it does not exist
+		if (typeof field === 'string'){
+			if (!this.exist(field)){
+				this.list.push([field,value,true]); //true is a default so user will not be notified if not used
+			}
+		}
+	} // }}}
+	this.AssignObjectFields = function(object){ // {{{
+		//ASSIGNOBJECTFIELDS - assign object fields from options
+		for (i=0;i<list.length;i++){
+			fieldname=list[i][0];
+			fieldvalue=list[i][1];
+			if (fieldname in object){
+				obj2[fieldname]=fieldvalue;
+			}
+			else{
+				console.log(sprintf("%s'%s'%s%s\n",'WARNING: ',fieldname, 'is not a property of ',typeof object));
+			}
+		}
+	} // }}}
+	this.changefieldvalue = function(field,newvalue){ // {{{
+		//CHANGEOPTIONVALUE - change the value of an option in an option list
+
+		var found=0;
+		for (i=0;i<this.list.length;i++){
+			if (this.list[i][0] === field){
+				found=1;
+			}
+		}
+
+		if (found==0){
+			this.list.push([field,newvalue,true]); // do not notify user if unused
+		}
+		else{
+			for (i=0;i<this.list.length;i++){
+				if (this.list[i][0] === field){
+					this.list[i][1] = newvalue;
+				}
+			}
+		}
+	} // }}}
+	this.deleteduplicates = function(warn){ // {{{
+		//DELETEDUPLICATES - delete duplicates in an option list
+
+		//track the first occurrence of each option
+		var indices=NewArrayFill(this.list.length,0);
+		for (i=0;i<this.list.length;i++){
+			if(indices[i]==0){
+				for(var j=i+1;j<this.list.length;j++){
+					if (this.list[i][0] === this.list[j][0])indices[j]=1;
+				}
+			}
+		}
+		sumindices=ArraySum(indices);
+
+		//remove duplicates from the options list
+		newlist=Create2DArray(sumindices,3);
+		var count=0;
+		for (i=0;i<this.list.length;i++){
+			if (indices[i]==1) if (warn) console.log(sprintf("%s%s%s\n",'WARNING: option ', this.list[i,0],' appeared more than once. Only its first occurrence will be kept'));
+			else{
+				newlist[count]=this.list[i];
+				count++;
+			}
+		}
+	} // }}}
+	this.displayunused = function (){ // {{{
+		//DISPLAYUNUSED - display unused options
+
+		for (i=0;i<this.list.length;i++){
+			if (!(this.list[i][2])){
+				console.log(sprintf("%s%s%s\n",'WARNING: option ',this.list[i][0],' was not used'));
+			}
+		}
+	}// }}}
+	this.disp = function (){ //{{{
+		if (this.list.length){
+			console.log(sprintf('   pairoptions: (%i)\n',this.list.length));
+			for (i=0;i<this.list.length;i++){
+				if (typeof this.list[i][1] === 'string'){
+					console.log(sprintf("     field: '%s' value(string): ''%s''",this.list[i][0],this.list[i][1]));
+				}
+				else if( typeof this.list[i][1] === 'number'){
+					console.log(sprintf("     field: '%s' value(number): %g",this.list[i][0],this.list[i][1]));
+				}
+				else if( IsArray(this.list[i][1])){
+					console.log(sprintf("     field: '%s' value(array): [%i]",this.list[i][0],this.list[i][1].length));
+				}
+			}
+		}
+		else{
+			console.log(sprintf('   list: empty'));
+		}
+	}// }}}
+	this.exist = function (field) { //{{{
+
+		//EXIST - check if the option exists
+		//some argument checking: 
+		if (!(typeof field === 'string')){
+			throw Error('exist error message: field should be a string');
+		}
+
+		//Recover option
+		var bool=0;
+		for (var i=0;i<this.list.length;i++){
+			if (this.list[i][0] === field){
+				bool=1;
+				this.list[i][2]=1; //It is a default so user will not be notified if not used
+				break;
+			}
+		}
+		return bool;
+	} // }}}
+	this.fieldoccurrences = function(field){ // {{{
+
+		//FIELDOCCURRENCES - get number of occurrence of a field
+		var num=0;
+
+		//check input 
+		if (!(typeof field === 'string')){
+			throw Error('exist error message: field should be a string');
+		}
+
+		//count number of occurrences:
+		for (i=0;i<this.list.length;i++) if (this.list[i][0] === field)num++;
+
+		return num;
+
+	} // }}}
+	this.getfieldvalue = function(field){ // {{{
+		//GETOPTION - get the value of an option
+		//
+		//   Usage:
+		//      value=pairoptions.getfieldvalue(field,varargin)
+		//
+		//   Find an option value from a field. A default option
+		//   can be given in input if the field does not exist
+		//
+		//   Examples:
+		//      value=pairoptions.getfieldvalue('caxis');
+		//      value=pairoptions.getfieldvalue('caxis',[0 2]);
+
+		//some argument checking: 
+		if(!(arguments.length==1 | arguments.length==2)){
+			error('pairoptions usage error: getfieldvalue bad usage');
+		}
+
+		if (!(typeof field === 'string')){
+			throw Error('pairoptions error message: field should be a string');
+		}
+
+		//Recover option
+		for(var i=0;i<this.list.length;i++){
+			if (this.list[i][0] === field){
+				this.list[i][2]=1; //option used
+				return value=this.list[i][1];
+			}
+		}
+
+		//The option has not been found, output default if provided
+		if (arguments.length==2){
+			return arguments[1];
+		}
+		else{
+			throw Error(sprintf("%s%s%s\n",'error message: field ',field,' has not been provided by user (and no default value has been specified)'));
+		}
+	} // }}}
+	this.removefield = function(field,warn){// {{{
+
+		//REMOVEFIELD - delete a field in an option list
+		//
+		//   Usage:
+		//      options.removefield(field,warn)
+		//
+		//   if warn==1 display an info message to warn user that
+		//   some of his options have been removed.
+
+		//check if field exists
+		if (this.exist(field)){
+
+			var indices;
+			var count;
+
+			//find where the field is located
+			indices=NewArrayFill(this.list.length,1);
+			for (i=0;i<this.list.length;i++)if(this.list[i][1] === field)indices[i]=0;
+			sumindices=ArraySum(indices);
+
+			//remove duplicates from the options list
+			newlist=Create2DArray(sumindices,3);
+
+			count=0;
+			for (i=0;i<this.list.length;i++){
+				if(!(this.list[i][1] === field)){
+					newlist[count]=this.list[i];
+					count++;
+				}
+			}
+			this.list=newlist;
+
+			//warn user if requested
+			if (warn){
+				console.log(sprintf("%s%s%s\n",'removefield info: option ',field,' has been removed from the list of options.'));
+			}
+		}
+	} // }}}
+	this.marshall = function(fid,firstindex){// {{{
+
+		throw Error('pairoptions marshall error: not implemented yet!');
+	} // }}}
+
+	//properties 
+	list         = [];
+	this.constructor(args);
+}
Index: /issm/trunk-jpl/src/m/classes/plotoptions.js
===================================================================
--- /issm/trunk-jpl/src/m/classes/plotoptions.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/classes/plotoptions.js	(revision 19721)
@@ -0,0 +1,166 @@
+//PLOTOPTIONS class definition
+//
+//   Usage:
+//      plotoptions = plotoptions(varargin)
+
+function plotoptions(args) {
+	//methods
+	 this.disp = function (){ // {{{
+		 console.log(sprintf('\nplotoptions = \n'));
+		 console.log(sprintf('   figurenumber: %i',this.figurenumber));
+		 console.log(sprintf('   numberofplots: %i',this.numberofplots));
+		 if (this.list.length){
+			 for (var i=0;i<this.list.length;i++){
+				 console.log(sprintf('\n   options of plot number %i',i+1));
+				 this.list[i].disp();
+			 }
+		 }
+		 else{
+			 console.log(sprintf('   list: empty'));
+		 }
+	 }
+	 //}}}
+	 this.constructor = function (args){ // {{{
+
+		 //check length of input
+		 if (args.length % 2){
+			 for (i=0;i<args.length;i+=2){
+				 if (!(typeof args[i] === 'string')){
+					 console.log('Last valid option: ' + args[i-2]);
+					 break;
+				 }
+			 }
+			 throw Error('plotoptions error message: invalid parameter/value pair arguments');
+		 }
+
+		 //go through varargin and build list (like pairoptions)
+		 var rawoptions=new pairoptions(args);
+		 numoptions=rawoptions.numoptions();
+
+		 var counter=0;
+		 for (i=0;i<numoptions;i++){
+			 if(typeof args[2*i] === 'string')counter++;
+		 }
+		 rawlist=Create2DArray(counter,2);
+		 var counter=0;
+		 for (i=0;i<numoptions;i++){
+			 optionname=args[2*i];
+			 optionval=args[2*i+1];
+			 if(typeof optionname === 'string'){
+				 rawlist[counter][0]=optionname;
+				 rawlist[counter][1]=optionval;
+				 counter++;
+			 }
+			 else{
+				 //option is not a string, ignore it
+				 console.log(sprintf("%s%i%s\n",'WARNING: option number ',i,' is not a string, it will be ignored'));
+				 rawlist[counter]=[];
+				 continue
+			 }
+		 }
+		 
+			 
+		 //get number of data to be plotted
+		 numberofplots=rawoptions.fieldoccurrences('data');
+		 this.numberofplots=numberofplots;
+
+		 //figure out wether alloptions flog is on
+		 if (rawoptions.getfieldvalue('alloptions','off') === 'on') allflag=1;
+		 else allflag=0;
+
+		 //initialize list
+		 var list=new Array(numberofplots);
+		 for (i=0;i<numberofplots;i++){
+			 list[i]=new pairoptions([]);
+		 }
+		 		 
+		//process plot options
+		 for(var i=0;i<rawlist.length;i++){
+
+			 //If alloptions flag has is on, apply to all plots
+			 if (allflag & !(rawlist[i][0] === 'data') & (rawlist[i][0].indexOf('#') == -1)){
+				 for(var j=0;j<numberofplots;j++){
+					 list[j].addfield(rawlist[i][0],rawlist[i][1]);
+				 }
+			 }
+			 else if (rawlist[i][0].indexOf('#') != -1){ //option contains '#'
+
+				 //get suplot(s) associated
+				 string=rawlist[i][0].split('#');
+				 plotnums=string[1];
+				 field=string[0];
+
+				 //divide plotnums if there is a comma ','
+				 plotnums=plotnums.split(',');
+
+				 //loop over plotnums
+				 for (k=0;k<plotnums.length;k++){
+					 plotnum=plotnums[k];
+
+					 //Empty
+					 if (plotnum === '') continue;
+
+					 else if (plotnum === 'all'){ //pound all
+						 for(var j=0;j<numberofplots;j++){
+							 list[j].addfield(field,rawlist[i][1]);
+						 }
+					 }
+					 else if (plotnum.indexOf('-')!=-1){  //pound i-j
+						 nums=plotnum.split('-');
+						 if (nums.length!=2) continue;
+						 if ((nums[0] == '') | (nums[1] === '')){
+							 throw Error(sprintf("%s%s\n",'the option #i-j is not set properly for ',field));
+						 }
+						 for (j=(Number(nums[0])-1);j<(Number(nums[1])); j++){
+							 list[j].addfield(field,rawlist[i][1]);
+						 }
+					 }
+					 else{ //pound i
+						 //assign to subplot
+						 if (Number(plotnum)>numberofplots){
+							throw Error(sprintf("%s%s%s%i%s\n",'plotoptions error message: ',field,' cannot be assigned (',plotnum,' exceeds maximum number of plot)'));
+						 }
+						 list[Number(plotnum)-1].addfield(field,rawlist[i][1]);
+					 }
+				 }
+			 }
+			 else{ //assign option field to corresponding subplot
+
+				 
+				 //go through all subplot and assign to the first one free
+				 var inc=0;
+				 
+				 while (inc<numberofplots){
+					
+					 if (!list[inc].exist(rawlist[i][0])){
+						 list[inc].addfield(rawlist[i][0],rawlist[i][1]);
+						 break
+					 }
+					 else inc++;
+				 }
+
+				 if (inc>numberofplots-1){
+					 console.log(sprintf("%s%s%s\n",'plot info message: too many ',rawlist[i][0],' options'));
+				 }
+			 }
+		 }
+
+		 //check that there is no duplicates
+		 for (var i=0;i<numberofplots;i++) list[i].deleteduplicates();
+
+		 //Get figure number (should be in options for subplot 1)
+		 this.figurenumber=list[0].getfieldvalue('figure',1);
+		 list[0].removefield('figure',0);
+
+		 //asign output
+		 this.list=list;
+
+	 } //}}}
+    //properties 
+	 // {{{
+	 numberofplots = 0;
+	 figurenumber  = 1;
+	 list          = [];
+	 this.constructor(args);
+	 //}}}
+}
Index: /issm/trunk-jpl/src/m/geometry/FlagElements.js
===================================================================
--- /issm/trunk-jpl/src/m/geometry/FlagElements.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/geometry/FlagElements.js	(revision 19721)
@@ -34,5 +34,5 @@
 			for (i=0;i<md.mesh.numberofelements;i++)
 				var sum=0;
-				for(j=0;j<md.mesh.elements[0].length;j++){
+				for(var j=0;j<md.mesh.elements[0].length;j++){
 					sum += region[md.mesh.element[i][j]-1];
 				}
@@ -40,9 +40,9 @@
 		}
 		else{
-			console.error('Flaglist for region must be of same size as number of elements in model');
+			throw Error('Flaglist for region must be of same size as number of elements in model');
 		}
 	}
 	else{
-		console.error('Invalid region option');
+		throw Error('Invalid region option');
 	}
 	return flag;
Index: /issm/trunk-jpl/src/m/mesh/triangle.js
===================================================================
--- /issm/trunk-jpl/src/m/mesh/triangle.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/mesh/triangle.js	(revision 19721)
@@ -50,5 +50,5 @@
 	md.mesh.vertexonboundary=new Float64Array(md.mesh.numberofvertices); 
 
-	for (i=0;i<md.mesh.segments.length;i++) for(j=0;j<2;j++) md.mesh.vertexonboundary[md.mesh.segments[i][j]-1]=1;
+	for (i=0;i<md.mesh.segments.length;i++) for(var j=0;j<2;j++) md.mesh.vertexonboundary[md.mesh.segments[i][j]-1]=1;
 
 	//Now, build the connectivity tables for this mesh.
Index: /issm/trunk-jpl/src/m/miscellaneous/fielddisplay.js
===================================================================
--- /issm/trunk-jpl/src/m/miscellaneous/fielddisplay.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/miscellaneous/fielddisplay.js	(revision 19721)
@@ -85,5 +85,5 @@
 		}
 		else{
-			console.error("fielddisplay error message: format for comment not supported yet");
+			throw Error("fielddisplay error message: format for comment not supported yet");
 		}
 	}
Index: /issm/trunk-jpl/src/m/parameterization/setmask.js
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setmask.js	(revision 19720)
+++ /issm/trunk-jpl/src/m/parameterization/setmask.js	(revision 19721)
@@ -26,5 +26,5 @@
 	//some checks on list of arguments
 	if (!((arguments.length==3) | (arguments.length==5))){
-		console.error('mask error message: wrong usage.');
+		throw Error('mask error message: wrong usage.');
 	}
 
@@ -34,8 +34,8 @@
 		}
 		else{
-			console.error('mask error message: wrong field specified. Only icedomain allowed for now.');
+			throw Error('mask error message: wrong field specified. Only icedomain allowed for now.');
 		}
 		if (IsArray(icedomain)){
-			console.error('setmask error message: icedomain should be an array!');
+			throw Error('setmask error message: icedomain should be an array!');
 		}
 	}
@@ -59,10 +59,10 @@
 	vertexonfloatingice=NewArrayFill(md.mesh.numberofvertices,0);
 	vertexongroundedice=NewArrayFill(md.mesh.numberofvertices,0);
-	pos=ArrayFind(elementongroundedice,1); for (i=0;i<pos.length;i++)for(j=0;j<3;j++) vertexongroundedice[md.mesh.elements[i,j]-1]=1;
+	pos=ArrayFind(elementongroundedice,1); for (i=0;i<pos.length;i++)for(var j=0;j<3;j++) vertexongroundedice[md.mesh.elements[i,j]-1]=1;
 	pos=ArrayFind(vertexongroundedice,0); for (i=0;i<pos.length;i++)vertexonfloatingice[i]=1;
 
 	//level sets
 	groundedice_levelset=vertexongroundedice;
-	pos=ArrayFind(vertexongroundedice,0);for(i=0;i<pos.length;i++) groundedice_levelset[i]=-1;
+	pos=ArrayFind(vertexongroundedice,0);for(var i=0;i<pos.length;i++) groundedice_levelset[i]=-1;
 	md.mask.groundedice_levelset=groundedice_levelset;
 
@@ -71,5 +71,5 @@
 		//use contourtomesh to set ice values inside ice domain
 		[vertexinsideicedomain,elementinsideicedomain]=ContourToMesh(elements,x,y,icedomain,'node',1);
-		pos=ArrayFind(vertexinsideicedomain,1.0);for(i=0;i<pos.length;i++) md.mask.ice_levelset[pos]=-1;
+		pos=ArrayFind(vertexinsideicedomain,1.0);for(var i=0;i<pos.length;i++) md.mask.ice_levelset[pos]=-1;
 	}
 	else{
Index: /issm/trunk-jpl/src/m/plot/checkplotoptions.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/checkplotoptions.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/checkplotoptions.js	(revision 19721)
@@ -0,0 +1,239 @@
+function checkplotoptions(md,options){
+	//PARSE_OPTIONS - build a structure that holds all plot options
+	//
+	//   Usage:
+	//      checkplotoptions(md,options);
+	//
+	//   See also: PLOTMODEL
+
+	//units
+	if (options.exist('unit')){
+		if (options.getfieldvalue('unit') === 'km'){
+			options.changefieldvalue('unit',10^-3);
+		}
+		if (options.getfieldvalue('unit') === '100km'){
+			options.changefieldvalue('unit',10^-5);
+		}
+	}
+
+	//density
+	if (options.exist('density')){
+		density=options.getfieldvalue('density');
+		options.changefieldvalue('density',Math.abs(Math.ceil(density)));
+	}
+
+	//Show section
+	if (options.exist('showsection')){
+		if (options.getfieldvalue('showsection') === 'on'){
+			options.changefieldvalue('showsection',4);
+		}
+	}
+
+	//smooth values
+	if (options.exist('smooth')){
+		if (options.getfieldvalue('smooth') === 'on'){
+			options.changefieldvalue('smooth',0);
+		}
+	}
+
+	//contouronly values
+	if (options.exist('contouronly')){
+		if (options.getfieldvalue('contouronly') === 'on'){
+			options.changefieldvalue('contouronly',1);
+		}
+	}
+
+	//Colorbar;
+	if (options.exist('colorbar')){
+		if (options.getfieldvalue('colorbar') === 'on'){
+			options.changefieldvalue('colorbar',1);
+		}
+		else if (options.getfieldvalue('colorbar') === 'off'){
+			options.changefieldvalue('colorbar',0);
+		}
+	}
+
+	//text
+	if (options.exist('text')){
+
+		//1: textvalue
+		textvalues=options.getfieldvalue('text');
+
+		//ischar if only one expstyle -> create a cell
+		if (typeof textvalues === 'string'){
+			textvalues=[textvalues];
+			numtext=1;
+		}
+		else if (IsArray(textvalues)){
+			numtext=textvalues.length;
+		}
+		else throw Error("plot error message: ''text'' option should be either a string or a cell");
+
+		//2: textweight
+		if (options.exist('textweight')){
+
+			textweightvalues=options.getfieldvalue('textweight');
+
+			//ischar if only one textweight -> create a cell
+			if (typeof textweightvalues === 'string'){
+				textweightvalues=[textweightvalues];
+			}
+			else if (!IsArray(textweightvalues)){
+				throw Error("plot error message: ''textweight'' option should be either a string or a cell");
+			}
+		}
+		else{
+			textweightvalues=['n'];
+		}
+		if (textweightvalues.length==1){
+			var value=textweightvalues[0];
+			for (var i=0;i<numtext-1;i++)textweightvalues.push(value);
+		}
+
+		//3: textsize
+		if (options.exist('textsize')){
+			textsizevalues=options.getfieldvalue('textsize');
+		}
+		//ischar if only one textsize -> create a cell
+		if (typeof textsizevalues === 'number'){
+			textsizevalues=[textsizevalues];
+		}
+		else if (!IsArray(textsizevalues)){
+			throw Error("plot error message: ''textsize'' option should be either a number or a cell");
+		}
+		else{
+			textsizevalues=[14];
+		}
+		if (textsizevalues.length==1){
+			var value=textsizevalues[0];
+			for (var i=0;i<numtext-1;i++)textsizevalues.push(value);
+		}
+			
+		//4: textcolor
+		if (options.exist('textcolor')){
+			textcolorvalues=options.getfieldvalue('textcolor');
+		}
+		if (typeof textcolorvalues === 'string'){ //ischar if only one textcolor -> create a cell
+			textcolorvalues=[textcolorvalues];
+		}
+		else if (!IsArray(textcolorvalues)){
+			throw Error("plot error message: ''textcolor'' option should be either a string or a cell");
+		}
+		else textcolorvalues=['k'];
+
+		if (textcolorvalues.length==1){
+			var value=textcolorvalues[0];
+			for (var i=0;i<numtext-1;i++)textcolorvalues.push(value);
+		}
+		
+		//5: textposition
+		if (options.exist('textposition')){
+			textpositionvalues=options.getfieldvalue('textposition');
+		}
+		//ischar if only one textposition -> create a cell
+		if (typeof textpositionvalues === 'number'){
+			textpositionvalues=[textpositionvalues];
+		}
+		else if(!IsArray(textpositionvalues)){
+			throw Error("plot error message: ''textposition'' option should be either a string or a cell");
+		}
+		else throw Error("plot error message: ''textposition'' option is missing");
+			
+		//6: textrotation
+		if (options.exist('textrotation')){
+			textrotationvalues=options.getfieldvalue('textrotation');
+		}
+		//ischar if only one textsize -> create a cell
+		if (typeof textrotationvalues === 'number'){
+			textrotationvalues=[textrotationvalues];
+		}
+		else if (!IsArray(textrotationvalues)){
+			throw Error("plot error message: ''textrotation'' option should be either a number or a cell");
+		}
+		else textrotationvalues=[0];
+		
+		if (textrotationvalues.length==1){
+			var value=textrotationvalues[0];
+			for (var i=0;i<numtext-1;i++)textrotationvalues.push(value);
+		}
+			
+		options.changefieldvalue('text',textvalues);
+		options.changefieldvalue('textsize',textsizevalues);
+		options.changefieldvalue('textweight',textweightvalues);
+		options.changefieldvalue('textcolor',textcolorvalues);
+		options.changefieldvalue('textposition',textpositionvalues);
+		options.changefieldvalue('textrotation',textrotationvalues);
+	}
+
+	//expdisp
+	expdispvaluesarray=[];
+	expstylevaluesarray=[];
+	expstylevalues=[];
+	if (options.exist('expstyle')){
+		expstylevalues=options.getfieldvalue('expstyle');
+		//ischar if only one expstyle -> create a cell
+		if (typeof expstylevalues === 'string'){
+			expstylevalues=[expstylevalues];
+		}
+		options.changefieldvalue('expdisp',expdispvaluesarray);
+	}
+		
+	if (options.exist('expdisp')){
+		expdispvalues=options.getfieldvalue('expdisp');
+	
+		//ischar if only one expstyle -> create a cell
+		if (typeof expdispvalues === 'string'){
+			expdispvalues=[expdispvalues];
+		}
+		for (var i=0; i< expdispvalues.length;i++){
+			expdispvaluesarray.push(expdispvalues[i]);
+			if (expstylevalues.length>i){
+				expstylevaluesarray.push(expstylevalues[i]);
+			}
+			else{
+				expstylevaluesarray.push('g-');
+			}
+		}
+		options.changefieldvalue('expstyle',expstylevaluesarray);
+	}
+
+	//latlonnumbering
+	if (options.exist('latlonclick')){
+		if (options.getfieldvalue('latlonclick') === 'on'){
+			options.changefieldvalue('latlonclick',1);
+		}
+	}
+
+	//north arrow
+	if (options.exist('northarrow')){
+	   if (options.getfieldvalue('northarrow') === 'on'){
+		   
+		   //default values
+		   Lx=ArrayMax(md.mesh.y)-ArrayMin(md.mesh.y);
+		   Ly=ArrayMax(md.mesh.y)-ArrayMin(md.mesh.y);
+		  
+		   //default values
+		   options.changefieldvalue('northarrow',[ArrayMin(md.mesh.x)+1/6*Lx,ArrayMin(md.mesh.y)+5/6*Ly,1/15*Ly,0.25,1/250*Ly]);
+	   }
+	}
+
+	//scale ruler
+	if (options.exist('scaleruler')){
+	   if (options.getfieldvalue('scaleruler') === 'on'){
+		   //default values
+		   Lx=ArrayMax(md.mesh.x)-ArrayMin(md.mesh.x);
+		   Ly=ArrayMax(md.mesh.y)-ArrayMin(md.mesh.y);
+		   
+		   //default values
+		   options.changefieldvalue('scaleruler',[ArrayMin(md.mesh.x)+6/8*Lx, ArrayMin(md.mesh.y)+1/10*Ly, 10^(Mat.ceil(Mat.log10(Lx)))/5, Math.floor(Lx/100), 5]);
+	   }
+	}
+
+	//Log scale (LOTS of changes to be performed
+	if (options.exist('log')){
+	   if (options.exist('caxis')){
+		   options.changefieldvalue('caxis',Math.log(options.getfieldvalue('caxis'))/Math.log(options.getfieldvalue('log')));
+	   }
+	   options.changefieldvalue('cutoff',Math.log(options.getfieldvalue('cutoff',1.5))/Math.log(options.getfieldvalue('log')));
+	}
+}
Index: /issm/trunk-jpl/src/m/plot/plot_manager.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_manager.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/plot_manager.js	(revision 19721)
@@ -0,0 +1,235 @@
+function plot_manager(md,options,subplotwidth,nlines,ncols,i){
+//PLOT__MANAGER - distribute the plots, called by plotmodel
+//
+//   Usage:
+//      plot_manager(md,options,subplotwidth,i);
+//
+//   See also: PLOTMODEL, PLOT_UNIT
+
+	//parse options and get a structure of options. 
+	checkplotoptions(md,options);
+
+	options.disp();
+
+	//get data to be displayed
+	data=options.getfieldvalue('data');
+
+	//figure out if this is a special plot
+	if (typeof data === 'string'){
+
+		switch(data){
+
+			case 'boundaries':
+				plot_boundaries(md,options,subplotwidth,i);
+				break;
+			case 'BC':
+				plot_BC(md,options,subplotwidth,i,data);
+				break;
+			case 'edges':
+				plot_edges(md,options,subplotwidth,i,data);
+				break;
+			case 'elementnumbering':
+				plot_elementnumbering(md,options,subplotwidth,i);
+				break;
+			case 'highlightelements':
+				plot_highlightelements(md,options,subplotwidth,i);
+				break;
+			case 'qmumean':
+				plot_qmumean(md,options,nlines,ncols,i);
+				break;
+			case 'qmustddev':
+				plot_qmustddev(md,options,nlines,ncols,i);
+				break;
+			case 'qmuhistnorm':
+				plot_qmuhistnorm(md,options,nlines,ncols,i);
+				break;
+			case 'qmu_mass_flux_segments':
+				plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
+				break;
+			case 'part_hist':
+				plot_parthist(md,options,nlines,ncols,i);
+				break;
+			case 'part_hist_n':
+				plot_parthistn(md,options,nlines,ncols,i);
+				break;
+			case 'part_hist_w':
+				plot_parthistw(md,options,nlines,ncols,i);
+				break;
+			case 'elements_type':
+				plot_elementstype(md,options,subplotwidth,i);
+				break;
+			case 'vertexnumbering':
+				plot_vertexnumbering(md,options,subplotwidth,i);
+				break;
+			case 'highlightvertices':
+				plot_highlightvertices(md,options,subplotwidth,i);
+				break;
+			case 'basal_drag':
+				plot_basaldrag(md,options,subplotwidth,i,data);
+				break;
+			case 'basal_dragx':
+				plot_basaldrag(md,options,subplotwidth,i,data);
+				break;
+			case 'basal_dragy':
+				plot_basaldrag(md,options,subplotwidth,i,data);
+				break;
+			case 'driving_stress':
+				plot_drivingstress(md,options,subplotwidth,i);
+				break;
+			case 'mesh':
+				plot_mesh(md,options,nlines,ncols,i);
+				break;
+			case 'none':
+				if (!(options.exist('overlay'))){
+					plot_none(md,options,nlines,ncols,i);
+				}
+				break;
+			case 'penalties':
+				plot_penalties(md,options,subplotwidth,i);
+				break;
+			case 'partition':
+				plot_partition(md,options,nlines,ncols,i);
+				break;
+			case 'referential':
+				plot_referential(md,options,nlines,ncols,i);
+				break;
+			case 'riftvel':
+				plot_riftvel(md,options,nlines,ncols,i);
+				break;
+			case 'riftnumbering':
+				plot_riftnumbering(md,options,nlines,ncols,i);
+				break;
+			case 'rifts':
+				plot_rifts(md,options,nlines,ncols,i);
+				break;
+			case 'riftrelvel':
+				plot_riftrelvel(md,options,nlines,ncols,i);
+				break;
+			case 'riftpenetration':
+				plot_riftpenetration(md,options,nlines,ncols,i);
+				break;
+			case 'riftfraction':
+				plot_riftfraction(md,options,nlines,ncols,i);
+				break;
+			case 'sarpwr':
+				plot_sarpwr(md,options,subplotwidth,i);
+				break;
+			case 'time_dependant':
+				plot_vstime(md,options,nlines,ncols,i);
+				break;
+			case 'icefront':
+				plot_icefront(md,options,subplotwidth,i,data);
+				break;
+			case 'segments':
+				plot_segments(md,options,subplotwidth,i,data);
+				break;
+			case 'quiver':
+				data=[md.initialization.vx, md.initialization.vy]; //Go ahead and try plot_unit
+
+			case 'strainrate_tensor':
+			case 'strainrate':
+			case 'strainrate_principal':
+			case 'strainrate_principalaxis1':
+			case 'strainrate_principalaxis2':
+			case 'strainrate_principalaxis3':
+			case 'stress_tensor':
+			case 'stress':
+			case 'stress_principal':
+			case 'stress_principalaxis1':
+			case 'stress_principalaxis2':
+			case 'stress_principalaxis3':
+			case 'deviatoricstress_tensor':
+			case 'deviatoricstress':
+			case 'deviatoricstress_principal':
+			case 'deviatoricstress_principalaxis1':
+			case 'deviatoricstress_principalaxis2':
+			case 'deviatoricstress_principalaxis3':
+				plot_tensor(md,options,subplotwidth,i,data);
+				break;
+			case 'thermaltransient_results':
+				plot_thermaltransient_results(md,options,subplotwidth,i);
+				break;
+			case 'transient_movie':
+				plot_transient_movie(md,options,subplotwidth,i);
+				break;
+			case 'transient_results':
+				plot_transient_results(md,options,subplotwidth,i);
+				break;
+			case 'transient_field':
+				plot_transient_field(md,options,subplotwidth,i);
+				break;
+			default:
+				if (data in md){
+					data=md[data];
+				}
+				else{
+					error('plot error message: data provided not supported yet. Type plotdoc for help');
+				}
+		}
+	}
+
+	//Figure out if this is a semi-transparent plot.
+	if (options.exist('overlay')){
+		plot_overlay(md,data,options,nlines,ncols,i);
+		return;
+	}
+
+	//Figure out if this is a semi-transparent plot.
+	if (options.exist('googlemaps')){
+		plot_googlemaps(md,data,options,nlines,ncols,i);
+		return;
+	}
+
+	//Figure out if this is a semi-transparent plot.
+	if (options.exist('gridded')){
+		plot_gridded(md,data,options,nlines,ncols,i);
+		return;
+	}
+
+	//Figure out if this is a Section plot
+	if (options.exist('sectionvalue')){
+		plot_section(md,data,options,nlines,ncols,i);
+		return;
+	}
+
+	//Figure out if this is a Profile plot
+	if (options.exist('profile')){
+		plot_profile(md,data,options,nlines,ncols,i);
+		return;
+	}
+
+	//process data and model
+    var meshresults = processmesh(md,data,options);
+	var x = meshresults[0]; 
+	var y = meshresults[1]; 
+	var z = meshresults[2]; 
+	var elements = meshresults[3]; 
+	var is2d = meshresults[4]; 
+	var isplanet = meshresults[5];
+
+	var dataresults = processdata(md,data,options);
+	var data2 = dataresults[0]; 
+	var datatype = dataresults[1];
+
+
+	//standard plot:
+	if (options.exist('asymsubplot')){
+		id=options.getfieldvalue('asymsubplot',i);
+		//subplot(nlines,ncols,id);
+	}
+	else{
+		//subplot(nlines,ncols,i);
+	}
+
+	//plot unit
+	plot_unit(x,y,z,elements,data2,is2d,isplanet,datatype,options);
+
+	//apply all options
+	if (datatype==3){
+		options.changefieldvalue('colorbar',2);
+		if (options.exist('contourlevels')){
+			data2=data;
+		}
+	}
+	applyoptions(md,data2,options);
+}
Index: /issm/trunk-jpl/src/m/plot/plot_unit.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 19721)
@@ -0,0 +1,80 @@
+function plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options){
+	//PLOT_UNIT - unit plot, display data
+	//
+	//   Usage:
+	//      plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options);
+	//
+	//   See also: PLOTMODEL, PLOT_MANAGER
+
+	//edgecolor
+	edgecolor=options.getfieldvalue('edgecolor','none');
+
+	switch(datatype){
+
+		//element plot
+		case 1:
+
+			pos=ArrayFindNot(data,NaN); //needed for element on water
+			if (elements[0].length==6){ //prisms
+
+				/*A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); D=elements(pos,4); E=elements(pos,5); F=elements(pos,6);
+				  patch( 'Faces', [A B C],  'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  */
+			}
+			else if (elements[0].length==4){ //tetras
+				/*A=elements(:,1); B=elements(:,2); C=elements(:,3); D=elements(:,4);
+				  patch( 'Faces',[A B C],'Vertices', [x y z],'CData',data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces',[A B D],'Vertices', [x y z],'CData',data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces',[B C D],'Vertices', [x y z],'CData',data(pos),'FaceColor','flat','EdgeColor',edgecolor);
+				  patch( 'Faces',[C A D],'Vertices', [x y z],'CData',data(pos),'FaceColor','flat','EdgeColor',edgecolor);*/
+			}
+			else{
+				/*A=elements(pos,1); B=elements(pos,2); C=elements(pos,3);
+				  patch( 'Faces', [A B C], 'Vertices', [x y z],'CData', data(pos),'FaceColor','flat','EdgeColor',edgecolor);*/
+			}
+			break;
+
+			//node plot
+		case 2:
+
+			if (elements[0].length==6){ //prisms
+				/*A=elements(:,1); B=elements(:,2); C=elements(:,3); D=elements(:,4); E=elements(:,5); F=elements(:,6);
+				  patch( 'Faces', [A B C],  'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);*/
+			}
+			else if (elements[0].length==4){//tetras
+				/*A=elements(:,1); B=elements(:,2); C=elements(:,3); D=elements(:,4);
+				  patch( 'Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces',[A B D],'Vertices', [x y z],'FaceVertexCData',data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces',[B C D],'Vertices', [x y z],'FaceVertexCData',data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  patch( 'Faces',[C A D],'Vertices', [x y z],'FaceVertexCData',data(:),'FaceColor','interp','EdgeColor',edgecolor);*/
+			}
+			else{
+				throw Error('Here we are, take it over Dan');
+				/*A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+				  patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+				  */
+			}
+			break;
+
+			//quiver plot
+		case 3:
+
+			if (is2d){
+				//plot_quiver(x,y,data(:,1),data(:,2),options);
+			}
+			else{
+				//plot_quiver3(x,y,z,data(:,1),data(:,2),data(:,3),options);
+			}
+
+		default:
+				throw Error(sprintf("%s%i%s\n",'case ',datatype,' not supported'));
+	}
+}
Index: /issm/trunk-jpl/src/m/plot/plotmodel.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plotmodel.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/plotmodel.js	(revision 19721)
@@ -0,0 +1,50 @@
+function plotmodel(md){
+
+	//Convert arguments to array: 
+	var args = Array.prototype.slice.call(arguments);
+
+	//First process options
+	var  options = new plotoptions(args.slice(1,args.length));
+	
+	//get number of subplots
+	subplotwidth=Math.ceil(Math.sqrt(options.numberofplots)); 
+	
+	//Get figure number and number of plots
+	figurenumber=options.figurenumber;
+	numberofplots=options.numberofplots;
+
+	//if nlines and ncols specified, then bypass.
+	var nlines,ncols;
+	if (options.list[0].exist('nlines')){
+		nlines=options.list[0].getfieldvalue('nlines');
+	}
+	else {
+		nlines=Math.ceil(numberofplots/subplotwidth);
+	}
+	if (options.list[0].exist('ncols')){
+		ncols=options.list[0].getfieldvalue('ncols');
+	}
+	else {
+		ncols=subplotwidth;
+	}
+	
+	//check that nlines and ncols were given at the same time!
+	if ((options.list[0].exist('ncols') & !options.list[0].exist('nlines')) | (options.list[0].exist('nlines') & !options.list[0].exist('ncols'))) throw Error('plotmodel error message: nlines and ncols  need to be specified together, or not at all');
+
+	//go through subplots
+	if (numberofplots){
+
+		//Create figure : to be replaced by Dan's code here for the <div> segment of the html code?
+		//f=figure(figurenumber);clf;
+		//deal with visible off or on, figure position, etc...
+
+		//Go through all data plottable and close window if an error occurs
+		for (var i=0;i<numberofplots;i++){
+
+			plot_manager(options.list[i].getfieldvalue('model',md),options.list[i],subplotwidth,nlines,ncols,i);
+
+			//List all unused options
+			options.list[i].displayunused();
+		}
+	}
+}
Index: /issm/trunk-jpl/src/m/plot/processdata.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/processdata.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/processdata.js	(revision 19721)
@@ -0,0 +1,226 @@
+function processdata(md,data,options){
+	//PROCESSDATA - process data to be plotted
+	//
+	//   datatype = 1 -> elements
+	//   datatype = 2 -> nodes
+	//   datatype = 3 -> node quivers
+	//   datatype = 4 -> patch
+	//
+	//   Usage:
+	//      var array = processdata(md,data,options);
+	//      var data = array[0]; 
+	//      var datatype = array[1];
+	//
+	//   See also: PLOTMODEL, PROCESSMESH
+
+	//check format
+	if ( data.length ==0 | data === [] | typeof data === 'number' | ArrayAnyNaN(data)){
+		throw Error('plotmodel error message: data provided is empty');
+	}
+
+	//Process NaN if any (do not know before mask is applied)
+	if (options.exist('nan')){
+		var valuefornan=options.getfieldvalue('nan',0);
+		for (var i=0;i<data.length;i++)if(IsNaN(data[i]))data[i]=valuefornan;
+	}
+
+	//special case for mesh 2dvertical
+	if (md.mesh.domaintype() === '2Dvertical'){
+		return processdata(md.mesh,md,data,options);
+	}
+
+	//needed later on
+	if ('numberofvertices2d' in md.mesh){
+		numberofvertices2d=md.mesh.numberofvertices2d; 
+		numberofelements2d=md.mesh.numberofelements2d; 
+	}
+	else {
+		numberofvertices2d=NaN;
+		numberofelements2d=NaN;
+	}
+
+	//initialize datatype
+	datatype=0;
+
+	//get datasize
+	datasize=data.length;
+
+	//transpose data if necessary
+	if (data[0].length > data.length){
+		throw Error('processdata error message: you need to tranpose your data!');
+	}
+
+
+	//check length
+	if (datasize != md.mesh.numberofvertices & datasize !=md.mesh.numberofelements & datasize!=md.mesh.numberofvertices*6 & 
+			((md.mesh.domaintype() === '3D') & !(datasize==numberofelements2d | datasize==numberofvertices2d))){
+		throw Error('plotmodel error message: data not supported yet');
+	}
+
+	//quiver?
+	if (data[0].length>1){
+		datatype=3;
+
+		//check number of columns, add zeros if necessary,
+		if (md.mesh.dimension()==3){
+			if (data[0].length==2){
+				data=[data, NewArrayFill(data.length,1)];
+			}
+			else if (data[0].length!=3){
+				throw Error('plotmodel error message: data provided should have 2 or 3 columns for quiver plot, and 1 for regular plot');
+			}
+		}
+	}
+
+	//treat the case datasize(1)=6*nodes
+	if (datasize==6*md.mesh.numberofvertices){
+		//keep the only norm of data
+		data1=new Array(md.mesh.numberofvertices);
+		data2=new Array(md.mesh.numberofvertices);
+		data=new Array(md.mesh.numberofvertices);
+		for(var i=0;i<md.mesh.numberofvertices;i++){
+			data1[i]=data[6*i+0];
+			data2[i]=data[6*i+1];
+			data[i]=Math.sqrt(pow(data1[i],2),pow(data2[i],2));
+		}
+		datasize=md.mesh.numberofvertices;
+		//---> go to node data
+	}
+
+	//treat the case datasize(1)=nodes2d
+	if (md.mesh.dimension()==3 & datasize==numberofvertices2d){
+		data=project3d(md,'vector',data,'type','node');
+		datasize=md.mesh.numberofvertices;
+		//---> go to node data
+	}
+
+	//treat the case datasize=nodes2d
+	if (md.mesh.dimension()==3 & datasize==numberofelements2d){
+		data=project3d(md,'vector',data,'type','element');
+		datasize=md.mesh.numberofelements;
+		//---> go to node data
+	}
+
+	//smoothing?
+	if (options.exist('smooth')){
+		data=averaging(md,data,options.getfieldvalue('smooth'));
+		datasize=md.mesh.numberofvertices;
+		//---> go to node data
+	}
+
+	//element data
+	if (datasize==md.mesh.numberofelements & data[0].length==1){
+
+		//Initialize datatype if non patch
+		if(datatype!=4 & datatype!=5){
+			datatype=1;
+		}
+
+		//Mask?
+		if(options.exist('mask')){
+			flags=options.getfieldvalue('mask');
+			if(flags.length==md.mesh.numberofvertices){
+				for(var i=0;i<md.mesh.numberofelements;i++){
+					var nanify=0;
+					for(var j=0;j<md.mesh.elements[0].length;j++){
+						if (flags[md.mesh.elements[i][j]-1]==0)nanify=1;
+					}
+					if(nanify) for(var j=0;j<md.mesh.elements[0].length;j++)data[md.mesh.elements[i][j]-1]=NaN;
+				}
+			}
+			else if (flags.length==md.mesh.numberofelements){
+				for(var i=0;i<md.mesh.numberofelements;i++)if (flags[i]==0)data[i]=NaN;
+			}
+			else{
+				console.log('plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements)');
+			}
+		}
+
+		//log?
+		if (options.exist('log')){
+			var bounds=options.getfieldvalue('caxis',[ArrayMin(data),ArrayMax(data)]);
+			for(var i=0;i<md.mesh.numberofelements;i++)if(data[i]<bounds[0])data[i]=bounds[0];
+			for(var i=0;i<md.mesh.numberofelements;i++)if(data[i]<=0){
+				throw Error("Log option cannot be applied on negative values. Use caxis option (Rignot''s settings: [1.5 max(data)])");
+			}
+			for(var i=0;i<md.mesh.numberofelements;i++){
+				if(!IsNaN(data[i])){
+					data[i]=Math.log(data[i])/log(options.getfieldvalue('log'));
+				}
+			}
+		}
+	}
+
+	//node data
+	if (datasize==md.mesh.numberofvertices){
+		datatype=2;
+
+		//Mask?
+		if (options.exist('mask')){
+			flags=options.getfieldvalue('mask');
+			if (flags.length==md.mesh.numberofvertices){
+				for(var i=0;i<md.mesh.numberofvertices;i++){
+					if(flags[i]==0)data[i]=NaN;
+				}
+			}
+			else if( length(flags)==md.mesh.numberofelements){
+				for(var i=0;i<md.mesh.numberofelements;i++){
+					if(flags[i]==0){
+						for(var j=0;j<md.mesh.elements[0].length;j++){
+							data[md.mesh.elements[i][j]-1]=NaN;
+						}
+					}
+				}
+			}
+			else{
+				console.log("plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements");
+			}
+		}
+
+		//log?
+		if (options.exist('log')){
+		   for(var i=0;i<md.mesh.numberofvertices;i++){
+			   data[i]=Math.log(data[i])/log(options.getfieldvalue('log'));
+		   }
+		}
+	}
+
+	//layer projection? 
+	if (options.getfieldvalue('layer',0)>=1){
+		data=project2d(md,data,options.getfieldvalue('layer')); //project onto 2d mesh
+	}
+
+	//control arrow density if quiverplot: not done yet since conversion of matlab to javascript.
+	/*if (datatype==3 & options.exist('density')){
+		databak=data;
+		data=NewArrayFill(datasize,NaN);
+
+		density=options.getfieldvalue('density');
+		data(1:density:end,:)=databak(1:density:end,:);
+		clear databak
+	}*/
+
+	/*if (datatype==3){ //not done yet
+		//Mask?
+		if (options.exist('mask')){
+			flags=options.getfieldvalue('mask');
+			pos=find(~flags);
+			if (flags.length==md.mesh.numberofvertices){
+			   data(pos,:)=NaN;
+			}
+			else if (flags.length==md.mesh.numberofelements){
+				data(md.mesh.elements(pos,:),:)=NaN;
+			}
+			else{
+				console.log("plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements");
+			}
+		}
+	}*/
+
+	//OK, if datatype=0 error out
+	if (datatype==0){
+	   throw Error('data provided not recognized or not supported');
+	}
+
+	return [data,datatype];
+}
Index: /issm/trunk-jpl/src/m/plot/processmesh.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/processmesh.js	(revision 19721)
+++ /issm/trunk-jpl/src/m/plot/processmesh.js	(revision 19721)
@@ -0,0 +1,97 @@
+function processmesh(md,data,options){
+//PROCESSMESH - process mesh to be plotted
+//
+//   Usage:
+//      var meshresults=processmesh(md,data,options)
+//      var x=meshresults[0]; 
+//      var y=meshresults[1]; 
+//      var z=meshresults[2]; 
+//      var elements=meshresults[3]; 
+//      var is2d=meshresults[4]; 
+//      var isplanet=meshresults[5]; 
+//
+//   See also: PLOTMODEL, PROCESSDATA
+
+	//some checks
+	if (md.mesh.numberofvertices==0){
+		throw Error('plot error message: mesh is empty');
+	}
+
+	if (md.mesh.numberofvertices==md.mesh.numberofelements){
+		throw Error(['plot error message: the number of elements is the same as the number of nodes...']);
+	}
+
+	//special case for mesg 2dvertical
+	if (md.mesh.domaintype() === '2Dvertical') return processmesh(md.mesh,options);
+
+	//special case for mesh 3dsurface
+	if (md.mesh.domaintype() == '3Dsurface') return processmesh(md.mesh,options);
+
+	if (options.getfieldvalue('coord','xy') !== 'latlon'){
+		x=md.mesh.x;
+		if ('x2d' in md.mesh) x2d=md.mesh.x2d;
+		y=md.mesh.y;
+		if ('y2d' in md.mesh) y2d=md.mesh.y2d;
+	}
+	else{
+		x=md.mesh.long;
+		y=md.mesh.lat;
+	}
+
+	if ('z' in md.mesh){
+		z=md.mesh.z;
+	}
+	else{
+		z=NewArrayFill(x.length,0);
+	}
+	z=options.getfieldvalue('z',z);
+	if (typeof z === 'string'){
+		z=md[z];
+	}
+
+	if ('elements2d' in md.mesh) elements2d=md.mesh.elements2d;
+	elements=md.mesh.elements;
+
+	//is it a 2d plot?
+	if (md.mesh.dimension()==2){
+		is2d=1;
+	}
+	else{
+		if (options.getfieldvalue('layer',0)>=1){
+			is2d=1;
+		}
+		else{
+			is2d=0;
+		}
+	}
+
+	//layer projection? 
+	if (options.getfieldvalue('layer',0)>=1){
+		if (options.getfieldvalue('coord','xy') === 'latlon'){
+			throw Error('processmesh error message: cannot work with 3D meshes for now');
+		}
+		
+		//we modify the mesh temporarily to a 2d mesh from which the 3d mesh was extruded. 
+		x=x2d;
+		y=y2d;
+		z=NewArrayFill(x2d.length,0);
+		elements=elements2d;
+	}
+
+	//units
+	if (options.exist('unit')){
+		unit=options.getfieldvalue('unit');
+		x=x*unit;
+		y=y*unit;
+		z=z*unit;
+	}
+
+	//for now, always isplanet = 0, as we don't have the isa capability: 
+	//if isa(md,'planet'),
+	//	isplanet=1;
+	//else
+	isplanet=0;
+	//end
+
+	return  [x,y,z,elements,is2d,isplanet];
+}
