Index: /issm/trunk-jpl/src/m/contrib/hack/sia.m
===================================================================
--- /issm/trunk-jpl/src/m/contrib/hack/sia.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/contrib/hack/sia.m	(revision 13009)
@@ -0,0 +1,26 @@
+function [velx,vely,vel]=sia(md)
+%BALVEL - computation of Shallow Ice velocities
+%
+%   This routine uses the model of Hutter to compute the velocities
+%   of a 2d model using the surface slope
+%
+%   Usage:
+%      [velx,vely,vel]=sia(md)
+
+if md.mesh.dimension~=2,
+	error('Only 2d meshes are allowed to compute velocity balances');
+end
+
+%Get slope
+[sx,sy,s]=slope(md);
+
+%Average thickness and B over all elements.
+summer=[1;1;1];
+hel=md.geometry.thickness(md.mesh.elements)*summer/3;
+Bel=md.B(md.mesh.elements)*summer/3;
+
+Ael=Bel.^(-3);
+
+velx=-2*(md.materials.rho_ice*md.constants.g)^3*s.^2.*sx.*Ael/4.*hel.^4;
+vely=-2*(md.materials.rho_ice*md.constants.g)^3*s.^2.*sy.*Ael/4.*hel.^4;
+vel=sqrt(velx.^2+vely.^2);
Index: /issm/trunk-jpl/src/m/display/fielddisplay.m
===================================================================
--- /issm/trunk-jpl/src/m/display/fielddisplay.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/display/fielddisplay.m	(revision 13009)
@@ -0,0 +1,154 @@
+function fielddisplay(md,name,comment)
+%FIELDDISPLAY - display model field
+%
+%   Usage:
+%      fielddisplay(md,offset,name,comment)
+
+	%get field
+	field=md.(name);
+
+	%disp corresponding line as a function of field type (offset set as 9 spaces)
+	parsedisplay('         ',name,field,comment);
+
+end %function
+
+function parsedisplay(offset,name,field,comment); %{{{
+
+	%string
+	if ischar(field),
+
+		if length(field)>30;
+			displayunit(offset,name,'not displayed',comment),
+		else
+			displayunit(offset,name,['''' field ''''],comment),
+		end
+
+	%numeric
+	elseif isnumeric(field)
+
+		%get size
+		fieldsize=size(field);
+
+		%double
+		if max(fieldsize)==1,
+			displayunit(offset,name,num2str(field),comment),
+		%matrix
+		else
+			displayunit(offset,name,['(' num2str(fieldsize(1)) 'x' num2str(fieldsize(2)) ')'],comment),
+		end
+
+	%logical
+	elseif islogical(field)
+
+		%get size
+		fieldsize=size(field);
+
+		%single value
+		if max(fieldsize)==1,
+			if (field)
+				displayunit(offset,name,'true',comment),
+			else
+				displayunit(offset,name,'false',comment),
+			end
+		%matrix
+		else
+			displayunit(offset,name,['(' num2str(fieldsize(1)) 'x' num2str(fieldsize(2)) ')'],comment),
+		end
+
+		%structure
+	elseif isstruct(field),
+		if ~isempty(fields(field))
+			displayunit(offset,name,'(structure)',comment),
+			struct_display(field,[offset '   ']),
+		else
+			displayunit(offset,name,'N/A',comment),
+		end
+
+	%cell
+	elseif iscell(field),
+		cell_display(offset,name,field,comment),
+
+	else
+		displayunit(offset,name,'not displayed',comment),
+
+	end
+end%}}}
+
+function struct_display(structure,offset) % {{{
+
+	structure_fields=fields(structure);
+
+	for i=1:length(structure_fields),
+
+		%get current field
+		field=structure.(structure_fields{i});
+
+		%recursive call if necessary
+		if isstruct(field),
+			displayunit(offset,structure_fields{i},'(structure)',''),
+			struct_display(field,[offset '   ']);
+
+		%display value
+		else
+			parsedisplay(offset,structure_fields{i},field,'');
+		end
+	end
+end% }}}
+function cell_display(offset,name,field,comment) % {{{
+
+	%initialization
+	string='{';
+
+	%go through the cell and fill string
+	if length(field)<5;
+		for i=1:length(field),
+			if ischar(field{i}),
+				string=[string ''''  field{i} ''','];
+			elseif (isnumeric(field{i}) & length(field{i})==1)
+				string=[string num2str(field{i}) ',' ];
+			else
+				string='{';
+				break
+			end
+		end
+	end
+	if strcmp(string,'{'),
+		string=['(' num2str(size(field,1)) 'x' num2str(size(field,2)) ')'];
+	else
+		string=[string(1:end-1) '}'];
+	end
+
+	%call displayunit
+	displayunit(offset,name,string,comment);
+end% }}}
+function displayunit(offset,name,characterization,comment),% {{{
+
+	%take care of name
+	if length(name)>23,
+		name=[name(1:20) '...'];
+	end
+
+	%take care of characterization
+	if (strcmp(characterization,['''' '''']) | strcmp(characterization,'NaN')),
+		characterization='N/A';
+	end
+	if length(characterization)>15,
+		characterization=[characterization(1:12) '...'];
+	end
+
+	%print
+	if isempty(comment)
+		disp(sprintf('%s%-23s: %-15s',offset,name,characterization));
+	else
+		if ischar(comment),
+			disp(sprintf('%s%-23s: %-15s -- %s',offset,name,characterization,comment));
+		elseif iscell(comment),
+			disp(sprintf('%s%-23s: %-15s -- %s',offset,name,characterization,comment{1}));
+			for i=2:length(comment),
+				disp(sprintf('%s%-23s  %-15s    %s',offset,'','',comment{i}));
+			end
+		else
+			error('fielddisplay error message: format for comment not supportet yet');
+		end
+	end
+end% }}}
Index: /issm/trunk-jpl/src/m/display/fielddisplay2.m
===================================================================
--- /issm/trunk-jpl/src/m/display/fielddisplay2.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/display/fielddisplay2.m	(revision 13009)
@@ -0,0 +1,14 @@
+function fielddisplay2(md,name,comment)
+%FIELDDISPLAY2 - display model field
+%
+%   Usage:
+%      fielddisplay2(md,offset,name,comment)
+
+	%get field
+	field=md.(name);
+
+	if length(name)>23,
+		name=[name(1:20) '...'];
+	end
+
+	disp(sprintf('%s%-23s -- %s','      ',name,comment));
Index: /issm/trunk-jpl/src/m/extrusion/DepthAverage.m
===================================================================
--- /issm/trunk-jpl/src/m/extrusion/DepthAverage.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/extrusion/DepthAverage.m	(revision 13009)
@@ -0,0 +1,33 @@
+function  vector_average=DepthAverage(md,vector);
+%DEPTHAVERAGE - computes depth average of 3d vector, and return value on 2d mesh. 
+%
+%   Usage:
+%      vector_average=DepthAverage(md,vector);
+%
+%   Example:
+%      vel_bar=DepthAverage(md,md.initialization.vel);
+
+%check that the model given in input is 3d
+if ~md.mesh.dimension==3;
+	error('DepthAverage error message: the model given in input must be 3d')
+end
+
+%nods data
+if (length(vector)==md.mesh.numberofvertices),
+	vector_average=zeros(md.mesh.numberofvertices2d,1);
+	for i=1:md.mesh.numberoflayers-1,
+		vector_average=vector_average+(project2d(md,vector,i)+project2d(md,vector,i+1))/2.*(project2d(md,md.mesh.z,i+1)-project2d(md,md.mesh.z,i));
+	end
+	vector_average=vector_average./project2d(md,md.geometry.thickness,1);
+
+%element data
+elseif (length(vector)==md.mesh.numberofelements),
+	vector_average=zeros(md.mesh.numberofelements2d,1);
+	for i=1:md.mesh.numberoflayers-1,
+		vector_average=vector_average+project2d(md,vector,i).*(project2d(md,md.mesh.z,i+1)-project2d(md,md.mesh.z,i));
+	end
+	vector_average=vector_average./project2d(md,md.geometry.thickness,1);
+
+else
+	error('vector size not supported yet');
+end
Index: /issm/trunk-jpl/src/m/extrusion/project2d.m
===================================================================
--- /issm/trunk-jpl/src/m/extrusion/project2d.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/extrusion/project2d.m	(revision 13009)
@@ -0,0 +1,36 @@
+function projection_value=project2d(md3d,value,layer)
+%PROJECT2D - returns the value of a field for a given layer of the mesh
+%
+%   project 'value' vector taken at layer 'layer' from extruded 2d-3d mesh onto 2d mesh 
+%   used to do the extrusion. This routine is used to compare values between a 2d-3d mesh
+%   at a certain layer, and the equivalent value (if it exists), on the original 2d mesh. 
+%   This routine relies heavily on projections (contained in 3d model md) recored during 
+%   the extrude operation.
+%
+%   Usage:
+%      projection_value=project2d(md3d,value,layer)
+%
+%   Example:
+%      vel2=project2d(md3d,md3d.vel,2);
+
+%some checks on list of arguments
+if ((nargin~=3) ),
+	help project2d
+	error('project2d error message');
+end
+
+if (md3d.mesh.dimension~=3),
+	error('wrong model type ... should be ''3d''');
+end
+
+if ((layer<1) | (layer>md3d.mesh.numberoflayers)),
+	error(['layer must be between 1 and ' num2str(md3d.mesh.numberoflayers)]);
+end
+
+if size(value,1)==md3d.mesh.numberofvertices,
+	projection_value=value((layer-1)*md3d.mesh.numberofvertices2d+1:layer*md3d.mesh.numberofvertices2d,:);
+elseif size(value,1)==md3d.mesh.numberofvertices+1,
+	projection_value=[value((layer-1)*md3d.mesh.numberofvertices2d+1:layer*md3d.mesh.numberofvertices2d,:); value(end,:)];
+else
+	projection_value=value((layer-1)*md3d.mesh.numberofelements2d+1:layer*md3d.mesh.numberofelements2d,:);
+end
Index: /issm/trunk-jpl/src/m/extrusion/project3d.m
===================================================================
--- /issm/trunk-jpl/src/m/extrusion/project3d.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/extrusion/project3d.m	(revision 13009)
@@ -0,0 +1,82 @@
+function projected_vector=project3d(md,varargin);
+%PROJECT3D - vertically project a vector from 2d mesh
+%
+%   vertically project a vector from 2d mesh (split in noncoll and coll areas) into a 3d mesh.
+%   This vector can be a node vector of size (md.mesh.numberofvertices2d,N/A) or an 
+%   element vector of size (md.mesh.numberofelements2d,N/A). 
+%   arguments: 
+%      'vector': 2d vector
+%      'type': 'element' or 'node'. 
+%   options: 
+%      'layer' a layer number where vector should keep its values. If not specified, all layers adopt the 
+%             value of the 2d vector.
+%      'padding': default to 0 (value adopted by other 3d layers not being projected0
+%
+%   Egs:
+%      extruded_vector=project3d(md,'vector',vector2d,'type','node','layer',1,'padding',NaN);
+%      extruded_vector=project3d(md,'vector',vector2d,'type','element','padding',0);
+%      extruded_vector=project3d(md,'vector',vector2d,'type','node');
+
+%some regular checks
+if nargin==0,
+	help project3d
+	error('bad usage');
+end
+if md.mesh.dimension~=3
+	error('input model is not 3d');
+end
+
+%retrieve parameters from options.
+options      = pairoptions(varargin{:});
+vector2d     = getfieldvalue(options,'vector');     %mandatory
+type         = getfieldvalue(options,'type');       %mandatory
+layer        = getfieldvalue(options,'layer',0);    %optional (do all layers otherwise)
+paddingvalue = getfieldvalue(options,'padding',0);  %0 by default
+
+if length(vector2d)==1,
+	projected_vector=vector2d;
+elseif strcmpi(type,'node'),
+
+	%Initialize 3d vector
+	if size(vector2d,1)==md.mesh.numberofvertices2d
+		projected_vector=paddingvalue*ones(md.mesh.numberofvertices,  size(vector2d,2));
+	elseif size(vector2d,1)==md.mesh.numberofvertices2d+1
+		projected_vector=paddingvalue*ones(md.mesh.numberofvertices+1,size(vector2d,2));
+		projected_vector(end,:)=vector2d(end,:);
+		vector2d=vector2d(1:end-1,:);
+	else
+		error('vector length not supported')
+	end
+
+	%Fill in
+	if layer==0,
+		for i=1:md.mesh.numberoflayers,
+			projected_vector(((i-1)*md.mesh.numberofvertices2d+1):(i*md.mesh.numberofvertices2d),:)=vector2d;
+		end
+	else
+		projected_vector(((layer-1)*md.mesh.numberofvertices2d+1):(layer*md.mesh.numberofvertices2d),:)=vector2d;
+	end
+elseif strcmpi(type,'element'),
+
+	%Initialize 3d vector
+	if size(vector2d,1)==md.mesh.numberofelements2d
+		projected_vector=paddingvalue*ones(md.mesh.numberofelements,  size(vector2d,2));
+	elseif size(vector2d,1)==md.mesh.numberofelements2d+1
+		projected_vector=paddingvalue*ones(md.mesh.numberofelements+1,size(vector2d,2));
+		projected_vector(end,:)=vector2d(end,:);
+		vector2d=vector2d(1:end-1,:);
+	else
+		error('vector length not supported')
+	end
+
+	if layer==0,
+		for i=1:(md.mesh.numberoflayers-1),
+			projected_vector( ((i-1)*md.mesh.numberofelements2d+1):(i*md.mesh.numberofelements2d),:)=vector2d;
+		end
+
+	else
+		projected_vector( ((layer-1)*md.mesh.numberofelements2d+1):(layer*md.mesh.numberofelements2d),:)=vector2d;
+	end
+else
+	error('project3d error message: unknown projection type');
+end
Index: /issm/trunk-jpl/src/m/inversions/misfit.m
===================================================================
--- /issm/trunk-jpl/src/m/inversions/misfit.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/inversions/misfit.m	(revision 13009)
@@ -0,0 +1,37 @@
+function J=misfit(md)
+%MISFIT - compute misfit
+%
+%   Usage:
+%      J=misfit(md)
+%
+%   Example:
+%      J=misfit(md)
+%
+
+if md.mesh.dimension==2,
+	elements=md.mesh.elements;
+	x=md.mesh.x;
+	y=md.mesh.y;
+	vx=md.initialization.vx;
+	vy=md.initialization.vy;
+	vx_obs=md.inversion.vx_obs;
+	vy_obs=md.inversion.vy_obs;
+else
+	elements=md.mesh.elements2d;
+	x=md.mesh.x2d;
+	y=md.mesh.y2d;
+	vx=project2d(md,md.initialization.vx,md.mesh.numberoflayers);
+	vy=project2d(md,md.initialization.vy,md.mesh.numberoflayers);
+	vx_obs=project2d(md,md.inversion.vx_obs,md.mesh.numberoflayers);
+	vy_obs=project2d(md,md.inversion.vy_obs,md.mesh.numberoflayers);
+end
+
+%compute areas;
+areas=GetAreas(elements,x,y);
+
+%compute delta v on elements
+deltav=1/2*(   (vx-vx_obs).^2+(vy-vy_obs).^2)/md.constants.yts^2;
+deltav_elem=deltav(elements)*[1;1;1]/3;
+
+%compute misfit
+J=sum(deltav_elem.*areas);
Index: /issm/trunk-jpl/src/m/inversions/parametercontrolB.m
===================================================================
--- /issm/trunk-jpl/src/m/inversions/parametercontrolB.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/inversions/parametercontrolB.m	(revision 13009)
@@ -0,0 +1,122 @@
+function md=parametercontrolB(md,varargin),
+%PARAMETERCONTROLB - parameterization for control method on B
+%
+%   It is possible to specify the number of steps, values for the
+%   minimum and maximum values of B, the 
+%   kind of cm_responses to use or the the optscal.
+%   
+%   Usage:
+%       md=parametercontrolB(md,varargin)
+%
+%   Example:
+%      md=parametercontrolB(md)
+%      md=parametercontrolB(md,'nsteps',20,'cm_responses',0)
+%      md=parametercontrolB(md,'cm_min',10,'cm_max',10^8,'cm_jump',0.99,'maxiter',20)
+%      md=parametercontrolB(md,eps_cm',10^-4,'optscal',[10^7 10^8])
+%
+%   See also  PARAMETERCONTROLDRAG
+
+%process options
+options=pairoptions(varargin{:});
+
+%control type
+md.inversion.control_parameters={'MaterialsRheologyBbar'};
+
+%weights
+weights=getfieldvalue(options,'weights',ones(md.mesh.numberofvertices,1));
+if (length(weights)~=md.mesh.numberofvertices)
+	md.inversion.cost_functions_coefficients=ones(md.mesh.numberofvertices,1);
+else
+	md.inversion.cost_functions_coefficients=weights;
+end
+
+%nsteps
+nsteps=getfieldvalue(options,'nsteps',100);
+if (length(nsteps)~=1 | nsteps<=0 | floor(nsteps)~=nsteps)
+	md.inversion.nsteps=100;
+else
+	md.inversion.nsteps=nsteps;
+end
+
+
+%cm_min
+cm_min=getfieldvalue(options,'cm_min',paterson(273.15+5)*ones(md.mesh.numberofvertices,1));
+if (length(cm_min)==1)
+	md.inversion.min_parameters=cm_min*ones(md.mesh.numberofvertices,1);
+elseif (length(cm_min)==md.mesh.numberofvertices)
+	md.inversion.min_parameters=cm_min;
+else
+	md.inversion.min_parameters=cm_min;
+end
+
+%cm_max
+cm_max=getfieldvalue(options,'cm_max',paterson(273.15-70)*ones(md.mesh.numberofvertices,1));
+if (length(cm_max)==1)
+	md.inversion.max_parameters=cm_max*ones(md.mesh.numberofvertices,1);
+elseif (length(cm_max)==md.mesh.numberofvertices)
+	md.inversion.max_parameters=cm_max;
+else
+	md.inversion.max_parameters=cm_max;
+end
+
+%eps_cm
+eps_cm=getfieldvalue(options,'eps_cm',NaN);
+if (length(eps_cm)~=1 | eps_cm<0 )
+	md.inversion.cost_function_threshold=NaN;
+else
+	md.inversion.cost_function_threshold=eps_cm;
+end
+
+%maxiter
+maxiter=getfieldvalue(options,'maxiter',10*ones(md.inversion.nsteps,1));
+if (any(maxiter<0) | any(floor(maxiter)~=maxiter))
+	md.inversion.maxiter_per_step=10*ones(md.inversion.nsteps,1);
+else
+	md.inversion.maxiter_per_step=repmat(maxiter(:),md.inversion.nsteps,1);
+	md.inversion.maxiter_per_step(md.inversion.nsteps+1:end)=[];
+end
+
+%cm_jump
+cm_jump=getfieldvalue(options,'cm_jump',0.9*ones(md.inversion.nsteps,1));
+if ~isreal(cm_jump)
+	md.inversion.step_threshold=0.9*ones(md.inversion.nsteps,1);
+else
+	md.inversion.step_threshold=repmat(cm_jump(:),md.inversion.nsteps,1);
+	md.inversion.step_threshold(md.inversion.nsteps+1:end)=[];
+end
+
+%cm_responses
+found=0;
+if exist(options,'cm_responses'),
+	cm_responses=getfieldvalue(options,'cm_responses');
+	if ~any(~ismember(cm_responses,[ 101:105])),
+		md.inversion.cost_functions=repmat(cm_responses(:),md.inversion.nsteps,1);
+		md.inversion.cost_functions(md.inversion.nsteps+1:end)=[];
+		found=1;
+	end
+end
+if ~found
+	third=ceil(md.inversion.nsteps/3);
+	md.inversion.cost_functions=[...
+		103*ones(third,1);...
+		101*ones(third,1);...
+		repmat([101;101;103;101],third,1)...
+		];
+	md.inversion.cost_functions(md.inversion.nsteps+1:end)=[];
+end
+
+%optscal
+found=0;
+if exist(options,'optscal'),
+	optscal=getfieldvalue(options,'optscal');
+	if ~any(optscal<0),
+		md.inversion.gradient_scaling=repmat(optscal(:),md.inversion.nsteps,1);
+		md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[];
+		found=1;
+	end
+end
+if ~found
+	third=ceil(md.inversion.nsteps/3);
+	md.inversion.gradient_scaling=[2*10^8*ones(3,1);10^8*ones(third-3,1);10^7*ones(2*third,1);];
+	md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[];
+end
Index: /issm/trunk-jpl/src/m/inversions/parametercontroldrag.m
===================================================================
--- /issm/trunk-jpl/src/m/inversions/parametercontroldrag.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/inversions/parametercontroldrag.m	(revision 13009)
@@ -0,0 +1,121 @@
+function md=parametercontroldrag(md,varargin),
+%PARAMETERCONTROLDRAG - parameterization for control method on drag
+%
+%   It is possible to specify the number of steps, values for the
+%   minimum and maximum values of the drag, the 
+%   kind of cm_responses to use or the the optscal.
+%   
+%   Usage:
+%       md=parametercontroldrag(md,varargin)
+%
+%   Example:
+%      md=parametercontroldrag(md)
+%      md=parametercontroldrag(md,'nsteps',20,'cm_responses',0)
+%      md=parametercontroldrag(md,'cm_min',1,'cm_max',150,'cm_jump',0.99,'maxiter',20)
+%      md=parametercontroldrag(md,eps_cm',10^-4,'optscal',[10^7 10^8])
+%
+%   See also PARAMETERCONTROLB
+
+%process options
+options=pairoptions(varargin{:});
+
+%control type
+md.inversion.control_parameters={'FrictionCoefficient'};
+
+%weights
+weights=getfieldvalue(options,'weights',ones(md.mesh.numberofvertices,1));
+if (length(weights)~=md.mesh.numberofvertices)
+	md.inversion.cost_functions_coefficients=ones(md.mesh.numberofvertices,1);
+else
+	md.inversion.cost_functions_coefficients=weights;
+end
+
+%nsteps
+nsteps=getfieldvalue(options,'nsteps',100);
+if (length(nsteps)~=1 | nsteps<=0 | floor(nsteps)~=nsteps)
+	md.inversion.nsteps=100;
+else
+	md.inversion.nsteps=nsteps;
+end
+
+%cm_min
+cm_min=getfieldvalue(options,'cm_min',1*ones(md.mesh.numberofvertices,1));
+if (length(cm_min)==1)
+	md.inversion.min_parameters=cm_min*ones(md.mesh.numberofvertices,1);
+elseif (length(cm_min)==md.mesh.numberofvertices)
+	md.inversion.min_parameters=cm_min;
+else
+	md.inversion.min_parameters=cm_min;
+end
+
+%cm_max
+cm_max=getfieldvalue(options,'cm_max',250*ones(md.mesh.numberofvertices,1));
+if (length(cm_max)==1)
+	md.inversion.max_parameters=cm_max*ones(md.mesh.numberofvertices,1);
+elseif (length(cm_max)==md.mesh.numberofvertices)
+	md.inversion.max_parameters=cm_max;
+else
+	md.inversion.max_parameters=cm_max;
+end
+
+%eps_cm
+eps_cm=getfieldvalue(options,'eps_cm',NaN);
+if (length(eps_cm)~=1 | eps_cm<0 )
+	md.inversion.cost_function_threshold=NaN;
+else
+	md.inversion.cost_function_threshold=eps_cm;
+end
+
+%maxiter
+maxiter=getfieldvalue(options,'maxiter',10*ones(md.inversion.nsteps,1));
+if (any(maxiter<0) | any(floor(maxiter)~=maxiter))
+	md.inversion.maxiter_per_step=10*ones(md.inversion.nsteps,1);
+else
+	md.inversion.maxiter_per_step=repmat(maxiter(:),md.inversion.nsteps,1);
+	md.inversion.maxiter_per_step(md.inversion.nsteps+1:end)=[];
+end
+
+%cm_jump
+cm_jump=getfieldvalue(options,'cm_jump',0.8*ones(md.inversion.nsteps,1));
+if ~isreal(cm_jump)
+	md.inversion.step_threshold=0.8*ones(md.inversion.nsteps,1);
+else
+	md.inversion.step_threshold=repmat(cm_jump(:),md.inversion.nsteps,1);
+	md.inversion.step_threshold(md.inversion.nsteps+1:end)=[];
+end
+
+%cm_responses
+found=0;
+if exist(options,'cm_responses'),
+	cm_responses=getfieldvalue(options,'cm_responses');
+	if ~any(~ismember(cm_responses,[101 105]))
+		md.inversion.cost_functions=repmat(cm_responses(:),md.inversion.nsteps,1);
+		md.inversion.cost_functions(md.inversion.nsteps+1:end)=[];
+		found=1;
+	end
+end
+if ~found
+	third=ceil(md.inversion.nsteps/3);
+	md.inversion.cost_functions=[...
+		103*ones(third,1);...
+		101*ones(third,1);...
+		repmat([101;101;103;101],third,1)...
+		];
+	md.inversion.cost_functions(md.inversion.nsteps+1:end)=[];
+end
+
+%optscal
+found=0;
+if exist(options,'optscal'),
+	optscal=getfieldvalue(options,'optscal');
+	if ~any(optscal<0),
+		md.inversion.gradient_scaling=repmat(optscal(:),md.inversion.nsteps,1);
+		md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[];
+		found=1;
+	end
+end
+if ~found
+	third=ceil(md.inversion.nsteps/3);
+	md.inversion.gradient_scaling=[50*ones(3,1);15*ones(third-3,1);10*ones(third,1);repmat([10;10;20;10],third,1)];
+	md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[];
+end
Index: /issm/trunk-jpl/src/m/io/loadmodel.m
===================================================================
--- /issm/trunk-jpl/src/m/io/loadmodel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/io/loadmodel.m	(revision 13009)
@@ -0,0 +1,46 @@
+function varargout=loadmodel(path)
+%LOADMODEL - load a model using built-in load module
+%
+%   check that model prototype has not changed. if so, adapt to new model prototype.
+%
+%   Usage:
+%      md=loadmodel(path)
+%      loadmodel path
+
+%check nargout
+if nargout>1,
+	error('loadmodel usage error: md=loadmodel(path)');
+end
+
+%check existence
+if exist(path,'file')
+	%do nothing
+elseif exist([path '.mat'],'file')
+	%add extension
+	path = [path '.mat'];
+else
+	error(['loadmodel error message: file ' path ' does not exist']);
+end
+
+try,
+	%recover model on file and name it md
+	warning off MATLAB:unknownElementsNowStruc;
+	warning off MATLAB:load:classNotFound
+	struc=load(path,'-mat');
+	warning on MATLAB:unknownElementsNowStruc;
+	warning on MATLAB:load:classNotFound
+
+	name=char(fieldnames(struc));
+	if size(name,1)>1,
+		error(['loadmodel error message: file ' path ' contains several variables. Only one model should be present.']); 
+	end
+	md=struc.(name);
+	if nargout,
+		varargout{1}=md;
+	else
+		assignin('caller',name,md);
+	end
+catch me
+	disp(getReport(me))
+	error(['could not load model ' path]);
+end
Index: /issm/trunk-jpl/src/m/io/loadmodellist.m
===================================================================
--- /issm/trunk-jpl/src/m/io/loadmodellist.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/io/loadmodellist.m	(revision 13009)
@@ -0,0 +1,50 @@
+function varargout=loadmodellist(path)
+%LOADMODELLIST- load a model using built-in load module
+%
+%   check that modellist prototype has not changed. if so, adapt to new modellist prototype.
+%
+%   Usage:
+%      mds=loadmodellist(path)
+%      loadmodellist path
+
+%check nargout
+if nargout>1,
+	error('loadmodellist usage error: mds=loadmodellist(path)');
+end
+%check existence
+if ~exist(path)
+	error(['loadmodellist error message: file ' path ' does not exist']);
+end
+
+%check that the file is readable
+[stat,mess]=fileattrib(path);
+if( stat==0 | mess.UserRead~=1),
+	error(['loadmodellist error message: file ' path ' is not readable (permission dinied).']);
+end
+
+%check number of variables
+if length(whos('-file',path))>1,
+	error(['loadmodellist error message: file ' path ' contains several variables. Only one model should be present.']);
+end
+
+try,
+	struc=load(path,'-mat');
+
+	%get name of model variable
+	fieldname=char(fieldnames(struc));
+	mds=eval(['struc.' fieldname]);
+	if ~strcmpi(class(mds),'model'),
+		mds2=modellist;
+		mds2=structtomodel(mds2,mds);
+		mds=mds2;
+		clear mds2;
+	end
+	if nargout,
+		varargout{1}=mds;
+	else
+		assignin('caller',fieldname,mds);
+	end
+catch me
+	disp(getReport(me))
+	error(['could not load model ' path]);
+end
Index: /issm/trunk-jpl/src/m/mesh/bamg.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/bamg.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/bamg.m	(revision 13009)
@@ -0,0 +1,483 @@
+function md=bamg(md,varargin)
+%BAMG - mesh generation
+%
+%   Available options (for more details see ISSM website http://issm.jpl.nasa.gov/):
+%
+%   - domain :            followed by an ARGUS file that prescribes the domain outline
+%   - hmin :              minimum edge length (default is 10^-100)
+%   - hmax :              maximum edge length (default is 10^100)
+%   - hVertices :         imposed edge length for each vertex (geometry or mesh)
+%   - hminVertices :      minimum edge length for each vertex (mesh)
+%   - hmaxVertices :      maximum edge length for each vertex (mesh)
+%
+%   - anisomax :          maximum ratio between the smallest and largest edges (default is 10^30)
+%   - coeff :             coefficient applied to the metric (2-> twice as many elements, default is 1)
+%   - cutoff :            scalar used to compute the metric when metric type 2 or 3 are applied
+%   - err :               error used to generate the metric from a field
+%   - errg :              geometric error (default is 0.1)
+%   - field :             field of the model that will be used to compute the metric
+%                         to apply several fields, use one column per field
+%   - gradation :         maximum ratio between two adjacent edges
+%   - Hessiantype :       0 -> use double P2 projection (default)
+%                         1 -> use Green formula
+%   - KeepVertices :      try to keep initial vertices when adaptation is done on an existing mesh (default 1)
+%   - MaxCornerAngle :    maximum angle of corners in degree (default is 10)
+%   - maxnbv :            maximum number of vertices used to allocate memory (default is 10^6)
+%   - maxsubdiv :         maximum subdivision of exisiting elements (default is 10)
+%   - metric :            matrix (numberofnodes x 3) used as a metric
+%   - Metrictype :        1 -> absolute error          c/(err coeff^2) * Abs(H)        (default)
+%                         2 -> relative error          c/(err coeff^2) * Abs(H)/max(s,cutoff*max(s))
+%                         3 -> rescaled absolute error c/(err coeff^2) * Abs(H)/(smax-smin)
+%   - nbjacoby :          correction used by Hessiantype=1 (default is 1)
+%   - nbsmooth :          number of metric smoothing procedure (default is 3)
+%   - omega :             relaxation parameter of the smoothing procedure (default is 1.8)
+%   - power :             power applied to the metric (default is 1)
+%   - splitcorners :      split triangles whuch have 3 vertices on the outline (default is 1)
+%   - geometricalmetric : take the geometry into account to generate the metric (default is 0)
+%   - verbose :           level of verbosity (default is 1)
+%
+%   - rifts :             followed by an ARGUS file that prescribes the rifts
+%   - toltip :            tolerance to move tip on an existing point of the domain outline
+%   - tracks :            followed by an ARGUS file that prescribes the tracks that the mesh will stick to
+%   - RequiredVertices :  mesh vertices that are required. [x,y,ref]; ref is optional
+%   - tol :               if the distance between 2 points of the domain outline is less than tol, they
+%                         will be merged
+%
+%   Examples:
+%      md=bamg(md,'domain','DomainOutline.exp','hmax',3000);
+%      md=bamg(md,'field',[md.inversion.vel_obs md.geometry.thickness],'hmax',20000,'hmin',1000);
+%      md=bamg(md,'metric',A,'hmin',1000,'hmax',20000,'gradation',3,'anisomax',1);
+
+%process options
+options=pairoptions(varargin{:});
+options=deleteduplicates(options,1);
+
+%initialize the structures required as input of Bamg
+bamg_options=struct();
+bamg_geometry=bamggeom;
+bamg_mesh=bamgmesh;
+
+% Bamg Geometry parameters {{{
+if exist(options,'domain'),
+
+	%Check that file exists
+	domainfile=getfieldvalue(options,'domain');
+	if ~exist(domainfile,'file') error(['bamg error message: file ' domainfile ' not found ']); end
+
+	%Build geometry 
+	domain=expread(domainfile);
+	count=0;
+	for i=1:length(domain),
+
+		%Check that the domain is closed
+		if (domain(i).x(1)~=domain(i).x(end) | domain(i).y(1)~=domain(i).y(end)),
+			error('bamg error message: all contours provided in ''domain'' should be closed');
+		end
+
+		%Checks that all holes are INSIDE the principle domain outline
+		if i>1,
+			flags=ContourToNodes(domain(i).x,domain(i).y,domain(1),0);
+			if any(~flags),
+				error('bamg error message: All holes should be stricly inside the principal domain');
+			end
+		end
+
+		%Add all points to bamg_geometry
+		nods=domain(i).nods-1; %the domain are closed 1=end;
+		bamg_geometry.Vertices=[bamg_geometry.Vertices; [domain(i).x(1:nods) domain(i).y(1:nods) ones(nods,1)]];
+		bamg_geometry.Edges   =[bamg_geometry.Edges;    [transpose(count+1:count+nods) transpose([count+2:count+nods count+1])  1*ones(nods,1)]];
+		if i>1, bamg_geometry.SubDomains=[bamg_geometry.SubDomains; 2 count+1 1 1]; end
+
+		%update counter
+		count=count+nods;
+	end
+
+	%take care of rifts
+	if exist(options,'rifts'),
+
+		%Check that file exists
+		riftfile=getfieldvalue(options,'rifts');
+		if ~exist(riftfile,'file')
+			error(['bamg error message: file ' riftfile ' not found ']);
+		end
+		rift=expread(riftfile);
+
+		for i=1:length(rift),
+
+			%detect wether all points of the rift are inside the domain
+			flags=ContourToNodes(rift(i).x,rift(i).y,domain(1),0);
+			if ~flags,
+				error('one Rift has all his points outside of the domain outline'),
+
+			elseif any(~flags),
+				%We LOTS of work to do
+				disp('Rift tip outside of or on the domain has been detected and is being processed...');
+
+				%check that only one point is outsie (for now)
+				if sum(~flags)~=1,
+					error('bamg error message: only one point outside of the domain is supported yet');
+				end
+
+				%Move tip outside to the first position
+				if flags(1)==0,
+					%OK, first point is outside (do nothing),
+				elseif (flags(end)==0),
+					rift(i).x=flipud(rift(i).x);
+					rift(i).y=flipud(rift(i).y);
+				else
+					error('bamg error message: only a rift tip can be outside of the domain');
+				end
+
+				%Get cordinate of intersection point
+				x1=rift(i).x(1); y1=rift(i).y(1);
+				x2=rift(i).x(2); y2=rift(i).y(2);
+				for j=1:length(domain(1).x)-1;
+					if SegIntersect([x1 y1; x2 y2],[domain(1).x(j) domain(1).y(j); domain(1).x(j+1) domain(1).y(j+1)]),
+
+						%Get position of the two nodes of the edge in domain
+						i1=j;
+						i2=mod(j+1,domain(1).nods);
+
+						%rift is crossing edge [i1 i2] of the domain
+						%Get coordinate of intersection point (http://mathworld.wolfram.com/Line-LineIntersection.html)
+						x3=domain(1).x(i1); y3=domain(1).y(i1);
+						x4=domain(1).x(i2); y4=domain(1).y(i2);
+						x=det([det([x1 y1; x2 y2])  x1-x2;det([x3 y3; x4 y4])  x3-x4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
+						y=det([det([x1 y1; x2 y2])  y1-y2;det([x3 y3; x4 y4])  y3-y4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
+
+						segdis= sqrt((x4-x3)^2+(y4-y3)^2);
+						tipdis=[sqrt((x-x3)^2+(y-y3)^2)  sqrt((x-x4)^2+(y-y4)^2)];
+
+						if (min(tipdis)/segdis) < getfieldvalue(options,'toltip',0),
+							disp('moving tip-domain intersection point');
+
+							%Get position of the closest point
+							if tipdis(1)>tipdis(2),
+								pos=i2;
+							else
+								pos=i1;
+							end
+
+							%This point is only in Vertices (number pos).
+							%OK, no we can add our own rift
+							nods=rift(i).nods-1;
+							bamg_geometry.Vertices=[bamg_geometry.Vertices; [rift(i).x(2:end) rift(i).y(2:end) ones(nods,1)]];
+							bamg_geometry.Edges=[bamg_geometry.Edges;...
+								pos count+1  (1+i);...
+								[transpose(count+1:count+nods-1) transpose([count+2:count+nods])  (1+i)*ones(nods-1,1)]];
+							count=count+nods;
+
+							break;
+
+						else
+							%Add intersection point to Vertices
+							bamg_geometry.Vertices=[bamg_geometry.Vertices; x y 1];
+							count=count+1;
+
+							%Decompose the crossing edge in 2 subedges
+							pos=find(bamg_geometry.Edges(:,1)==i1 & bamg_geometry.Edges(:,2)==i2);
+							if isempty(pos) error('bamg error message: a problem occured...'); end
+							bamg_geometry.Edges=[bamg_geometry.Edges(1:pos-1,:);...
+								bamg_geometry.Edges(pos,1) count                           bamg_geometry.Edges(pos,3);...
+								count                      bamg_geometry.Edges(pos,2)   bamg_geometry.Edges(pos,3);...
+								bamg_geometry.Edges(pos+1:end,:)];
+
+							%OK, no we can add our own rift
+							nods=rift(i).nods-1;
+							bamg_geometry.Vertices=[bamg_geometry.Vertices; [rift(i).x(2:end) rift(i).y(2:end) ones(nods,1)]];
+							bamg_geometry.Edges=[bamg_geometry.Edges;...
+								count  count+1  2 ;...
+								[transpose(count+1:count+nods-1) transpose([count+2:count+nods])  (1+i)*ones(nods-1,1)]];
+							count=count+nods;
+
+							break;
+						end
+					end
+				end
+			else
+				nods=rift(i).nods-1;
+				bamg_geometry.Vertices=[bamg_geometry.Vertices; [rift(i).x(:) rift(i).y(:) ones(nods+1,1)]];
+				bamg_geometry.Edges=[bamg_geometry.Edges; [transpose(count+1:count+nods) transpose([count+2:count+nods+1])  (1+i)*ones(nods,1)]];
+				count=count+nods+1;
+			end
+		end
+	end
+
+	%Deal with tracks
+	if exist(options,'tracks'),
+
+		%read tracks
+		track=getfieldvalue(options,'tracks');
+		if all(ischar(track)),
+			A=expread(track); 
+			track=[A.x A.y];
+		else
+			track=double(track); %for some reason, it is of class "single"
+		end
+		if(size(track,2)==2), track=[track 3*ones(size(track,1),1)]; end
+
+		%only keep those inside
+		flags=ContourToNodes(track(:,1),track(:,2),domainfile,0);
+		track=track(find(flags),:);
+
+		%Add all points to bamg_geometry
+		nods=size(track,1);
+		bamg_geometry.Vertices=[bamg_geometry.Vertices; track];
+		bamg_geometry.Edges=[bamg_geometry.Edges; [transpose(count+1:count+nods-1) transpose([count+2:count+nods])  3*ones(nods-1,1)]];
+
+		%update counter
+		count=count+nods;
+	end
+
+	%Deal with vertices that need to be kept by mesher
+	if exist(options,'RequiredVertices'),
+
+		%recover RequiredVertices
+		requiredvertices=double(getfieldvalue(options,'RequiredVertices')); %for some reason, it is of class "single"
+		if(size(requiredvertices,2)==2), requiredvertices=[requiredvertices 4*ones(size(requiredvertices,1),1)]; end
+	
+		%only keep those inside
+		flags=ContourToNodes(requiredvertices(:,1),requiredvertices(:,2),domain(1),0);
+		requiredvertices=requiredvertices(find(flags),:);
+
+		%Add all points to bamg_geometry
+		nods=size(requiredvertices,1);
+		bamg_geometry.Vertices=[bamg_geometry.Vertices; requiredvertices];
+
+		%update counter
+		count=count+nods;
+
+	end
+
+	%process geom
+	%bamg_geometry=processgeometry(bamg_geometry,getfieldvalue(options,'tol',NaN),domain(1));
+
+elseif isstruct(md.private.bamg) & isfield(md.private.bamg,'geometry'),
+	bamg_geometry=bamggeom(md.private.bamg.geometry); 
+else
+	%do nothing...
+end
+%}}}
+% Bamg Mesh parameters {{{
+if (~exist(options,'domain') & md.mesh.numberofvertices~=0 & md.mesh.dimension==2),
+
+	if isstruct(md.private.bamg) & isfield(md.private.bamg,'mesh'),
+		bamg_mesh=bamgmesh(md.private.bamg.mesh);
+	else
+		bamg_mesh.Vertices=[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)];
+		bamg_mesh.Triangles=[md.mesh.elements ones(md.mesh.numberofelements,1)];
+	end
+
+	if isstruct(md.rifts.riftstruct)
+		error('bamg error message: rifts not supported yet. Do meshprocessrift AFTER bamg');
+	end
+end
+%}}}
+% Bamg Options {{{
+bamg_options.Crack=getfieldvalue(options,'Crack',0);
+bamg_options.anisomax=getfieldvalue(options,'anisomax',10^30);
+bamg_options.coeff=getfieldvalue(options,'coeff',1);
+bamg_options.cutoff=getfieldvalue(options,'cutoff',10^-5);
+bamg_options.err=getfieldvalue(options,'err',0.01);
+bamg_options.errg=getfieldvalue(options,'errg',0.1);
+bamg_options.field=getfieldvalue(options,'field',[]);
+bamg_options.gradation=getfieldvalue(options,'gradation',1.5);
+bamg_options.Hessiantype=getfieldvalue(options,'Hessiantype',0);
+bamg_options.hmin=getfieldvalue(options,'hmin',10^-100);
+bamg_options.hmax=getfieldvalue(options,'hmax',10^100);
+bamg_options.hminVertices=getfieldvalue(options,'hminVertices',[]);
+bamg_options.hmaxVertices=getfieldvalue(options,'hmaxVertices',[]);
+bamg_options.hVertices=getfieldvalue(options,'hVertices',[]);
+bamg_options.KeepVertices=getfieldvalue(options,'KeepVertices',1);
+bamg_options.MaxCornerAngle=getfieldvalue(options,'MaxCornerAngle',10);
+bamg_options.maxnbv=getfieldvalue(options,'maxnbv',10^6);
+bamg_options.maxsubdiv=getfieldvalue(options,'maxsubdiv',10);
+bamg_options.metric=getfieldvalue(options,'metric',[]);
+bamg_options.Metrictype=getfieldvalue(options,'Metrictype',0);
+bamg_options.nbjacobi=getfieldvalue(options,'nbjacobi',1);
+bamg_options.nbsmooth=getfieldvalue(options,'nbsmooth',3);
+bamg_options.omega=getfieldvalue(options,'omega',1.8);
+bamg_options.power=getfieldvalue(options,'power',1);
+bamg_options.splitcorners=getfieldvalue(options,'splitcorners',1);
+bamg_options.geometricalmetric=getfieldvalue(options,'geometricalmetric',0);
+bamg_options.verbose=getfieldvalue(options,'verbose',1);
+%}}}
+
+%call Bamg
+[bamgmesh_out bamggeom_out]=BamgMesher(bamg_mesh,bamg_geometry,bamg_options);
+
+% plug results onto model
+md.private.bamg=struct();
+md.private.bamg.mesh=bamgmesh(bamgmesh_out);
+md.private.bamg.geometry=bamggeom(bamggeom_out);
+md.mesh.x=bamgmesh_out.Vertices(:,1);
+md.mesh.y=bamgmesh_out.Vertices(:,2);
+md.mesh.elements=bamgmesh_out.Triangles(:,1:3);
+md.mesh.edges=bamgmesh_out.IssmEdges;
+md.mesh.segments=bamgmesh_out.IssmSegments(:,1:3);
+md.mesh.segmentmarkers=bamgmesh_out.IssmSegments(:,4);
+
+%Fill in rest of fields:
+md.mesh.dimension=2;
+md.mesh.numberofelements=size(md.mesh.elements,1);
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.numberofedges=size(md.mesh.edges,1);
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mask.vertexonwater=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+md.mesh.elementconnectivity=md.private.bamg.mesh.ElementConnectivity;
+md.mesh.elementconnectivity(find(isnan(md.mesh.elementconnectivity)))=0;
+
+%Check for orphan
+reshape(md.mesh.elements,3*md.mesh.numberofelements,1);
+(~ismember(1:md.mesh.numberofvertices,sort(unique(reshape(md.mesh.elements,3*md.mesh.numberofelements,1)))));
+if any(~ismember(1:md.mesh.numberofvertices,sort(unique(reshape(md.mesh.elements,3*md.mesh.numberofelements,1)))))
+	error('Output mesh has orphans. Decrease MaxCornerAngle to prevent outside points (ex: 0.01)');
+end
+end 
+
+function geom=processgeometry(geom,tol,outline); % {{{
+
+%Deal with edges
+disp('Checking Edge crossing...');
+i=0;
+while (i<size(geom.Edges,1)),
+
+	%edge counter
+	i=i+1;
+
+	%Get coordinates
+	x1=geom.Vertices(geom.Edges(i,1),1);
+	y1=geom.Vertices(geom.Edges(i,1),2);
+	x2=geom.Vertices(geom.Edges(i,2),1);
+	y2=geom.Vertices(geom.Edges(i,2),2);
+	color1=geom.Edges(i,3);
+
+	j=i; %test edges located AFTER i only
+	while (j<size(geom.Edges,1)),
+
+		%edge counter
+		j=j+1;
+
+		%Skip if the two edges already have a vertex in common
+		if any(ismember(geom.Edges(i,1:2),geom.Edges(j,1:2))),
+			continue
+		end
+
+		%Get coordinates
+		x3=geom.Vertices(geom.Edges(j,1),1);
+		y3=geom.Vertices(geom.Edges(j,1),2);
+		x4=geom.Vertices(geom.Edges(j,2),1);
+		y4=geom.Vertices(geom.Edges(j,2),2);
+		color2=geom.Edges(j,3);
+
+		%Check if the two edges are crossing one another
+		if SegIntersect([x1 y1; x2 y2],[x3 y3; x4 y4]),
+
+			%Get coordinate of intersection point (http://mathworld.wolfram.com/Line-LineIntersection.html)
+			x=det([det([x1 y1; x2 y2])  x1-x2;det([x3 y3; x4 y4])  x3-x4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
+			y=det([det([x1 y1; x2 y2])  y1-y2;det([x3 y3; x4 y4])  y3-y4])/det([x1-x2 y1-y2;x3-x4 y3-y4]);
+
+			%Add vertex to the list of vertices
+			geom.Vertices(end+1,:)=[x y min(color1,color2)];
+			id=size(geom.Vertices,1);
+
+			%Update edges i and j
+			edgei=geom.Edges(i,:);
+			edgej=geom.Edges(j,:);
+			geom.Edges(i,:)    =[edgei(1) id       edgei(3)];
+			geom.Edges(end+1,:)=[id       edgei(2) edgei(3)];
+			geom.Edges(j,:)    =[edgej(1) id       edgej(3)];
+			geom.Edges(end+1,:)=[id       edgej(2) edgej(3)];
+
+			%update current edge second tip
+			x2=x; y2=y;
+		end
+	end
+
+end
+
+%Check point outside
+disp('Checking for points outside the domain...');
+i=0;
+num=0;
+while (i<size(geom.Vertices,1)),
+
+	%vertex counter
+	i=i+1;
+
+	%Get coordinates
+	x=geom.Vertices(i,1);
+	y=geom.Vertices(i,2);
+	color=geom.Vertices(i,3);
+
+	%Check that the point is inside the domain
+	if (color~=1 & ~ContourToNodes(x,y,outline(1),1)),
+
+		%Remove points from list of Vertices
+		num=num+1;
+		geom.Vertices(i,:)=[];
+
+		%update edges
+		[posedges dummy]=find(geom.Edges==i);
+		geom.Edges(posedges,:)=[];
+		posedges=find(geom.Edges>i);
+		geom.Edges(posedges)=geom.Edges(posedges)-1;
+
+		%update counter
+		i=i-1;
+	end
+end
+if num,
+	disp(['WARNING: ' num2str(num) ' points outside the domain outline have been removed']);
+end
+
+%Check point spacing
+if ~isnan(tol),
+	disp('Checking point spacing...');
+	i=0;
+	while (i<size(geom.Vertices,1)),
+
+		%vertex counter
+		i=i+1;
+
+		%Get coordinates
+		x1=geom.Vertices(i,1);
+		y1=geom.Vertices(i,2);
+
+		j=i; %test edges located AFTER i only
+		while (j<size(geom.Vertices,1)),
+
+			%vertex counter
+			j=j+1;
+
+			%Get coordinates
+			x2=geom.Vertices(j,1);
+			y2=geom.Vertices(j,2);
+
+			%Check whether the two vertices are too close
+			if ((x2-x1)^2+(y2-y1)^2<tol^2)
+
+				%Remove points from list of Vertices
+				geom.Vertices(j,:)=[];
+
+				%update edges
+				posedges=find(ismember(geom.Edges,j));
+				geom.Edges(posedges)=i;
+				posedges=find(geom.Edges>j);
+				geom.Edges(posedges)=geom.Edges(posedges)-1;
+
+				%update counter
+				j=j-1;
+
+			end
+		end
+	end
+end
+%remove empty edges
+geom.Edges(find(geom.Edges(:,1)==geom.Edges(:,2)),:)=[];
+end % }}}
Index: /issm/trunk-jpl/src/m/mesh/findsegments.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/findsegments.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/findsegments.m	(revision 13009)
@@ -0,0 +1,92 @@
+function segments=findsegments(md,varargin)
+%FINDSEGMENTS - build segments model field
+%
+%   Optional inputs:
+%      'mesh.elementconnectivity'
+%
+%   Usage:
+%      segments=findsegments(md,varargin);
+
+%get options
+options=pairoptions(varargin{:});
+
+%Get connectivity
+mesh.elementconnectivity=getfieldvalue(options,'mesh.elementconnectivity',md.mesh.elementconnectivity);
+
+%Now, build the connectivity tables for this mesh if not correclty done
+if size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements,
+	if exist(options,'mesh.elementconnectivity'),
+		error(' ''mesh.elementconnectivity'' option does not have thge right size.');
+	else
+		mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+	end
+end
+
+%Recreate the segments
+elementonboundary=double(mesh.elementconnectivity(:,3)==0);
+pos=find(elementonboundary);
+num_segments=length(pos);
+segments=zeros(num_segments,3);
+count=1;
+
+%loop over the segments
+for i=1:num_segments,
+
+	%get current element on boundary
+	el1=pos(i);
+
+	%get elements connected to el1
+	els2=mesh.elementconnectivity(el1,find(mesh.elementconnectivity(el1,:)));
+
+	%el1 is connected to 2 other elements
+	if length(els2)>1,
+
+		%get nodes of el1
+		nods1=md.mesh.elements(el1,:);
+
+		%find the common vertices to the two elements connected to el1 (1 or 2)
+		flag=intersect(md.mesh.elements(els2(1),:),md.mesh.elements(els2(2),:));
+
+		%get the vertices on the boundary and build segment
+		nods1(find(ismember(nods1,flag)))=[];
+		segments(count,:)=[nods1 el1];
+
+		%swap segment nodes if necessary
+		ord1=find(nods1(1)==md.mesh.elements(el1,:));
+		ord2=find(nods1(2)==md.mesh.elements(el1,:));
+		if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ),
+			temp=segments(count,1);
+			segments(count,1)=segments(count,2);
+			segments(count,2)=temp;
+		end
+		segments(count,1:2)=fliplr(segments(count,1:2));
+		count=count+1;
+
+	%el1 is connected to only one element
+	else
+		%get nodes of el1
+		nods1=md.mesh.elements(el1,:);
+
+		%find the vertex  the el1 to not share with els2
+		flag=setdiff(nods1,md.mesh.elements(els2,:));
+
+		for j=1:3,
+			nods=nods1; nods(j)=[];
+			if any(ismember(flag,nods)),
+
+				segments(count,:)=[nods el1];
+
+				%swap segment nodes if necessary
+				ord1=find(nods(1)==md.mesh.elements(el1,:));
+				ord2=find(nods(2)==md.mesh.elements(el1,:));
+				if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ),
+					temp=segments(count,1);
+					segments(count,1)=segments(count,2);
+					segments(count,2)=temp;
+				end
+				segments(count,1:2)=fliplr(segments(count,1:2));
+				count=count+1;
+			end
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/mesh/meshconvert.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/meshconvert.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/meshconvert.m	(revision 13009)
@@ -0,0 +1,48 @@
+function md=meshconvert(md,varargin)
+%CONVERTMESH - convert mesh to bamg mesh
+%
+%   Usage:
+%      md=meshconvert(md);
+%      md=meshconvert(md,index,x,y);
+
+if nargin~=1 & nargin~=4,
+	help meshconvert
+	error('meshconvert error message: bad usage');
+end
+
+if nargin==1,
+	x=md.mesh.x;
+	y=md.mesh.y;
+	index=md.mesh.elements;
+else
+	x=varargin{1};
+	y=varargin{2};
+	index=varargin{3};
+end
+
+%call Bamg
+[bamgmesh_out bamggeom_out]=BamgConvertMesh(index,x,y);
+
+% plug results onto model
+md.private.bamg=struct();
+md.private.bamg.mesh=bamgmesh(bamgmesh_out);
+md.private.bamg.geometry=bamggeom(bamggeom_out);
+md.mesh.x=bamgmesh_out.Vertices(:,1);
+md.mesh.y=bamgmesh_out.Vertices(:,2);
+md.mesh.elements=bamgmesh_out.Triangles(:,1:3);
+md.mesh.edges=bamgmesh_out.IssmEdges;
+md.mesh.segments=bamgmesh_out.IssmSegments(:,1:3);
+md.mesh.segmentmarkers=bamgmesh_out.IssmSegments(:,4);
+
+%Fill in rest of fields:
+md.mesh.dimension=2;
+md.mesh.numberofelements=size(md.mesh.elements,1);
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.numberofedges=size(md.mesh.edges,1);
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mask.vertexonwater=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
Index: /issm/trunk-jpl/src/m/mesh/planet/mesh_refine_tri4.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/mesh_refine_tri4.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/mesh_refine_tri4.m	(revision 13009)
@@ -0,0 +1,146 @@
+function [ FV ] = mesh_refine_tri4(FV)
+
+% mesh_refine_tri4 - creates 4 triangle from each triangle of a mesh
+%
+% [ FV ] = mesh_refine_tri4( FV )
+%
+% FV.vertices   - mesh vertices (Nx3 matrix)
+% FV.faces      - faces with indices into 3 rows
+%                 of FV.vertices (Mx3 matrix)
+% 
+% For each face, 3 new vertices are created at the 
+% triangle edge midpoints.  Each face is divided into 4
+% faces and returned in FV.
+%
+%        B
+%       /\
+%      /  \
+%    a/____\b       Construct new triangles
+%    /\    /\       [A,a,c]
+%   /  \  /  \      [a,B,b]
+%  /____\/____\     [c,b,C]
+% A	     c	   C    [a,b,c]
+% 
+% It is assumed that the vertices are listed in clockwise order in
+% FV.faces (A,B,C above), as viewed from the outside in a RHS coordinate
+% system.
+% 
+% See also: mesh_refine, sphere_tri, sphere_project
+% 
+
+
+% ---this method is not implemented, but the idea here remains...
+% This can be done until some minimal distance (D) of the mean 
+% distance between vertices of all triangles is achieved.  If
+% no D argument is given, the function refines the mesh once.
+% Alternatively, it could be done until some minimum mean 
+% area of faces is achieved.  As is, it just refines once.
+
+
+% $Revision: 1.1 $ $Date: 2004/11/12 01:32:35 $
+
+% Licence:  GNU GPL, no implied or express warranties
+% History:  05/2002, Darren.Weber_at_radiology.ucsf.edu, created
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+tic;
+fprintf('...refining mesh (tri4)...')
+
+% NOTE
+% The centroid is located one third of the way from each vertex to 
+% the midpoint of the opposite side. Each median divides the triangle 
+% into two equal areas; all the medians together divide it into six 
+% equal parts, and the lines from the median point to the vertices 
+% divide the whole into three equivalent triangles.
+
+% Each input triangle with vertices labelled [A,B,C] as shown
+% below will be turned into four new triangles:
+%
+% Make new midpoints
+% a = (A+B)/2
+% b = (B+C)/2
+% c = (C+A)/2
+%
+%        B
+%       /\
+%      /  \
+%    a/____\b       Construct new triangles
+%    /\    /\       [A,a,c]
+%   /  \  /  \      [a,B,b]
+%  /____\/____\     [c,b,C]
+% A	     c	   C    [a,b,c]
+%
+
+% Initialise a new vertices and faces matrix
+Nvert = size(FV.vertices,1);
+Nface = size(FV.faces,1);
+V2 = zeros(Nface*3,3);
+F2 = zeros(Nface*4,3);
+
+for f = 1:Nface,
+    
+    % Get the triangle vertex indices
+    NA = FV.faces(f,1);
+    NB = FV.faces(f,2);
+    NC = FV.faces(f,3);
+    
+    % Get the triangle vertex coordinates
+    A = FV.vertices(NA,:);
+    B = FV.vertices(NB,:);
+    C = FV.vertices(NC,:);
+    
+    % Now find the midpoints between vertices
+    a = (A + B) ./ 2;
+    b = (B + C) ./ 2;
+    c = (C + A) ./ 2;
+    
+    % Find the length of each median
+    %A2blen = sqrt ( sum( (A - b).^2, 2 ) );
+    %B2clen = sqrt ( sum( (B - c).^2, 2 ) );
+    %C2alen = sqrt ( sum( (C - a).^2, 2 ) );
+    
+    % Store the midpoint vertices, while
+    % checking if midpoint vertex already exists
+    [FV, Na] = mesh_find_vertex(FV,a);
+    [FV, Nb] = mesh_find_vertex(FV,b);
+    [FV, Nc] = mesh_find_vertex(FV,c);
+    
+    % Create new faces with orig vertices plus midpoints
+    F2(f*4-3,:) = [ NA, Na, Nc ];
+    F2(f*4-2,:) = [ Na, NB, Nb ];
+    F2(f*4-1,:) = [ Nc, Nb, NC ];
+    F2(f*4-0,:) = [ Na, Nb, Nc ];
+    
+end
+
+% Replace the faces matrix
+FV.faces = F2;
+
+t=toc; fprintf('done (%5.2f sec)\n',t);
+
+return
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [FV, N] = mesh_find_vertex(FV,vertex)
+
+    Vn = size(FV.vertices,1);
+    Va = repmat(vertex,Vn,1);
+    Vexist = find( FV.vertices(:,1) == Va(:,1) & ...
+                   FV.vertices(:,2) == Va(:,2) & ...
+                   FV.vertices(:,3) == Va(:,3) );
+    if Vexist,
+        if size(Vexist) == [1,1],
+            N = Vexist;
+        else,
+            msg = sprintf('replicated vertices');
+            error(msg);
+        end
+    else
+        FV.vertices(end+1,:) = vertex;
+        N = size(FV.vertices,1);
+    end
+
+return
Index: /issm/trunk-jpl/src/m/mesh/planet/planetmesher.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/planetmesher.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/planetmesher.m	(revision 13009)
@@ -0,0 +1,35 @@
+function md=planetmesher(md,varargin)
+%PLANETMESHER - create planet mesh using several packages
+%
+%   This routine creates a planet mesh using several packages: a custom made 
+%   ISSM mesher (called planetmixedmesh.m, method 'mixed') and the planettrimesh
+%   (method 'tria')
+%   where md is a @planet object, varargin is a list of options
+%
+% Usage: md=planetmesher(md,'method','mixed','radius',6378000,'angleresol',1);
+%        md=planetmesher(md,'method','tria','shape','iso','radius',6378000,'refinement',5);
+%
+%
+
+	%recover options
+	options=pairoptions(varargin{:});
+
+	method=getfieldvalue(options,'method','mixed');
+
+	if strcmpi(method,'mixed'),
+		%recover radius and angleresol: 
+		radius=getfieldvalue(options,'radius',6378000); %earth radius as default
+		angleresol=getfieldvalue(options,'angleresol',10); %10 degree resolution
+
+		%call mixed mesh 
+		md=planetmixedmesh(md,radius,angleresol);
+	else
+		%recover radius, shape and level of refinmenet
+		radius=getfieldvalue(options,'radius',6378000); %earth radius as default
+		refinement=getfieldvalue(options,'refinement',5); %refine 5 times
+		shape=getfieldvalue(options,'shape','ico'); 
+
+		%call triangular mesh
+		md=planettrimesh(md,shape,radius,refinement);
+	end
+end
Index: /issm/trunk-jpl/src/m/mesh/planet/planetmixedmesh.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/planetmixedmesh.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/planetmixedmesh.m	(revision 13009)
@@ -0,0 +1,99 @@
+function md=planetmixedmesh(md,radius,angleresol)
+%PLANETMIXEDMESH: build 2d shell mesh
+%
+% Usage: md=planetmixedshell(md,radius,angleresol)
+%
+
+conv=pi/180;
+
+r=radius;
+theta=(0:angleresol:360)';
+theta=theta*conv;
+phi=(0:angleresol:180)';
+phi=phi(2:end-1)*conv;
+
+nphi=length(phi);
+nthetha=length(theta);
+
+x=zeros(nphi*nthetha,1);
+y=zeros(nphi*nthetha,1);
+z=zeros(nphi*nthetha,1);
+
+for i=1:nphi,
+	phii=phi(i);
+	x((i-1)*nthetha+1:i*nthetha)=r.*cos(theta).*sin(phii);
+	y((i-1)*nthetha+1:i*nthetha)=r.*sin(theta).*sin(phii);
+	z((i-1)*nthetha+1:i*nthetha)=r.*cos(phii);
+end
+
+quads=zeros((nthetha-1)*(nphi-1),4);
+
+%build elements
+for i=1:nphi-1,
+	for j=1:nthetha-1,
+		count=(i-1)*(nthetha-1)+j;
+	
+		A=(i-1)*nthetha+j;
+		B=(i-1)*nthetha+j+1;
+		C=(i)*nthetha+j+1;
+		D=(i)*nthetha+j;
+		
+		quads(count,:)=[A B C D];
+	end
+end
+
+%now, add polar elements:
+%first north: phi = 0;
+x=[r.*cos(0).*sin(0);x];
+y=[r.*sin(0).*sin(0);y];
+z=[r.*cos(0);z];
+
+%add 1 to quads: 
+quads=quads+1;
+
+%add tria elements:
+trias=zeros(nthetha-1,4);
+
+for i=1:nthetha-1,
+	A=1;
+	B=i+1;
+	C=i+2;
+	trias(i,:)=[A B C NaN];
+end
+
+quads=[trias;quads];
+
+
+% now add south pole: 
+phii=180*conv;
+x=[x;r.*cos(phii).*sin(phii)];
+y=[y;r.*sin(phii).*sin(phii)];
+z=[z;r.*cos(phii)];
+nods=length(x);
+
+%add tria elements:
+trias=zeros(nthetha-1,4);
+
+start=nods-nthetha;
+for i=1:nthetha-1,
+	A=start+i-1;
+	B=start+i;
+	C=nods;
+	trias(i,:)=[A B C NaN];
+end
+
+quads=[quads;trias];
+
+
+md.mesh.elements=quads;
+md.mesh.x=x;
+md.mesh.y=y;
+md.mesh.z=z;
+md.mesh.r=sqrt(x.^2+y.^2+z.^2);
+md.mesh.theta=acos(z./md.mesh.r);
+md.mesh.phi=atan2(y,x);
+
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.numberofelements=size(md.mesh.elements,1);
+
+md.mesh.dimension=3;
Index: /issm/trunk-jpl/src/m/mesh/planet/planettrimesh.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/planettrimesh.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/planettrimesh.m	(revision 13009)
@@ -0,0 +1,20 @@
+function md=planettrimesh(md,shape,radius,refinement)
+%PLANETTRIMESH: build 2d shell mesh
+%
+% Usage: md=planettrimesh(md,shape,radius,refinement)
+%
+
+results = sphere_tri(shape,refinement,radius);
+md.mesh.x=results.vertices(:,1);
+md.mesh.y=results.vertices(:,2);
+md.mesh.z=results.vertices(:,3);
+md.mesh.elements=results.faces;
+
+md.mesh.r=sqrt(md.mesh.x.^2+md.mesh.y.^2+md.mesh.z.^2);
+md.mesh.theta=acos(md.mesh.z./md.mesh.r);
+md.mesh.phi=atan2(md.mesh.y,md.mesh.x);
+
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.numberofelements=size(md.mesh.elements,1);
+
+md.mesh.dimension=3;
Index: /issm/trunk-jpl/src/m/mesh/planet/sphere_project.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/sphere_project.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/sphere_project.m	(revision 13009)
@@ -0,0 +1,66 @@
+function V = sphere_project(v,r,c)
+
+% sphere_project - project point X,Y,Z to the surface of sphere radius r
+% 
+% V = sphere_project(v,r,c)
+% 
+% Cartesian inputs:
+% v is the vertex matrix, Nx3 (XYZ)
+% r is the sphere radius, 1x1 (default 1)
+% c is the sphere centroid, 1x3 (default 0,0,0)
+%
+% XYZ are converted to spherical coordinates and their radius is
+% adjusted according to r, from c toward XYZ (defined with theta,phi)
+% 
+% V is returned as Cartesian 3D coordinates
+% 
+
+% $Revision: 1.1 $ $Date: 2004/11/12 01:32:36 $
+
+% Licence:  GNU GPL, no implied or express warranties
+% History:  06/2002, Darren.Weber_at_radiology.ucsf.edu, created
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+if ~exist('v','var'),
+    msg = sprintf('SPHERE_PROJECT: No input vertices (X,Y,Z)\n');
+    error(msg);
+end
+
+X = v(:,1);
+Y = v(:,2);
+Z = v(:,3);
+
+if ~exist('c','var'),
+    xo = 0;
+    yo = 0;
+    zo = 0;
+else
+    xo = c(1);
+    yo = c(2);
+    zo = c(3);
+end
+
+if ~exist('r','var'), r = 1; end
+
+% alternate method is to use unit vector of V
+% [ n = 'magnitude(V)'; unitV = V ./ n; ]
+% to change the radius, multiply the unitV
+% by the radius required.  This avoids the
+% use of arctan functions, which have branches.
+
+
+% Convert Cartesian X,Y,Z to spherical (radians)
+theta = atan2( (Y-yo), (X-xo) );
+phi   = atan2( sqrt( (X-xo).^2 + (Y-yo).^2 ), (Z-zo) );
+% do not calc: r = sqrt( (X-xo).^2 + (Y-yo).^2 + (Z-zo).^2);
+
+%   Recalculate X,Y,Z for constant r, given theta & phi.
+R = ones(size(phi)) * r;
+x = R .* sin(phi) .* cos(theta);
+y = R .* sin(phi) .* sin(theta);
+z = R .* cos(phi);
+
+V = [x y z];
+
+return
Index: /issm/trunk-jpl/src/m/mesh/planet/sphere_tri.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/planet/sphere_tri.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/planet/sphere_tri.m	(revision 13009)
@@ -0,0 +1,204 @@
+function [FV] = sphere_tri(shape,maxlevel,r,winding)
+
+% sphere_tri - generate a triangle mesh approximating a sphere
+% 
+% Usage: FV = sphere_tri(shape,Nrecurse,r,winding)
+% 
+%   shape is a string, either of the following:
+%   'ico'   starts with icosahedron (most even, default)
+%   'oct'   starts with octahedron
+%   'tetra' starts with tetrahedron (least even)
+%
+%   Nrecurse is int >= 0, setting the recursions (default 0)
+%
+%   r is the radius of the sphere (default 1)
+%
+%   winding is 0 for clockwise, 1 for counterclockwise (default 0).  The
+%   matlab patch command gives outward surface normals for clockwise
+%   order of vertices in the faces (viewed from outside the surface).
+%
+%   FV has fields FV.vertices and FV.faces.  The vertices 
+%   are listed in clockwise order in FV.faces, as viewed 
+%   from the outside in a RHS coordinate system.
+% 
+% The function uses recursive subdivision.  The first
+% approximation is an platonic solid, either an  icosahedron,
+% octahedron or a tetrahedron.  Each level of refinement 
+% subdivides each triangle face by a factor of 4 (see also 
+% mesh_refine).  At each refinement, the vertices are 
+% projected to the sphere surface (see sphere_project).
+% 
+% A recursion level of 3 or 4 is a good sphere surface, if
+% gouraud shading is used for rendering.
+% 
+% The returned struct can be used in the patch command, eg:
+% 
+% % create and plot, vertices: [2562x3] and faces: [5120x3]
+% FV = sphere_tri('ico',4,1);
+% lighting phong; shading interp; figure;
+% patch('vertices',FV.vertices,'faces',FV.faces,...
+%       'facecolor',[1 0 0],'edgecolor',[.2 .2 .6]);
+% axis off; camlight infinite; camproj('perspective');
+% 
+% See also: mesh_refine, sphere_project
+%
+
+
+
+% $Revision: 1.2 $ $Date: 2005/07/20 23:07:03 $
+
+% Licence:  GNU GPL, no implied or express warranties
+% Jon Leech (leech @ cs.unc.edu) 3/24/89
+% icosahedral code added by Jim Buddenhagen (jb1556@daditz.sbc.com) 5/93
+% 06/2002, adapted from c to matlab by Darren.Weber_at_radiology.ucsf.edu
+% 05/2004, reorder of the faces for the 'ico' surface so they are indeed
+% clockwise!  Now the surface normals are directed outward.  Also reset the
+% default recursions to zero, so we can get out just the platonic solids.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+eegversion = '$Revision: 1.2 $';
+fprintf('SPHERE_TRI [v %s]\n',eegversion(11:15)); tic
+
+if ~exist('shape','var') || isempty(shape),
+    shape = 'ico';
+end
+fprintf('...creating sphere tesselation based on %s\n',shape);
+
+% default maximum subdivision level
+if ~exist('maxlevel','var') || isempty(maxlevel) || maxlevel < 0,
+    maxlevel = 0;
+end
+
+% default radius
+if ~exist('r','var') || isempty(r),
+    r = 1;
+end
+
+if ~exist('winding','var') || isempty(winding),
+    winding = 0;
+end
+
+
+% -----------------
+% define the starting shapes
+
+shape = lower(shape);
+
+switch shape,
+case 'tetra',
+    
+    % Vertices of a tetrahedron
+    sqrt_3 = 0.5773502692;
+    
+    tetra.v = [  sqrt_3,  sqrt_3,  sqrt_3 ;   % +X, +Y, +Z  - PPP
+                -sqrt_3, -sqrt_3,  sqrt_3 ;   % -X, -Y, +Z  - MMP
+                -sqrt_3,  sqrt_3, -sqrt_3 ;   % -X, +Y, -Z  - MPM
+                 sqrt_3, -sqrt_3, -sqrt_3 ];  % +X, -Y, -Z  - PMM
+	
+    % Structure describing a tetrahedron
+    tetra.f = [ 1, 2, 3;
+                1, 4, 2;
+                3, 2, 4;
+                4, 1, 3 ];
+    
+    FV.vertices = tetra.v;
+    FV.faces    = tetra.f;
+    
+case 'oct',
+    
+    % Six equidistant points lying on the unit sphere
+    oct.v = [  1,  0,  0 ;  %  X
+              -1,  0,  0 ; 	% -X
+               0,  1,  0 ;  %  Y
+               0, -1,  0 ; 	% -Y
+               0,  0,  1 ; 	%  Z
+               0,  0, -1 ];	% -Z
+	
+    % Join vertices to create a unit octahedron
+    oct.f = [ 1 5 3 ;    %  X  Z  Y  -  First the top half
+              3 5 2 ;    %  Y  Z -X
+              2 5 4 ;    % -X  Z -Y
+              4 5 1 ;    % -Y  Z  X
+              1 3 6 ;    %  X  Y -Z  -  Now the bottom half
+              3 2 6 ;    %  Y  Z -Z
+              2 4 6 ;    % -X  Z -Z
+              4 1 6 ];   % -Y  Z -Z
+    
+    FV.vertices = oct.v;
+    FV.faces    = oct.f;
+    
+case 'ico',
+    
+    % Twelve vertices of icosahedron on unit sphere
+    tau = 0.8506508084; % t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2)
+    one = 0.5257311121; % one=1/sqrt(1+t^2) , unit sphere
+    
+    ico.v( 1,:) = [  tau,  one,    0 ]; % ZA
+    ico.v( 2,:) = [ -tau,  one,    0 ]; % ZB
+    ico.v( 3,:) = [ -tau, -one,    0 ]; % ZC
+    ico.v( 4,:) = [  tau, -one,    0 ]; % ZD
+    ico.v( 5,:) = [  one,   0 ,  tau ]; % YA
+    ico.v( 6,:) = [  one,   0 , -tau ]; % YB
+    ico.v( 7,:) = [ -one,   0 , -tau ]; % YC
+    ico.v( 8,:) = [ -one,   0 ,  tau ]; % YD
+    ico.v( 9,:) = [   0 ,  tau,  one ]; % XA
+    ico.v(10,:) = [   0 , -tau,  one ]; % XB
+    ico.v(11,:) = [   0 , -tau, -one ]; % XC
+    ico.v(12,:) = [   0 ,  tau, -one ]; % XD
+    
+    % Structure for unit icosahedron
+    ico.f = [  5,  8,  9 ;
+               5, 10,  8 ;
+               6, 12,  7 ;
+               6,  7, 11 ;
+               1,  4,  5 ;
+               1,  6,  4 ;
+               3,  2,  8 ;
+               3,  7,  2 ;
+               9, 12,  1 ;
+               9,  2, 12 ;
+              10,  4, 11 ;
+              10, 11,  3 ;
+               9,  1,  5 ;
+              12,  6,  1 ;
+               5,  4, 10 ;
+               6, 11,  4 ;
+               8,  2,  9 ;
+               7, 12,  2 ;
+               8, 10,  3 ;
+               7,  3, 11 ];
+	
+    FV.vertices = ico.v;
+    FV.faces    = ico.f;
+end
+
+
+% -----------------
+% refine the starting shapes with subdivisions
+if maxlevel,
+    
+    % Subdivide each starting triangle (maxlevel) times
+    for level = 1:maxlevel,
+        
+        % Subdivide each triangle and normalize the new points thus
+        % generated to lie on the surface of a sphere radius r.
+        FV = mesh_refine_tri4(FV);
+        FV.vertices = sphere_project(FV.vertices,r);
+        
+        % An alternative might be to define a min distance
+        % between vertices and recurse or use fminsearch
+        
+    end
+end
+
+if winding,
+    fprintf('...returning counterclockwise vertex order (viewed from outside)\n');
+    FV.faces = FV.faces(:,[1 3 2]);
+else
+    fprintf('...returning clockwise vertex order (viewed from outside)\n');
+end
+
+t=toc; fprintf('...done (%6.2f sec)\n\n',t);
+
+return
Index: /issm/trunk-jpl/src/m/mesh/rifts/meshaddrifts.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/meshaddrifts.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/meshaddrifts.m	(revision 13009)
@@ -0,0 +1,93 @@
+function md=meshaddrifts(md,riftname);
+%MESHADDRIFTS - add rifts to a preloaded mesh (typically, an argus mesh)
+%
+%   Usage:
+%      md=meshaddrifts(md,riftname);
+%
+%        where md is a model with a preexisting mesh, and riftname is the name of an .exp file.
+%        The format of the riftname file is as follows: a list of pairs of closed and open contours. 
+%        The closed contour defines the envelop of the rift, the open contour that follows in the 
+%        file defines the rift. The density of the rift should be chosen carefully in the file, as it 
+%        will be used to define the rift contour density of the mesh. The open contour density will 
+%        be preserved. There can be as many pairs of closed contour and rift contour as wished.
+
+
+%read rift: 
+domains=expread(riftname,1);
+contours=domains(1:2:end);
+rifts=domains(2:2:end);
+
+%now loop over rifts: 
+for rift_i=1:length(rifts),
+	
+	%refine rift to desired resolution: 
+	contour=contours(rift_i);
+	rift=rifts(rift_i);
+	
+	delete('Meshaddrifts.Rift.exp');
+	expwrite(rift,'Meshaddrifts.Rift.Coarse.exp');
+	expcoarsen('Meshaddrifts.Rift.exp','Meshaddrifts.Rift.Coarse.exp',rift.density);
+	delete('Meshaddrifts.Rift.Coarse.exp');
+	
+	%extract model:
+	expwrite(contour,'Meshaddrifts.Contour.exp');
+	md2=modelextract(md,'Meshaddrifts.Contour.exp');
+	
+	%create domain of md2 model: 
+	md2.mesh.segments=contourenvelope(md2,'Meshaddrifts.Contour.exp');
+	domain_index=md2.mesh.segments(1,1:2);
+	while (domain_index(end)~=domain_index(1)),
+		pos=find(md2.mesh.segments(:,1)==domain_index(end));
+		domain_index(end+1)=md2.mesh.segments(pos,2);
+	end
+	
+	domain.x=md2.mesh.x(domain_index);
+	domain.y=md2.mesh.y(domain_index);
+	domain.name='Meshaddrifts.Domain.exp';
+	domain.density=1;
+	expwrite(domain,'Meshaddrifts.Domain.exp');
+	
+	%unloop domain index: used for later.
+	domain_index=domain_index(1:end-1);
+	
+	%remesh md2 using new domain outline, and rift profile: 
+	md2=meshnodensity(md2,'Meshaddrifts.Domain.exp','Meshaddrifts.Rift.exp');
+	md2=meshprocessrifts(md2);
+	
+	%plug md2 mesh into md mesh: 
+	[md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.z,md.mesh.numberofelements,md.mesh.numberofvertices,elconv,nodeconv,elconv2,nodeconv2]=meshplug(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.z,...
+								md2.mesh.elements,md2.mesh.x,md2.mesh.y,md2.mesh.z,md2.extractednodes,md2.extractedelements,domain_index);
+
+	%update md2 rifts using elconv and nodeconv, and plug them into md: 
+	md2.rifts=updateriftindexing(md2.rifts,elconv2,nodeconv2);
+	
+	for i=1:md.rifts.numrifts,
+		md.rifts.riftstruct(i)=updateriftindexing(md.rifts.riftstruct(i),elconv,nodeconv);
+	end
+	
+	if md.rifts.numrifts==0,
+		md.rifts.riftstruct=md2.rifts;
+		md.rifts.numrifts=1;
+	else
+		md.rifts.riftstruct(end+1,1)=md2.rifts;
+		md.rifts.numrifts=md.rifts.numrifts+1;
+	end
+	
+	md.mesh.segments(:,1:2)=nodeconv(md.mesh.segments(:,1:2));
+	md.mesh.segments(:,3)=elconv(md.mesh.segments(:,3));
+
+end
+
+%finish up "a la" mesh.h
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+
+%Now, build the connectivity tables for this mesh.
+md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+
+%type of model
+md.mesh.dimension=2;
Index: /issm/trunk-jpl/src/m/mesh/rifts/meshplug.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/meshplug.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/meshplug.m	(revision 13009)
@@ -0,0 +1,89 @@
+function [elements,x,y,z,numberofelements,numberofnodes,elconv,nodeconv,elconv2,nodeconv2]=meshplug(elements,x,y,z,elements2,x2,y2,z2,extractednodes,extractedelements,domain);
+%MESHPLUG - embed mesh into another one
+%     See also meshaddrifts
+
+
+%initialize elconv,nodeconv conversion tables from md mesh to new md mesh
+elconv=1:size(elements,1); elconv=elconv';
+nodeconv=1:size(x,1); nodeconv=nodeconv';
+
+%take away old elements in area of interest: 
+elements(extractedelements,:)=[];
+element_offset=size(elements,1);
+
+%update elconv after having extracted the area of interest elements
+temp_elconv=elconv; temp_elconv(extractedelements)=[];
+temp_elconvnum=1:length(temp_elconv);
+elconv(temp_elconv)=temp_elconvnum;
+elconv(extractedelements)=NaN;
+
+%initialize elconv2 and nodeconv2, conversion tables from md2 mesh to new md mesh
+elconv2=1:size(elements2,1);elconv2=elconv2'+element_offset;
+nodeconv2=(size(x,1)+1):(size(x,1)+size(x2,1)); nodeconv2=nodeconv2';
+
+extractednodes_minusborder=extractednodes;
+extractednodes_minusborder(domain)=[];
+
+x(extractednodes_minusborder)=NaN;
+y(extractednodes_minusborder)=NaN;
+
+%now, plug md2 mesh: 
+
+%first, offset all ids of md2 mesh
+elements2=elements2+length(x);
+
+%NaN border nodes in second mesh
+x2(1:length(domain))=NaN;
+y2(1:length(domain))=NaN;
+
+%redirect border nodes in elements2  to elements
+for i=1:length(domain),
+	pos=find(elements2==(i+length(x)));
+	elements2(pos)=extractednodes(domain(i));
+end
+
+%same deal for nodeconv2:
+for i=1:length(domain),
+	nodeconv2(i)=extractednodes(domain(i));
+end
+
+
+%plug elements
+elements=[elements;elements2];
+
+
+%now, increase number of nodes
+x=[x; x2];
+y=[y; y2];
+z=[z; z2];
+
+%now, get rid of NaN in x:
+while  ~isempty(find(isnan(x))),
+
+	pos=find(isnan(x));
+	node=pos(1);
+
+	%collapse node
+	x(node)=[];
+	y(node)=[];
+	z(node)=[];
+
+	%renumber all nodes > node in elements
+	pos=find(elements>node);
+	elements(pos)=elements(pos)-1;
+
+	%same deal for nodeconv2: 
+	pos=find(nodeconv2>node);
+	nodeconv2(pos)=nodeconv2(pos)-1;
+
+end
+
+numberofnodes=length(x);
+numberofelements=length(elements);
+
+%finish nodeconv: 
+temp_nodeconv=nodeconv;  temp_nodeconv(extractednodes_minusborder)=[];
+temp_nodeconvnum=1:length(temp_nodeconv);
+nodeconv(temp_nodeconv)=temp_nodeconvnum;
+nodeconv(extractednodes_minusborder)=NaN;
+
Index: /issm/trunk-jpl/src/m/mesh/rifts/meshprocessoutsiderifts.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/meshprocessoutsiderifts.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/meshprocessoutsiderifts.m	(revision 13009)
@@ -0,0 +1,94 @@
+function md=meshprocessoutsiderifts(md,domainoutline)
+%MESHPROCESSOUTSIDERIFTS - process rifts when they touch the domain outline
+%
+%   Usage:
+%      md=meshprocessoutsiderifts(md,domain)
+%
+
+
+
+%go through rifts, and figure out which ones touch the domain outline
+for i=1:md.rifts.numrifts,
+	
+	%first, flag nodes that belong to the domain outline
+	flags=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0);
+
+	rift=md.rifts.riftstruct(i);
+	tips=rift.tips;
+	outsidetips=tips(find(flags(rift.tips)==0));
+
+	%we have found outsidetips, tips that touch the domain outline. go through them
+	for j=1:length(outsidetips),
+		
+		tip=outsidetips(j);
+		%find tip in the segments, take first segment (there should be 2) that holds tip, 
+		%and node_connected_to_tip is the other node on this segment:
+		tipindex=find(rift.segments(:,1)==tip); 
+		if length(tipindex),
+			tipindex=tipindex(1);
+			node_connected_to_tip=rift.segments(tipindex,2);
+		else
+			tipindex=find(rift.segments(:,2)==tip); tipindex=tipindex(1);
+			node_connected_to_tip=rift.segments(tipindex,1);
+		end
+
+		%ok, we have the tip node, and the first node connected to it, on the rift. Now, 
+		%identify all the elements that are connected to the tip, and that are on the same 
+		%side of the rift.
+		A=tip;
+		B=node_connected_to_tip;
+
+		elements=[];
+
+		while  flags(B), %as long as B does not belong to the domain outline, keep looking.
+			%detect elements on edge A,B:
+			edgeelements=ElementsFromEdge(md.mesh.elements,A,B);
+			%rule out those we already detected
+			already_detected=ismember(edgeelements,elements);
+			nextelement=edgeelements(find(~already_detected));
+			%add new detected element to the list of elements we are looking for.
+			elements=[elements;nextelement];
+			%new B:
+			B=md.mesh.elements(nextelement,find(~ismember(md.mesh.elements(nextelement,:),[A B])));
+		end
+		
+		%take the list of elements on one side of the rift that connect to the tip, 
+		%and duplicate the tip on them, so as to open the rift to the outside.
+		num=length(md.mesh.x)+1;
+		md.mesh.x=[md.mesh.x;md.mesh.x(tip)];
+		md.mesh.y=[md.mesh.y;md.mesh.y(tip)];
+		md.mesh.numberofvertices=num;
+		
+		%replace tip in elements
+		newelements=md.mesh.elements(elements,:);
+		pos=find(newelements==tip);
+		newelements(pos)=num;
+		md.mesh.elements(elements,:)=newelements;
+		md.rifts.riftstruct(i).tips=[md.rifts.riftstruct(i).tips num];
+
+		%deal with segments
+		tipsegments=find((md.mesh.segments(:,1)==tip) | (md.mesh.segments(:,2)==tip));
+		for  k=1:length(tipsegments),
+			segment_index=tipsegments(k);
+			pos=find(md.mesh.segments(segment_index,1:2)~=tip);
+			other_node=md.mesh.segments(segment_index,pos);
+			if ~isconnected(md.mesh.elements,other_node,tip),
+				pos=find(md.mesh.segments(segment_index,1:2)==tip);
+				md.mesh.segments(segment_index,pos)=num;
+			end
+		end
+	end
+end
+
+
+%Fill in rest of fields:
+md.mesh.numberofelements=length(md.mesh.elements);
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonboundary=zeros(length(md.mesh.x),1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+md.rifts.numrifts=length(md.rifts.riftstruct);
+md.flowequation.element_equation=3*ones(md.mesh.numberofelements,1);
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
Index: /issm/trunk-jpl/src/m/mesh/rifts/meshprocessrifts.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/meshprocessrifts.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/meshprocessrifts.m	(revision 13009)
@@ -0,0 +1,69 @@
+function md=meshprocessrifts(md,domainoutline)
+%MESHPROCESSRIFTS - process mesh when rifts are present
+%
+%   split rifts inside mesh (rifts are defined by presence of
+%   segments inside the domain outline)
+%   if domain outline is provided, check for rifts that could touch it, and open them up.
+%
+%   Usage:
+%      md=meshprocessrifts(md,domainoutline)
+%
+%   Ex: 
+%      md=meshprocessrifts(md,'DomainOutline.exp');
+%
+
+%some checks on arguments: 
+if nargout~=1,
+	help meshprocessrifts
+	error('meshprocessrifts usage error:');
+end
+
+if nargin~=2,
+	help meshprocessrifts
+	error('meshprocessrifts usage error:');
+end
+
+%Call MEX file
+[md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers,md.rifts.riftstruct]=TriMeshProcessRifts(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers);
+if ~isstruct(md.rifts.riftstruct),
+	error('TriMeshProcessRifts did not find any rift');
+end
+
+%Fill in rest of fields:
+numrifts=length(md.rifts.riftstruct);
+md.mesh.numberofelements=length(md.mesh.elements);
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonboundary=zeros(length(md.mesh.x),1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+
+%get coordinates of rift tips
+for i=1:numrifts,
+	md.rifts.riftstruct(i).tip1coordinates=[md.mesh.x(md.rifts.riftstruct(i).tips(1)) md.mesh.y(md.rifts.riftstruct(i).tips(1))];
+	md.rifts.riftstruct(i).tip2coordinates=[md.mesh.x(md.rifts.riftstruct(i).tips(2)) md.mesh.y(md.rifts.riftstruct(i).tips(2))];
+end
+
+%In case we have rifts that open up the domain outline, we need to open them: 
+flags=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0);
+found=0;
+for i=1:numrifts,
+	if flags(md.rifts.riftstruct(i).tips(1))==0,
+		found=1;
+		break;
+	end
+	if flags(md.rifts.riftstruct(i).tips(2))==0,
+		found=1;
+		break;
+	end
+end
+if found,
+	md=meshprocessoutsiderifts(md,domainoutline);
+end
+
+%get elements that are not correctly oriented in the correct direction:
+aires=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+pos=find(aires<0);
+md.mesh.elements(pos,:)=[md.mesh.elements(pos,2) md.mesh.elements(pos,1) md.mesh.elements(pos,3)];
Index: /issm/trunk-jpl/src/m/mesh/rifts/meshyamsrecreateriftsegments.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/meshyamsrecreateriftsegments.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/meshyamsrecreateriftsegments.m	(revision 13009)
@@ -0,0 +1,90 @@
+function md=meshyamsrecreateriftsegments(md)
+
+	%recreate rift segments: just used for yams. temporaroy routine.
+	pos_record=[];
+	if md.rifts.numrifts,
+		for i=1:md.rifts.numrifts,
+			rift=md.rifts.riftstruct(i);
+
+			%closed rifts first:
+			if length(rift.tips)==2,
+
+				%find tip1 and tip2 for this rift, in the new mesh created by yams.
+				pos=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip1coordinates(1),rift.tip1coordinates(2));
+				tip1=md.mesh.segments(pos,1);
+				pos=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip2coordinates(1),rift.tip2coordinates(2));
+				tip2=md.mesh.segments(pos,1);
+
+				%start from tip1, and build segments of this rift. 
+				pos=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip1coordinates(1),rift.tip1coordinates(2));
+				pos_record=[pos_record; pos];
+				riftsegs=md.mesh.segments(pos,:);
+				while 1,
+					A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3);
+					%find other segment that holds B.
+					pos=find(md.mesh.segments(:,1)==B);
+					pos_record=[pos_record; pos];
+					riftsegs=[riftsegs; md.mesh.segments(pos,:)];
+					if riftsegs(end,2)==tip1, 
+						break;
+					end
+				end
+				md.rifts.riftstruct(i).segments=riftsegs;
+				md.rifts.riftstruct(i).tips=[tip1 tip2];
+
+			else
+				%ok, this is a rift that opens up to the domain outline.  One tip is going to be 
+				%double, the other one, single. We are going to start from the single tip, towards the two 
+				%other doubles
+
+				%find tip1 and tip2 for this rift, in the new mesh created by yams.
+				pos1=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip1coordinates(1),rift.tip1coordinates(2));
+				tip1=md.mesh.segments(pos1,1);
+				pos2=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip2coordinates(1),rift.tip2coordinates(2));
+				tip2=md.mesh.segments(pos2,1);
+				if length(tip1)==2,
+					%swap.
+					temp=tip1; tip1=tip2; tip2=temp;
+					temp=pos1; pos1=pos2; pos2=temp;
+					pos=pos1;
+				else
+					pos=pos1;
+				end
+
+				pos_record=[pos_record; pos];
+				riftsegs=md.mesh.segments(pos,:);
+				while 1,
+					A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3);
+					%find other segment that holds B.
+					pos=find(md.mesh.segments(:,1)==B);
+					pos_record=[pos_record; pos];
+					riftsegs=[riftsegs; md.mesh.segments(pos,:)];
+					if ((riftsegs(end,2)==tip2(1)) | (riftsegs(end,2)==tip2(2))), 
+						%figure out which tip we reached
+						if riftsegs(end,2)==tip2(1), index=2; else index=1; end
+						break;
+					end
+				end
+
+				%ok, now, we start from the other tip2, towards tip1
+				pos=pos2(index);
+				pos_record=[pos_record; pos];
+				riftsegs=[riftsegs; md.mesh.segments(pos,:)];
+				while 1,
+					A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3);
+					%find other segment that holds B.
+					pos=find(md.mesh.segments(:,1)==B);
+					pos_record=[pos_record; pos];
+					riftsegs=[riftsegs; md.mesh.segments(pos,:)];
+					if riftsegs(end,2)==tip1, 
+						break;
+					end
+				end
+				md.rifts.riftstruct(i).segments=riftsegs;
+				md.rifts.riftstruct(i).tips=[tip1 tip2(1) tip2(2)];
+
+			end
+		end
+	end
+	%take out rift segments from segments
+	md.mesh.segments(pos_record,:)=[];
Index: /issm/trunk-jpl/src/m/mesh/rifts/rifttipsrefine.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/rifttipsrefine.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/rifttipsrefine.m	(revision 13009)
@@ -0,0 +1,26 @@
+function md=rifttipsrefine(md,filename,resolution,circleradius);
+%RIFTTIPSREFINE - refine mesh near rift tips
+%
+%   Usage:
+%      md=rifttipsrefine(md,filename,resolution,circleradius);
+
+numberofnodes=50;
+
+%take rifts, and create refinement circles around tips
+rifts=expread(filename,1);
+
+!echo -n "" > Circles.exp
+for i=1:length(rifts),
+	tip1=[rifts(i).x(1) rifts(i).y(1)];
+	tip2=[rifts(i).x(end) rifts(i).y(end)];
+	%create circle around tip
+	expcreatecircle('Circle1.exp',tip1(1),tip1(2),circleradius,numberofnodes);
+	expcreatecircle('Circle2.exp',tip2(1),tip2(2),circleradius,numberofnodes);
+	!cat Circles.exp Circle1.exp Circle2.exp > Circles2.exp
+	!mv Circles2.exp Circles.exp
+	!rm -rf Circle1.exp Circle2.exp
+end
+
+md=meshexprefine(md,'Circles.exp',resolution);
+
+system('rm -rf Circles.exp');
Index: /issm/trunk-jpl/src/m/mesh/rifts/updateriftindexing.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/rifts/updateriftindexing.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/rifts/updateriftindexing.m	(revision 13009)
@@ -0,0 +1,11 @@
+function rift=updateriftindexing(rift,elconv,nodeconv)
+%UPDATERIFTINDEXING - update rift indexing, using mesh to new mesh conversion tables
+%     See also meshaddrift
+
+rift.segments(:,1:2)=nodeconv(rift.segments(:,1:2));
+rift.segments(:,3)=elconv(rift.segments(:,3));
+rift.pairs=elconv(rift.pairs);
+rift.tips=nodeconv(rift.tips);
+
+rift.penaltypairs(:,1:2)=nodeconv(rift.penaltypairs(:,1:2));
+rift.penaltypairs(:,3:4)=elconv(rift.penaltypairs(:,3:4));
Index: /issm/trunk-jpl/src/m/mesh/triangle.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/triangle.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/triangle.m	(revision 13009)
@@ -0,0 +1,82 @@
+function md=triangle(md,domainname,varargin)
+%TRIANGLE - create model mesh using the triangle package
+%
+%   This routine creates a model mesh using TriMesh and a domain outline, to within a certain resolution
+%   where md is a @model object, domainname is the name of an Argus domain outline file, 
+%   and resolution is a characteristic length for the mesh (same unit as the domain outline
+%   unit). Riftname is an optional argument (Argus domain outline) describing rifts.
+%
+%   Usage:
+%      md=triangle(md,domainname,resolution)
+%   or md=triangle(md,domainname,riftname, resolution)
+%
+%   Examples:
+%      md=triangle(md,'DomainOutline.exp',1000);
+%      md=triangle(md,'DomainOutline.exp','Rifts.exp',1500);
+
+%Figure out a characteristic area. Resolution is a node oriented concept (ex a 1000m  resolution node would 
+%be made of 1000*1000 area squares). 
+if (nargin==3),
+	resolution=varargin{1};
+	riftname='';
+end
+if (nargin==4),
+	riftname=varargin{1};
+	resolution=varargin{2};
+end
+
+%Check that mesh was not already run, and warn user: 
+if md.mesh.numberofelements~=0,
+	choice=input('This model already has a mesh. Are you sure you want to go ahead? (y/n)','s');
+	if ~strcmp(choice,'y')
+		disp('no meshing done ... exiting');
+		return
+	end
+end
+
+area=resolution^2;
+
+%Mesh using TriMesh
+[elements,x,y,segments,segmentmarkers]=TriMesh(domainname,riftname,area);
+
+%check that all the created nodes belong to at least one element
+orphan=find(~ismember([1:length(x)],sort(unique(elements(:)))));
+for i=1:length(orphan),
+	disp('WARNING: removing orphans');
+	%get rid of the orphan node i
+	%update x and y
+	x=[x(1:orphan(i)-(i-1)-1); x(orphan(i)-(i-1)+1:end)];
+	y=[y(1:orphan(i)-(i-1)-1); y(orphan(i)-(i-1)+1:end)];
+	%update elements
+	pos=find(elements>orphan(i)-(i-1));
+	elements(pos)=elements(pos)-1;
+	%update segments
+	pos1=find(segments(:,1)>orphan(i)-(i-1));
+	pos2=find(segments(:,2)>orphan(i)-(i-1));
+	segments(pos1,1)=segments(pos1,1)-1;
+	segments(pos2,2)=segments(pos2,2)-1;
+end
+
+%plug into md
+md.mesh.x=x;
+md.mesh.y=y;
+md.mesh.elements=elements;
+md.mesh.segments=segments;
+md.mesh.segmentmarkers=segmentmarkers;
+
+%Fill in rest of fields:
+md.mesh.numberofelements=length(md.mesh.elements);
+md.mesh.numberofvertices=length(md.mesh.x);
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+
+%Now, build the connectivity tables for this mesh.
+md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+
+%type of model
+md.mesh.dimension=2;
Index: /issm/trunk-jpl/src/m/mesh/triangle.py
===================================================================
--- /issm/trunk-jpl/src/m/mesh/triangle.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/triangle.py	(revision 13009)
@@ -0,0 +1,56 @@
+from numpy import *
+import TriMesh as tm
+import NodeConnectivity as nc
+import ElementConnectivity as ec
+
+def triangle(md, domainname, resolution,riftname=''):
+	#TRIANGLE - create model mesh using the triangle package
+	#
+	#   This routine creates a model mesh using TriMesh and a domain outline, to within a certain resolution
+	#   where md is a @model object, domainname is the name of an Argus domain outline file, 
+	#   and resolution is a characteristic length for the mesh (same unit as the domain outline
+	#   unit). Riftname is an optional argument (Argus domain outline) describing rifts.
+	#
+	#   Usage:
+	#      md=triangle(md,domainname,resolution)
+	#   or md=triangle(md,domainname, resolution, riftname)
+	#
+	#   Examples:
+	#      md=triangle(md,'DomainOutline.exp',1000);
+	#      md=triangle(md,'DomainOutline.exp',1000,'Rifts.exp');
+
+
+	#Figure out a characteristic area. Resolution is a node oriented concept (ex a 1000m  resolution node would 
+	#be made of 1000*1000 area squares). 
+
+	#Check that mesh was not already run, and warn user: 
+	if md.mesh.numberofelements != 0.:
+		choice = input('This model already has a mesh. Are you sure you want to go ahead? (y/n)')
+		if choice != 'y':
+			print 'no meshing done ... exiting'
+			return []
+		
+	area = resolution**2.
+
+	#Mesh using TriMesh
+	[md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers]=tm.TriMesh(domainname,riftname,area)
+
+
+	#Fill in rest of fields:
+	md.mesh.numberofelements = len(md.mesh.elements)
+	md.mesh.numberofvertices = len(md.mesh.x)
+	md.mesh.z = zeros(md.mesh.numberofvertices)
+	md.mesh.vertexonboundary = zeros(md.mesh.numberofvertices)
+	md.mesh.vertexonboundary[md.mesh.segments[:,0:2].astype(int)-1] = 1.
+	md.mesh.vertexonbed = ones(md.mesh.numberofvertices)
+	md.mesh.vertexonsurface = ones(md.mesh.numberofvertices)
+	md.mesh.elementonbed = ones(md.mesh.numberofelements)
+	md.mesh.elementonsurface = ones(md.mesh.numberofelements)
+
+	#Now, build the connectivity tables for this mesh.
+	[md.mesh.vertexconnectivity]= nc.NodeConnectivity(md.mesh.elements, md.mesh.numberofvertices)
+	[md.mesh.elementconnectivity] = ec.ElementConnectivity(md.mesh.elements, md.mesh.vertexconnectivity)
+	
+	#type of model
+	md.mesh.dimension = 2.
+	return md
Index: /issm/trunk-jpl/src/m/mesh/yams.m
===================================================================
--- /issm/trunk-jpl/src/m/mesh/yams.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/mesh/yams.m	(revision 13009)
@@ -0,0 +1,171 @@
+function md=yams(md,varargin);
+%MESHYAMS - Build model of Antarctica by refining according to observed velocity error estimator
+%
+%   Usage:
+%      md=yams(md,varargin);
+%      where varargin is a lit of paired arguments. 
+%      arguments can be: 'domainoutline': Argus file containing the outline of the domain to be meshed
+%      arguments can be: 'velocities': matlab file containing the velocities [m/yr]
+%      optional arguments: 'groundeddomain': Argus file containing the outline of the grounded ice
+%                          this option is used to minimize the metric on water (no refinement)
+%      optional arguments: 'resolution': initial mesh resolution [m]
+%      optional arguments: 'nsteps': number of steps of mesh adaptation
+%      optional arguments: 'epsilon': average interpolation error wished [m/yr]
+%      optional arguments: 'hmin': minimum edge length
+%      optional arguments: 'hmanx': maximum edge
+%      optional arguments: 'riftoutline': if rifts are present, specifies rift outline file.
+%      
+%
+%   Examples:
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat');
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat','groundeddomain','ground.exp');
+%      md=yams(md,'domainoutline','Domain.exp','velocities','vel.mat','groundeddomain','ground.exp','nsteps',6,'epsilon',2,'hmin',500,'hmax',30000);
+
+%recover options
+options=pairoptions(varargin{:});
+options=deleteduplicates(options,1);
+
+%recover some fields
+disp('MeshYams Options:')
+domainoutline=getfieldvalue(options,'domainoutline');
+disp(sprintf('   %-15s: ''%s''','DomainOutline',domainoutline));
+riftoutline=getfieldvalue(options,'riftoutline','N/A');
+disp(sprintf('   %-15s: ''%s''','riftoutline',riftoutline));
+groundeddomain=getfieldvalue(options,'groundeddomain','N/A');
+disp(sprintf('   %-15s: ''%s''','GroundedDomain',groundeddomain));
+velocities=getfieldvalue(options,'velocities');
+disp(sprintf('   %-15s: ''%s''','Velocities',velocities));
+resolution=getfieldvalue(options,'resolution',5000);
+disp(sprintf('   %-15s: %f','Resolution',resolution));
+nsteps=getfieldvalue(options,'nsteps',6);
+disp(sprintf('   %-15s: %i','nsteps',nsteps));
+gradation=getfieldvalue(options,'gradation',2*ones(nsteps,1));
+disp(sprintf('   %-15s: %g','gradation',gradation(1)));
+epsilon=getfieldvalue(options,'epsilon',3);
+disp(sprintf('   %-15s: %f','epsilon',epsilon));
+hmin=getfieldvalue(options,'hmin',500);
+disp(sprintf('   %-15s: %f','hmin',hmin));
+hmax=getfieldvalue(options,'hmax',150*10^3);
+disp(sprintf('   %-15s: %f\n','hmax',hmax));
+
+%mesh with initial resolution
+disp('Initial mesh generation...');
+if strcmpi(riftoutline,'N/A');
+	md=setmesh(md,domainoutline,resolution);
+else
+	md=setmesh(md,domainoutline,riftoutline,resolution);
+	md=meshprocessrifts(md,domainoutline);
+end
+disp(['Initial mesh, number of elements: ' num2str(md.mesh.numberofelements)]);
+
+%load velocities 
+disp('loading velocities...');
+Names=VelFindVarNames(velocities);
+Vel=load(velocities);
+
+%start mesh adaptation
+for i=1:nsteps,
+	disp(['Iteration #' num2str(i) '/' num2str(nsteps)]);
+
+	%interpolate velocities onto mesh
+	disp('   interpolating velocities...');
+	if strcmpi(Names.interp,'node'),
+		vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+		vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+	else
+		vx_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+		vy_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+	end
+	field=sqrt(vx_obs.^2+vy_obs.^2);
+
+	%set mask.vertexonwater  field
+	if ~strcmp(groundeddomain,'N/A'),
+		nodeground=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,groundeddomain,'node',2);
+		md.mask.vertexonwater=ones(md.mesh.numberofvertices,1);
+		md.mask.vertexonwater(find(nodeground))=0;
+	else
+		md.mask.vertexonwater=zeros(md.mesh.numberofvertices,1);
+	end
+
+	%adapt according to velocities
+	disp('   adapting...');
+	md=YamsCall(md,field,hmin,hmax,gradation(i),epsilon);
+
+	%if we have rifts, we just messed them up, we need to recreate the segments that constitute those 
+	%rifts, because the segments are used in YamsCall to freeze the rifts elements during refinement.
+	if md.rifts.numrifts, 
+		md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+		md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+		md.mesh.segments=findsegments(md);
+		md=yamsrecreateriftsegments(md);
+	end
+
+end
+	
+disp(['Final mesh, number of elements: ' num2str(md.mesh.numberofelements)]);
+
+%Now, build the connectivity tables for this mesh.
+md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+
+%recreate segments
+md.mesh.segments=findsegments(md);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1;
+
+%Fill in rest of fields:
+md.mesh.z=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonbed=ones(md.mesh.numberofvertices,1);
+md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1);
+md.mesh.elementonbed=ones(md.mesh.numberofelements,1);
+md.mesh.elementonsurface=ones(md.mesh.numberofelements,1);
+if ~strcmp(groundeddomain,'N/A'),
+	nodeground=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,groundeddomain,'node',2);
+	md.mask.vertexonwater=ones(md.mesh.numberofvertices,1);
+	md.mask.vertexonwater(find(nodeground))=0;
+else
+	md.mask.vertexonwater=zeros(md.mesh.numberofvertices,1);
+end
+if strcmpi(Names.interp,'node'),
+	md.inversion.vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+	md.inversion.vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+else
+	md.inversion.vx_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0);
+	md.inversion.vy_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0);
+end
+md.inversion.vel_obs=sqrt(md.inversion.vx_obs.^2+md.inversion.vy_obs.^2);
+
+%deal with rifts 
+if md.rifts.numrifts,
+	%first, recreate rift segments
+	md=meshyamsrecreateriftsegments(md);
+
+	%using the segments, recreate the penaltypairs
+	for j=1:md.rifts.numrifts,
+		rift=md.rifts.riftstruct(j);
+
+		%build normals and lengths of segments:
+		lengths=sqrt((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))).^2 + (md.mesh.y(rift.segments(:,1))-md.mesh.y(rift.segments(:,2))).^2 );
+		normalsx=cos(atan2((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))) , (md.mesh.y(rift.segments(:,2))-md.mesh.y(rift.segments(:,1)))));
+		normalsy=sin(atan2((md.mesh.x(rift.segments(:,1))-md.mesh.x(rift.segments(:,2))) , (md.mesh.y(rift.segments(:,2))-md.mesh.y(rift.segments(:,1)))));
+
+		%ok, build penaltypairs: 
+		numpenaltypairs=length(rift.segments)/2-1;
+		rift.penaltypairs=zeros(numpenaltypairs,7);
+
+		for i=1:numpenaltypairs,
+			rift.penaltypairs(i,1)=rift.segments(i,2);
+			rift.penaltypairs(i,2)=rift.segments(end-i,2);
+			rift.penaltypairs(i,3)=rift.segments(i,3);
+			rift.penaltypairs(i,4)=rift.segments(end-i,3);
+			rift.penaltypairs(i,5)=normalsx(i)+normalsx(i+1);
+			rift.penaltypairs(i,6)=normalsy(i)+normalsy(i+1);
+			rift.penaltypairs(i,7)=(lengths(i)+lengths(i+1))/2;
+		end
+		%renormalize norms: 
+		norms=sqrt(rift.penaltypairs(:,5).^2+rift.penaltypairs(:,6).^2);
+		rift.penaltypairs(:,5)=rift.penaltypairs(:,5)./norms;
+		rift.penaltypairs(:,6)=rift.penaltypairs(:,6)./norms;
+
+		md.rifts.riftstruct(j)=rift;
+	end
+end
Index: /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScript.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScript.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScript.m	(revision 13009)
@@ -0,0 +1,23 @@
+function BuildMultipleQueueingScript(cluster,name,executionpath,codepath)
+%BUILDMULTIPLEQUEUEINGSCRIPT - 
+%
+%   Usage:
+%      BuildMultipleQueueingScript(executionpath,codepath)
+
+disp('building queueing script');
+
+%First try and figure out if there is a special script for this particular cluster
+function_name=['BuildMultipleQueueingScript' cluster];
+
+%some specific treatment of identical cluster, gemini, castor and pollux
+if strcmpi(cluster,'castor') || strcmpi(cluster,'pollux'),
+	function_name='BuildMultipleQueueingScriptgemini';
+end
+
+if exist(function_name,'file'),
+	%Call this function:
+	eval([function_name '(name,executionpath,codepath);']);
+else
+	%Call the generic BuildQueueingScript:
+	BuildMultipleQueueingScriptGeneric(name,executionpath,codepath);
+end
Index: /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptGeneric.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptGeneric.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptGeneric.m	(revision 13009)
@@ -0,0 +1,9 @@
+function BuildMultipleQueueingScriptGeneric(name,executionpath,codepath)
+%BUILDMULTIPLEQUEUEINGSCRIPTGENERIC - ...
+%
+%   Usage:
+%      BuildMultipleQueueingScriptGeneric(executionpath,codepath)
+
+%not done yet
+error('BuildMultipleQueueingScriptGenericerror message: not supported yet!');
+
Index: /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptgemini.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptgemini.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/BuildMultipleQueueingScriptgemini.m	(revision 13009)
@@ -0,0 +1,23 @@
+function BuildQueueingScriptgemini(name,executionpath,codepath)
+%BUILDQUEUEINGSCRIPTGEMINI - ...
+%
+%   Usage:
+%      BuildQueueingScriptgemini(md,executionpath,codepath)
+
+scriptname=[name '.queue'];
+
+fid=fopen(scriptname,'w');
+if fid==-1,
+	error(['BuildQueueingScriptgeminierror message: could not open ' scriptname ' file for ascii writing']);
+end
+
+fprintf(fid,'#!/bin/sh\n');
+fprintf(fid,'cd %s\n',executionpath);
+fprintf(fid,'mkdir %s\n',name);
+fprintf(fid,'cd %s\n',name);
+fprintf(fid,'mv ../ModelList.tar.gz ./\n');
+fprintf(fid,'tar -zxvf ModelList.tar.gz\n');
+fprintf(fid,'foreach i (%s-*vs*.queue)\n',name);
+fprintf(fid,'qsub $i\n');
+fprintf(fid,'end\n');
+fclose(fid);
Index: /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJob.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJob.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJob.m	(revision 13009)
@@ -0,0 +1,21 @@
+function LaunchMultipleQueueJob(cluster,name,executionpath)
+%LAUNCHMULTIPLEQUEUEJOB - ...
+%
+%   Usage:
+%      LaunchMultipleQueueJob(executionpath)
+
+%First try and figure out if there is a special script for thie particular cluster
+function_name=['LaunchMultipleQueueJob' cluster];
+
+%some specific treatment of identical cluster, gemini, castor and pollux
+if strcmpi(cluster,'castor') || strcmpi(cluster,'pollux'),
+	function_name='LaunchMultipleQueueJobgemini';
+end
+
+if exist(function_name,'file'),
+	%Call this function:
+	eval([function_name '(cluster,name,executionpath);']);
+else
+	%Call the generic LaunchMultipleQueueJob:
+	LaunchMultipleQueueJobGeneric(cluster,name,executionpath);
+end
Index: /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobGeneric.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobGeneric.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobGeneric.m	(revision 13009)
@@ -0,0 +1,7 @@
+function LaunchMultipleQueueJobGeneric(cluster,name,executionpath)
+%LAUNCHMULTIPLEQUEUEJOBGENERIC - Generic routine to launch multiple queueing job
+%
+%   Usage:
+%      LaunchMultipleQueueJobGeneric(cluster,name,executionpath)
+
+error('LaunchMultipleQueueJobGeneric error message: not supported yet!');
Index: /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobgemini.m
===================================================================
--- /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobgemini.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/multiplequeue/LaunchMultipleQueueJobgemini.m	(revision 13009)
@@ -0,0 +1,22 @@
+function md=LaunchMultipleQueueJobgemini(cluster,name,executionpath)
+%LAUNCHMULTIPLEQUEUEJOBGEMINI - Launch multiple queueing script on Gemini cluster
+%
+%   Usage:
+%      LaunchMultipleQueueJobgemini(cluster,name,executionpath)
+
+
+%first, check we have the binary file and the queueing script
+if ~exist([ name '.queue'],'file'),
+	error('LaunchMultipleQueueJobgemini error message: queueing script issing, cannot go forward');
+end
+
+if ~exist('ModelList.tar.gz','file'),
+	error('LaunchMultipleQueueJobgemini error message: inputs models file missing, cannot go forward');
+end
+
+%upload both files to cluster
+disp('uploading input file,  queueing script and variables script');
+eval(['!scp ModelList.tar.gz ' name '.queue '  cluster ':' executionpath]);
+
+disp('launching solution sequence on remote cluster');
+issmssh(cluster,login,['"cd ' executionpath ' && source ' name '.queue "']);
Index: /issm/trunk-jpl/src/m/parameterization/contourenvelope.m
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/contourenvelope.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/contourenvelope.m	(revision 13009)
@@ -0,0 +1,139 @@
+function segments=contourenvelope(md,varargin)
+%CONTOURENVELOPE - build a set of segments enveloping a contour .exp
+%
+%   Usage:
+%      segments=contourenvelope(md,varargin)
+%
+%   Example:
+%      segments=contourenvelope(md,'Stream.exp');
+%      segments=contourenvelope(md,md.mask.elementonfloatingice)
+%      segments=contourenvelope(md);
+
+%some checks
+if nargin>2,
+	help contourenvelope
+	error('contourenvelope error message: bad usage');
+end
+if nargin==2,
+	flags=varargin{1};
+
+	if ischar(flags),
+		file=flags;
+		file=varargin{1};
+		if ~exist(file),
+			error(['contourenvelope error message: file ' file ' not found']);
+		end
+		isfile=1;
+	elseif isnumeric(flags),
+		%do nothing for now
+		isfile=0;
+	else
+		error('contourenvelope error message:  second argument should a file or an elements flag');
+	end
+end
+
+%Now, build the connectivity tables for this mesh.
+%Computing connectivity
+if (size(md.mesh.vertexconnectivity,1)~=md.mesh.numberofvertices & size(md.mesh.vertexconnectivity,1)~=md.mesh.numberofvertices2d),
+	md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+end
+if (size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements & size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements2d),
+	md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+end
+
+%get nodes inside profile
+mesh.elementconnectivity=md.mesh.elementconnectivity;
+if md.mesh.dimension==2;
+	mesh.elements=md.mesh.elements;
+	mesh.x=md.mesh.x;
+	mesh.y=md.mesh.y;
+	mesh.numberofvertices=md.mesh.numberofvertices;
+	mesh.numberofelements=md.mesh.numberofelements;
+else
+	mesh.elements=md.mesh.elements2d;
+	mesh.x=md.mesh.x2d;
+	mesh.y=md.mesh.y2d;
+	mesh.numberofvertices=md.mesh.numberofvertices2d;
+	mesh.numberofelements=md.mesh.numberofelements2d;
+end
+
+if nargin==2,
+
+	if isfile,
+		%get flag list of elements and nodes inside the contour
+		nodein=ContourToMesh(mesh.elements,mesh.x,mesh.y,file,'node',1);
+		elemin=(sum(nodein(mesh.elements),2)==size(mesh.elements,2));
+		%modify element connectivity
+		elemout=find(~elemin);
+		mesh.elementconnectivity(elemout,:)=0;
+		mesh.elementconnectivity(find(ismember(mesh.elementconnectivity,elemout)))=0;
+	else
+		%get flag list of elements and nodes inside the contour
+		nodein=zeros(mesh.numberofvertices,1); 
+		elemin=zeros(mesh.numberofelements,1); 
+		
+		pos=find(flags); 
+		elemin(pos)=1;
+		nodein(mesh.elements(pos,:))=1;
+
+		%modify element connectivity
+		elemout=find(~elemin);
+		mesh.elementconnectivity(elemout,:)=0;
+		mesh.elementconnectivity(find(ismember(mesh.elementconnectivity,elemout)))=0;
+	end
+end
+
+%Find element on boundary
+%First: find elements on the boundary of the domain
+flag=mesh.elementconnectivity;
+if nargin==2,
+	flag(find(flag))=elemin(flag(find(flag)));
+end
+elementonboundary=double(prod(flag,2)==0 & sum(flag,2)>0);
+
+%Find segments on boundary
+pos=find(elementonboundary);
+num_segments=length(pos);
+segments=zeros(num_segments,3);
+count=1;
+
+for i=1:num_segments,
+	el1=pos(i);
+	els2=mesh.elementconnectivity(el1,find(mesh.elementconnectivity(el1,:)));
+	if length(els2)>1,
+		flag=intersect(mesh.elements(els2(1),:),mesh.elements(els2(2),:));
+		nods1=mesh.elements(el1,:);
+		nods1(find(nods1==flag))=[];
+		segments(count,:)=[nods1 el1];
+
+		ord1=find(nods1(1)==mesh.elements(el1,:));
+		ord2=find(nods1(2)==mesh.elements(el1,:));
+
+		%swap segment nodes if necessary
+		if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ),
+			temp=segments(count,1);
+			segments(count,1)=segments(count,2);
+			segments(count,2)=temp;
+		end
+		segments(count,1:2)=fliplr(segments(count,1:2));
+		count=count+1;
+	else
+		nods1=mesh.elements(el1,:);
+		flag=setdiff(nods1,mesh.elements(els2,:));
+		for j=1:3,
+			nods=nods1; nods(j)=[];
+			if any(ismember(flag,nods)),
+				segments(count,:)=[nods el1];
+				ord1=find(nods(1)==mesh.elements(el1,:));
+				ord2=find(nods(2)==mesh.elements(el1,:));
+				if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ),
+					temp=segments(count,1);
+					segments(count,1)=segments(count,2);
+					segments(count,2)=temp;
+				end
+				segments(count,1:2)=fliplr(segments(count,1:2));
+				count=count+1;
+			end
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/parameterization/parameterize.m
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/parameterize.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/parameterize.m	(revision 13009)
@@ -0,0 +1,57 @@
+function md=parameterize(md,parametername)
+%PARAMETERIZE - parameterize a model
+%
+%   from a parameter matlab file, start filling in all the @model fields that were not 
+%   filled in by the mesh.m and mask.m @model methods.
+%   Warning: the parameter file must be able to be run in Matlab
+%
+%   Usage:
+%      md=parameterize(md,parametername)
+%
+%   Example:
+%      md=parameterize(md,'Square.par');
+
+%some checks
+if ~exist(parametername),
+	error(['parameterize error message: file ' parametername ' not found!']);
+end
+
+%Try and run parameter file.
+temporaryname=['TemporaryParameterFile' num2str(feature('GetPid')) ];
+copyfile(parametername,[temporaryname '.m']);
+
+%WARNING: this is a bug of matlab: the TemporaryParameterFile must be cleared
+%otherwise matlab keeps the previous version of this file which is not what
+%we want!!!
+eval(['clear ' temporaryname]);
+
+try,
+	eval(temporaryname);
+	delete([temporaryname '.m']);
+catch me,
+	delete([temporaryname '.m']);
+
+	%copy error message
+	me2=struct('message',me.message,'stack',me.stack);
+
+	%rename parameter file
+	me2.message=regexprep(me2.message,[temporaryname '.m'],parametername);
+	for i=1:length(me2.stack)-1,
+		me2.stack(i).file=regexprep(me2.stack(i).file,[temporaryname '.m'],parametername);
+		me2.stack(i).name=regexprep(me2.stack(i).name,[temporaryname],parametername);
+		if strcmp(me2.stack(i).name,'parameterize'),
+			%remove error (eval(temporaryname);) misleading
+			me2.stack(i)=[];
+		end
+	end
+
+	%throw error message
+	rethrow(me2);
+end
+
+%Name and notes
+if isempty(md.miscellaneous.name), 
+	[path,root,ext]=fileparts(parametername);
+	md.miscellaneous.name=root; 
+end
+md=addnote(md,['Model created by using parameter file: ' parametername ' on: ' datestr(now)]);
Index: /issm/trunk-jpl/src/m/parameterization/parameterize.py
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/parameterize.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/parameterize.py	(revision 13009)
@@ -0,0 +1,34 @@
+import os
+import datetime
+from addnote import *
+
+def parameterize(md,parametername):
+	"""
+	PARAMETERIZE - parameterize a model
+
+	   from a parameter python file, start filling in all the model fields that were not 
+	   filled in by the mesh.py and mask.py model methods.
+	   Warning: the parameter file must be able to be run in Python
+
+	   Usage:
+	      md=parameterize(md,parametername)
+
+	   Example:
+	      md=parameterize(md,'Square.par');
+	"""
+
+	#some checks
+	if not os.path.exists(parametername):
+		raise IOError("parameterize error message: file '%s' not found!" % parametername)
+
+	#Try and run parameter file.
+	execfile(parametername)
+
+	#Name and notes
+	if not md.miscellaneous.name:
+		md.miscellaneous.name=os.path.basename(parametername).split('.')[0]
+
+	md=addnote(md,"Model created by using parameter file: '%s' on: %s." % (parametername,datetime.datetime.strftime(datetime.datetime.now(),'%c') ))
+
+	return md
+
Index: /issm/trunk-jpl/src/m/parameterization/setflowequation.m
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setflowequation.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/setflowequation.m	(revision 13009)
@@ -0,0 +1,281 @@
+function md=setflowequation(md,varargin)
+%SETELEMENTSTYPE - associate a solution type to each element
+%
+%   This routine works like plotmodel: it works with an even number of inputs
+%   'hutter','macayeal','pattyn','stokes' and 'fill' are the possible options
+%   that must be followed by the corresponding exp file or flags list
+%   It can either be a domain file (argus type, .exp extension), or an array of element flags. 
+%   If user wants every element outside the domain to be 
+%   setflowequationd, add '~' to the name of the domain file (ex: '~Pattyn.exp');
+%   an empty string '' will be considered as an empty domain
+%   a string 'all' will be considered as the entire domain
+%   You can specify the type of coupling, 'penalties' or 'tiling', to use with the input 'coupling'
+%
+%   Usage:
+%      md=setflowequation(md,varargin)
+%
+%   Example:
+%      md=setflowequation(md,'pattyn','Pattyn.exp','macayeal',md.mask.elementonfloatingice,'fill','hutter');
+%      md=setflowequation(md,'pattyn','Pattyn.exp',fill','hutter','coupling','tiling');
+
+%some checks on list of arguments
+if ((nargin<2) | (nargout~=1)),
+	error('setflowequation error message');
+end
+
+%Find_out what kind of coupling to use
+options=pairoptions(varargin{:});
+coupling_method=getfieldvalue(options,'coupling','tiling');
+if (~strcmpi(coupling_method,'tiling') & ~strcmpi(coupling_method,'penalties')),
+	error('coupling type can only be: tiling or penalties');
+end
+
+[hutterflag macayealflag pattynflag stokesflag filltype]=recover_areas(md,varargin{:});
+
+%Flag the elements that have not been flagged as filltype
+if strcmpi(filltype,'hutter'),
+	hutterflag(find(~(macayealflag | pattynflag)))=1;
+elseif strcmpi(filltype,'macayeal'),
+	macayealflag(find(~(hutterflag | pattynflag | stokesflag)))=1;
+elseif strcmpi(filltype,'pattyn'),
+	pattynflag(find(~(hutterflag | macayealflag | stokesflag)))=1;
+end
+
+%check that each element has at least one flag
+if any(hutterflag+ macayealflag+pattynflag+stokesflag==0),
+	error('setflowequation error message: elements type not assigned, must be specified')
+end
+
+%check that each element has only one flag
+if any(hutterflag+ macayealflag+pattynflag+stokesflag>1),
+	disp('setflowequation warning message: some elements have several types, higher order type is used for them')
+	hutterflag(find(hutterflag & macayealflag))=0;
+	hutterflag(find(hutterflag & pattynflag))=0;
+	macayealflag(find(macayealflag & pattynflag))=0;
+end
+
+%Check that no pattyn or stokes for 2d mesh
+if (md.mesh.dimension==2),
+	if any(stokesflag | pattynflag)
+		error('setflowequation error message: stokes and pattyn elements not allowed in 2d mesh, extrude it first')
+	end
+end
+
+%Stokes can only be used alone for now:
+if any(stokesflag) &any(hutterflag),
+	error('setflowequation error message: stokes cannot be used with any other model for now, put stokes everywhere')
+end
+
+%Initialize node fields
+nodeonhutter=zeros(md.mesh.numberofvertices,1);
+nodeonhutter(md.mesh.elements(find(hutterflag),:))=1;
+nodeonmacayeal=zeros(md.mesh.numberofvertices,1);
+nodeonmacayeal(md.mesh.elements(find(macayealflag),:))=1;
+nodeonpattyn=zeros(md.mesh.numberofvertices,1);
+nodeonpattyn(md.mesh.elements(find(pattynflag),:))=1;
+nodeonstokes=zeros(md.mesh.numberofvertices,1);
+noneflag=zeros(md.mesh.numberofelements,1);
+
+%First modify stokesflag to get rid of elements contrained everywhere (spc + border with pattyn or macayeal)
+if any(stokesflag),
+	fullspcnodes=double((~isnan(md.diagnostic.spcvx)+~isnan(md.diagnostic.spcvy)+~isnan(md.diagnostic.spcvz))==3 | (nodeonpattyn & nodeonstokes));         %find all the nodes on the boundary of the domain without icefront
+	fullspcelems=double(sum(fullspcnodes(md.mesh.elements),2)==6);         %find all the nodes on the boundary of the domain without icefront
+	stokesflag(find(fullspcelems))=0;
+	nodeonstokes(md.mesh.elements(find(stokesflag),:))=1;
+end
+
+%Then complete with NoneApproximation or the other model used if there is no stokes
+if any(stokesflag), 
+	if any(pattynflag), %fill with pattyn
+		pattynflag(~stokesflag)=1;
+		nodeonpattyn(md.mesh.elements(find(pattynflag),:))=1;
+	elseif any(macayealflag), %fill with macayeal
+		macayealflag(~stokesflag)=1;
+		nodeonmacayeal(md.mesh.elements(find(macayealflag),:))=1;
+	else %fill with none 
+		noneflag(find(~stokesflag))=1;
+	end
+end
+
+%Now take care of the coupling between MacAyeal and Pattyn
+md.diagnostic.vertex_pairing=[];
+nodeonmacayealpattyn=zeros(md.mesh.numberofvertices,1);
+nodeonpattynstokes=zeros(md.mesh.numberofvertices,1);
+nodeonmacayealstokes=zeros(md.mesh.numberofvertices,1);
+macayealpattynflag=zeros(md.mesh.numberofelements,1);
+macayealstokesflag=zeros(md.mesh.numberofelements,1);
+pattynstokesflag=zeros(md.mesh.numberofelements,1);
+if strcmpi(coupling_method,'penalties'),
+	%Create the border nodes between Pattyn and MacAyeal and extrude them
+	numnodes2d=md.mesh.numberofvertices2d;
+	numlayers=md.mesh.numberoflayers;
+	bordernodes2d=find(nodeonpattyn(1:numnodes2d) & nodeonmacayeal(1:numnodes2d)); %Nodes connected to two different types of elements
+
+	%initialize and fill in penalties structure
+	if ~isnan(bordernodes2d),
+		penalties=[];
+		for	i=1:numlayers-1,
+			penalties=[penalties; [bordernodes2d bordernodes2d+md.mesh.numberofvertices2d*(i)]];
+		end
+		md.diagnostic.vertex_pairing=penalties;
+	end
+elseif strcmpi(coupling_method,'tiling'),
+	if any(macayealflag) & any(pattynflag), %coupling macayeal pattyn
+		%Find node at the border
+		nodeonmacayealpattyn(find(nodeonmacayeal & nodeonpattyn))=1;
+		%Macayeal elements in contact with this layer become MacAyealPattyn elements
+		matrixelements=ismember(md.mesh.elements,find(nodeonmacayealpattyn));
+		commonelements=sum(matrixelements,2)~=0;
+		commonelements(find(pattynflag))=0; %only one layer: the elements previously in macayeal
+		macayealflag(find(commonelements))=0; %these elements are now macayealpattynelements
+		macayealpattynflag(find(commonelements))=1;
+		nodeonmacayeal(:)=0;
+		nodeonmacayeal(md.mesh.elements(find(macayealflag),:))=1;
+
+		%rule out elements that don't touch the 2 boundaries
+		pos=find(macayealpattynflag);
+		elist=zeros(length(pos),1);
+		elist = elist + any(sum(nodeonmacayeal(md.mesh.elements(pos,:)),2),2);
+		elist = elist - any(sum(nodeonpattyn(md.mesh.elements(pos,:))  ,2),2);
+		pos1=find(elist==1);
+		macayealflag(pos(pos1))=1;
+		macayealpattynflag(pos(pos1))=0;
+		pos2=find(elist==-1);
+		pattynflag(pos(pos2))=1;
+		macayealpattynflag(pos(pos2))=0;
+
+		%Recompute nodes associated to these elements
+		nodeonmacayeal(:)=0;
+		nodeonmacayeal(md.mesh.elements(find(macayealflag),:))=1;
+		nodeonpattyn(:)=0;
+		nodeonpattyn(md.mesh.elements(find(pattynflag),:))=1;
+		nodeonmacayealpattyn(:)=0;
+		nodeonmacayealpattyn(md.mesh.elements(find(macayealpattynflag),:))=1;
+
+	elseif any(pattynflag) & any(stokesflag), %coupling pattyn stokes
+		%Find node at the border
+		nodeonpattynstokes(find(nodeonpattyn & nodeonstokes))=1;
+		%Stokes elements in contact with this layer become PattynStokes elements
+		matrixelements=ismember(md.mesh.elements,find(nodeonpattynstokes));
+		commonelements=sum(matrixelements,2)~=0;
+		commonelements(find(pattynflag))=0; %only one layer: the elements previously in macayeal
+		stokesflag(find(commonelements))=0; %these elements are now macayealpattynelements
+		pattynstokesflag(find(commonelements))=1;
+		nodeonstokes=zeros(md.mesh.numberofvertices,1);
+		nodeonstokes(md.mesh.elements(find(stokesflag),:))=1;
+
+		%rule out elements that don't touch the 2 boundaries
+		pos=find(pattynstokesflag);
+		elist=zeros(length(pos),1);
+		elist = elist + any(sum(nodeonstokes(md.mesh.elements(pos,:)),2),2);
+		elist = elist - any(sum(nodeonpattyn(md.mesh.elements(pos,:)),2),2);
+		pos1=find(elist==1);
+		stokesflag(pos(pos1))=1;
+		pattynstokesflag(pos(pos1))=0;
+		pos2=find(elist==-1);
+		pattynflag(pos(pos2))=1;
+		pattynstokesflag(pos(pos2))=0;
+
+		%Recompute nodes associated to these elements
+		nodeonstokes(:)=0;
+		nodeonstokes(md.mesh.elements(find(stokesflag),:))=1;
+		nodeonpattyn(:)=0;
+		nodeonpattyn(md.mesh.elements(find(pattynflag),:))=1;
+		nodeonpattynstokes(:)=0;
+		nodeonpattynstokes(md.mesh.elements(find(pattynstokesflag),:))=1;
+
+	elseif any(stokesflag) & any(macayealflag),
+		%Find node at the border
+		nodeonmacayealstokes(find(nodeonmacayeal & nodeonstokes))=1;
+		%Stokes elements in contact with this layer become MacAyealStokes elements
+		matrixelements=ismember(md.mesh.elements,find(nodeonmacayealstokes));
+		commonelements=sum(matrixelements,2)~=0;
+		commonelements(find(macayealflag))=0; %only one layer: the elements previously in macayeal
+		stokesflag(find(commonelements))=0; %these elements are now macayealmacayealelements
+		macayealstokesflag(find(commonelements))=1;
+		nodeonstokes=zeros(md.mesh.numberofvertices,1);
+		nodeonstokes(md.mesh.elements(find(stokesflag),:))=1;
+
+		%rule out elements that don't touch the 2 boundaries
+		pos=find(macayealstokesflag);
+		elist=zeros(length(pos),1);
+		elist = elist + any(sum(nodeonmacayeal(md.mesh.elements(pos,:)),2),2);
+		elist = elist - any(sum(nodeonstokes(md.mesh.elements(pos,:))  ,2),2);
+		pos1=find(elist==1);
+		macayealflag(pos(pos1))=1;
+		macayealstokesflag(pos(pos1))=0;
+		pos2=find(elist==-1);
+		stokesflag(pos(pos2))=1;
+		macayealstokesflag(pos(pos2))=0;
+
+		%Recompute nodes associated to these elements
+		nodeonmacayeal(:)=0;
+		nodeonmacayeal(md.mesh.elements(find(macayealflag),:))=1;
+		nodeonstokes(:)=0;
+		nodeonstokes(md.mesh.elements(find(stokesflag),:))=1;
+		nodeonmacayealstokes(:)=0;
+		nodeonmacayealstokes(md.mesh.elements(find(macayealstokesflag),:))=1;
+
+	elseif any(stokesflag) & any(hutterflag),
+		error('type of coupling not supported yet');
+	end
+end
+
+%Create MacaAyealPattynApproximation where needed
+md.flowequation.element_equation=zeros(md.mesh.numberofelements,1);
+md.flowequation.element_equation(find(noneflag))=0;
+md.flowequation.element_equation(find(hutterflag))=1;
+md.flowequation.element_equation(find(macayealflag))=2;
+md.flowequation.element_equation(find(pattynflag))=3;
+md.flowequation.element_equation(find(stokesflag))=4;
+md.flowequation.element_equation(find(macayealpattynflag))=5;
+md.flowequation.element_equation(find(macayealstokesflag))=6;
+md.flowequation.element_equation(find(pattynstokesflag))=7;
+
+%border
+md.flowequation.borderpattyn=nodeonpattyn;
+md.flowequation.bordermacayeal=nodeonmacayeal;
+md.flowequation.borderstokes=nodeonstokes;
+
+%Create vertices_type
+md.flowequation.vertex_equation=zeros(md.mesh.numberofvertices,1);
+pos=find(nodeonhutter);
+md.flowequation.vertex_equation(pos)=1;
+pos=find(nodeonmacayeal);
+md.flowequation.vertex_equation(pos)=2;
+pos=find(nodeonpattyn);
+md.flowequation.vertex_equation(pos)=3;
+pos=find(nodeonhutter);
+md.flowequation.vertex_equation(pos)=1;
+pos=find(nodeonmacayealpattyn);
+md.flowequation.vertex_equation(pos)=5;
+pos=find(nodeonstokes);
+md.flowequation.vertex_equation(pos)=4;
+if any(stokesflag),
+	pos=find(~nodeonstokes);
+	if(~any(pattynflag) & ~any(macayealflag)),
+		md.flowequation.vertex_equation(pos)=0;
+	end
+end
+pos=find(nodeonpattynstokes);
+md.flowequation.vertex_equation(pos)=7;
+pos=find(nodeonmacayealstokes);
+md.flowequation.vertex_equation(pos)=6;
+
+%figure out solution types
+md.flowequation.ishutter=double(any(md.flowequation.element_equation==1));
+md.flowequation.ismacayealpattyn=double(any(md.flowequation.element_equation==2 | md.flowequation.element_equation==3));
+md.flowequation.isstokes=double(any(md.flowequation.element_equation==4));
+
+return
+
+%Check that tiling can work:
+if any(md.flowequation.bordermacayeal) & any(md.flowequation.borderpattyn) & any(md.flowequation.borderpattyn + md.flowequation.bordermacayeal ~=1),
+	error('error coupling domain too irregular');
+end
+if any(md.flowequation.bordermacayeal) & any(md.flowequation.borderstokes) & any(md.flowequation.borderstokes + md.flowequation.bordermacayeal ~=1),
+	error('error coupling domain too irregular');
+end
+if any(md.flowequation.borderstokes) & any(md.flowequation.borderpattyn) & any(md.flowequation.borderpattyn + md.flowequation.borderstokes~=1),
+	error('error coupling domain too irregular');
+end
Index: /issm/trunk-jpl/src/m/parameterization/setflowequation.py
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setflowequation.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/setflowequation.py	(revision 13009)
@@ -0,0 +1,278 @@
+import numpy
+from model import *
+from pairoptions import *
+from recover_areas import *
+from MatlabFuncs import *
+
+def setflowequation(md,*args):
+	"""
+	SETELEMENTSTYPE - associate a solution type to each element
+
+	   This routine works like plotmodel: it works with an even number of inputs
+	   'hutter','macayeal','pattyn','stokes' and 'fill' are the possible options
+	   that must be followed by the corresponding exp file or flags list
+	   It can either be a domain file (argus type, .exp extension), or an array of element flags. 
+	   If user wants every element outside the domain to be 
+	   setflowequationd, add '~' to the name of the domain file (ex: '~Pattyn.exp');
+	   an empty string '' will be considered as an empty domain
+	   a string 'all' will be considered as the entire domain
+	   You can specify the type of coupling, 'penalties' or 'tiling', to use with the input 'coupling'
+
+	   Usage:
+	      md=setflowequation(md,varargin)
+
+	   Example:
+	      md=setflowequation(md,'pattyn','Pattyn.exp','macayeal',md.mask.elementonfloatingice,'fill','hutter');
+	      md=setflowequation(md,'pattyn','Pattyn.exp',fill','hutter','coupling','tiling');
+	"""
+
+	#some checks on list of arguments
+	if not isinstance(md,model) or not len(args):
+		raise TypeError("setflowequation error message")
+
+	#Find_out what kind of coupling to use
+	options=pairoptions(*args)
+	coupling_method=options.getfieldvalue('coupling','tiling')
+	if not strcmpi(coupling_method,'tiling') and not strcmpi(coupling_method,'penalties'):
+		raise TypeError("coupling type can only be: tiling or penalties")
+
+	hutterflag,macayealflag,pattynflag,stokesflag,filltype=recover_areas(md,*args)
+
+	#Flag the elements that have not been flagged as filltype
+	if   strcmpi(filltype,'hutter'):
+		hutterflag[numpy.nonzero(numpy.logical_not(numpy.logical_or(macayealflag,pattynflag)))]=1
+	elif strcmpi(filltype,'macayeal'):
+		macayealflag[numpy.nonzero(numpy.logical_not(numpy.logical_or(hutterflag,numpy.logical_or(pattynflag,stokesflag))))]=1
+	elif strcmpi(filltype,'pattyn'):
+		pattynflag[numpy.nonzero(numpy.logical_not(numpy.logical_or(hutterflag,numpy.logical_or(macayealflag,stokesflag))))]=1
+
+	#check that each element has at least one flag
+	if not numpy.any(hutterflag+macayealflag+pattynflag+stokesflag):
+		raise TypeError("setflowequation error message: elements type not assigned, must be specified")
+
+	#check that each element has only one flag
+	if numpy.any(hutterflag+macayealflag+pattynflag+stokesflag>1):
+		print "setflowequation warning message: some elements have several types, higher order type is used for them"
+		hutterflag[numpy.nonzero(numpy.logical_and(hutterflag,macayealflag))]=0
+		hutterflag[numpy.nonzero(numpy.logical_and(hutterflag,pattynflag))]=0
+		macayealflag[numpy.nonzero(numpy.logical_and(macayealflag,pattynflag))]=0
+
+	#Check that no pattyn or stokes for 2d mesh
+	if md.mesh.dimension==2:
+		if numpy.any(numpy.logical_or(stokesflag,pattynflag)):
+			raise TypeError("setflowequation error message: stokes and pattyn elements not allowed in 2d mesh, extrude it first")
+
+	#Stokes can only be used alone for now:
+	if numpy.any(stokesflag) and numpy.any(hutterflag):
+		raise TypeError("setflowequation error message: stokes cannot be used with any other model for now, put stokes everywhere")
+
+	#Initialize node fields
+	nodeonhutter=numpy.zeros(md.mesh.numberofvertices)
+	nodeonhutter[md.mesh.elements[numpy.nonzero(hutterflag),:].astype(int)-1]=1
+	nodeonmacayeal=numpy.zeros(md.mesh.numberofvertices)
+	nodeonmacayeal[md.mesh.elements[numpy.nonzero(macayealflag),:].astype(int)-1]=1
+	nodeonpattyn=numpy.zeros(md.mesh.numberofvertices)
+	nodeonpattyn[md.mesh.elements[numpy.nonzero(pattynflag),:].astype(int)-1]=1
+	nodeonstokes=numpy.zeros(md.mesh.numberofvertices)
+	noneflag=numpy.zeros(md.mesh.numberofelements)
+
+	#First modify stokesflag to get rid of elements contrained everywhere (spc + border with pattyn or macayeal)
+	if any(stokesflag):
+#		fullspcnodes=double((~isnan(md.diagnostic.spcvx)+~isnan(md.diagnostic.spcvy)+~isnan(md.diagnostic.spcvz))==3 | (nodeonpattyn & nodeonstokes));         %find all the nodes on the boundary of the domain without icefront
+		fullspcnodes=numpy.logical_or(numpy.logical_not(numpy.isnan(md.diagnostic.spcvx))+ \
+		                              numpy.logical_not(numpy.isnan(md.diagnostic.spcvy))+ \
+		                              numpy.logical_not(numpy.isnan(md.diagnostic.spcvz))==3, \
+		                              numpy.logical_and(nodeonpattyn,nodeonstokes)).astype(int)    #find all the nodes on the boundary of the domain without icefront
+#		fullspcelems=double(sum(fullspcnodes(md.mesh.elements),2)==6);         %find all the nodes on the boundary of the domain without icefront
+		fullspcelems=(numpy.sum(fullspcnodes[md.mesh.elements.astype(int)-1],axis=1)==6).astype(int)    #find all the nodes on the boundary of the domain without icefront
+		stokesflag[numpy.nonzero(fullspcelems)]=0
+		nodeonstokes[md.mesh.elements[numpy.nonzero(stokesflag),:].astype(int)-1]=1
+
+	#Then complete with NoneApproximation or the other model used if there is no stokes
+	if any(stokesflag): 
+		if   any(pattynflag):    #fill with pattyn
+			pattynflag[numpy.logical_not(stokesflag)]=1
+			nodeonpattyn[md.mesh.elements[numpy.nonzero(pattynflag),:].astype(int)-1]=1
+		elif any(macayealflag):    #fill with macayeal
+			macayealflag[numpy.logical_not(stokesflag)]=1
+			nodeonmacayeal[md.mesh.elements[numpy.nonzero(macayealflag),:].astype(int)-1]=1
+		else:    #fill with none 
+			noneflag[numpy.nonzero(numpy.logical_not(stokesflag))]=1
+
+	#Now take care of the coupling between MacAyeal and Pattyn
+	md.diagnostic.vertex_pairing=numpy.array([])
+	nodeonmacayealpattyn=numpy.zeros(md.mesh.numberofvertices)
+	nodeonpattynstokes=numpy.zeros(md.mesh.numberofvertices)
+	nodeonmacayealstokes=numpy.zeros(md.mesh.numberofvertices)
+	macayealpattynflag=numpy.zeros(md.mesh.numberofelements)
+	macayealstokesflag=numpy.zeros(md.mesh.numberofelements)
+	pattynstokesflag=numpy.zeros(md.mesh.numberofelements)
+	if   strcmpi(coupling_method,'penalties'):
+		#Create the border nodes between Pattyn and MacAyeal and extrude them
+		numnodes2d=md.mesh.numberofvertices2d
+		numlayers=md.mesh.numberoflayers
+		bordernodes2d=numpy.nonzero(numpy.logical_and(nodeonpattyn[1:numnodes2d],nodeonmacayeal[1:numnodes2d]))    #Nodes connected to two different types of elements
+
+		#initialize and fill in penalties structure
+		if numpy.all(numpy.logical_not(numpy.isnan(bordernodes2d))):
+			penalties=numpy.zeros((0,2))
+			for	i in xrange(1,numlayers):
+				penalties=numpy.concatenate((penalties,numpy.concatenate((bordernodes2d,bordernodes2d+md.mesh.numberofvertices2d*(i)),axis=1)),axis=0)
+			md.diagnostic.vertex_pairing=penalties
+
+	elif strcmpi(coupling_method,'tiling'):
+		if   numpy.any(macayealflag) and numpy.any(pattynflag):    #coupling macayeal pattyn
+			#Find node at the border
+			nodeonmacayealpattyn[numpy.nonzero(numpy.logical_and(nodeonmacayeal,nodeonpattyn))]=1
+			#Macayeal elements in contact with this layer become MacAyealPattyn elements
+			matrixelements=ismember(md.mesh.elements,numpy.nonzero(nodeonmacayealpattyn))
+			commonelements=numpy.sum(matrixelements,axis=1)!=0
+			commonelements[numpy.nonzero(pattynflag)]=0    #only one layer: the elements previously in macayeal
+			macayealflag[numpy.nonzero(commonelements)]=0    #these elements are now macayealpattynelements
+			macayealpattynflag[numpy.nonzero(commonelements)]=1
+			nodeonmacayeal[:]=0
+			nodeonmacayeal[md.mesh.elements[numpy.nonzero(macayealflag),:].astype(int)-1]=1
+
+			#rule out elements that don't touch the 2 boundaries
+			pos=numpy.nonzero(macayealpattynflag)
+			elist=numpy.zeros(len(pos))
+			elist = elist + numpy.any(numpy.sum(nodeonmacayeal[md.mesh.elements[pos,:].astype(int)-1],axis=1),axis=1)
+			elist = elist - numpy.any(numpy.sum(nodeonpattyn[md.mesh.elements[pos,:].astype(int)-1]  ,axis=1),axis=1)
+			pos1=[i for i,item in enumerate(elist) if item==1]
+			macayealflag[pos[pos1]]=1
+			macayealpattynflag[pos[pos1]]=0
+			pos2=[i for i,item in enumerate(elist) if item==-1]
+			pattynflag[pos[pos2]]=1
+			macayealpattynflag[pos[pos2]]=0
+
+			#Recompute nodes associated to these elements
+			nodeonmacayeal[:]=0
+			nodeonmacayeal[md.mesh.elements[numpy.nonzero(macayealflag),:].astype(int)-1]=1
+			nodeonpattyn[:]=0
+			nodeonpattyn[md.mesh.elements[numpy.nonzero(pattynflag),:].astype(int)-1]=1
+			nodeonmacayealpattyn[:]=0
+			nodeonmacayealpattyn[md.mesh.elements[numpy.nonzero(macayealpattynflag),:].astype(int)-1]=1
+
+		elif numpy.any(pattynflag) and numpy.any(stokesflag):    #coupling pattyn stokes
+			#Find node at the border
+			nodeonpattynstokes[numpy.nonzero(numpy.logical_and(nodeonpattyn,nodeonstokes))]=1
+			#Stokes elements in contact with this layer become PattynStokes elements
+			matrixelements=ismember(md.mesh.elements,numpy.nonzero(nodeonpattynstokes))
+			commonelements=numpy.sum(matrixelements,axis=1)!=0
+			commonelements[numpy.nonzero(pattynflag)]=0    #only one layer: the elements previously in macayeal
+			stokesflag[numpy.nonzero(commonelements)]=0    #these elements are now macayealpattynelements
+			pattynstokesflag[numpy.nonzero(commonelements)]=1
+			nodeonstokes=numpy.zeros(md.mesh.numberofvertices)
+			nodeonstokes[md.mesh.elements[numpy.nonzero(stokesflag),:].astype(int)-1]=1
+
+			#rule out elements that don't touch the 2 boundaries
+			pos=numpy.nonzero(pattynstokesflag)
+			elist=numpy.zeros(len(pos))
+			elist = elist + numpy.any(numpy.sum(nodeonstokes[md.mesh.elements[pos,:].astype(int)-1],axis=1),axis=1)
+			elist = elist - numpy.any(numpy.sum(nodeonpattyn[md.mesh.elements[pos,:].astype(int)-1],axis=1),axis=1)
+			pos1=[i for i,item in enumerate(elist) if item==1]
+			stokesflag[pos[pos1]]=1
+			pattynstokesflag[pos[pos1]]=0
+			pos2=[i for i,item in enumerate(elist) if item==-1]
+			pattynflag[pos[pos2]]=1
+			pattynstokesflag[pos[pos2]]=0
+
+			#Recompute nodes associated to these elements
+			nodeonstokes[:]=0
+			nodeonstokes[md.mesh.elements[numpy.nonzero(stokesflag),:].astype(int)-1]=1
+			nodeonpattyn[:]=0
+			nodeonpattyn[md.mesh.elements[numpy.nonzero(pattynflag),:].astype(int)-1]=1
+			nodeonpattynstokes[:]=0
+			nodeonpattynstokes[md.mesh.elements[numpy.nonzero(pattynstokesflag),:].astype(int)-1]=1
+
+		elif numpy.any(stokesflag) and numpy.any(macayealflag):
+			#Find node at the border
+			nodeonmacayealstokes[numpy.nonzero(numpy.logical_and(nodeonmacayeal,nodeonstokes))]=1
+			#Stokes elements in contact with this layer become MacAyealStokes elements
+			matrixelements=ismember(md.mesh.elements,numpy.nonzero(nodeonmacayealstokes))
+			commonelements=numpy.sum(matrixelements,axis=1)!=0
+			commonelements[numpy.nonzero(macayealflag)]=0    #only one layer: the elements previously in macayeal
+			stokesflag[numpy.nonzero(commonelements)]=0    #these elements are now macayealmacayealelements
+			macayealstokesflag[numpy.nonzero(commonelements)]=1
+			nodeonstokes=numpy.zeros(md.mesh.numberofvertices)
+			nodeonstokes[md.mesh.elements[numpy.nonzero(stokesflag),:].astype(int)-1]=1
+
+			#rule out elements that don't touch the 2 boundaries
+			pos=numpy.nonzero(macayealstokesflag)
+			elist=numpy.zeros(len(pos))
+			elist = elist + numpy.any(numpy.sum(nodeonmacayeal[md.mesh.elements[pos,:].astype(int)-1],axis=1),axis=1)
+			elist = elist - numpy.any(numpy.sum(nodeonstokes[md.mesh.elements[pos,:].astype(int)-1]  ,axis=1),axis=1)
+			pos1=[i for i,item in enumerate(elist) if item==1]
+			macayealflag[pos[pos1]]=1
+			macayealstokesflag[pos[pos1]]=0
+			pos2=[i for i,item in enumerate(elist) if item==-1]
+			stokesflag[pos[pos2]]=1
+			macayealstokesflag[pos[pos2]]=0
+
+			#Recompute nodes associated to these elements
+			nodeonmacayeal[:]=0
+			nodeonmacayeal[md.mesh.elements[numpy.nonzero(macayealflag),:].astype(int)-1]=1
+			nodeonstokes[:]=0
+			nodeonstokes[md.mesh.elements[numpy.nonzero(stokesflag),:].astype(int)-1]=1
+			nodeonmacayealstokes[:]=0
+			nodeonmacayealstokes[md.mesh.elements[numpy.nonzero(macayealstokesflag),:].astype(int)-1]=1
+
+		elif numpy.any(stokesflag) and numpy.any(hutterflag):
+			raise TypeError("type of coupling not supported yet")
+
+	#Create MacaAyealPattynApproximation where needed
+	md.flowequation.element_equation=numpy.zeros(md.mesh.numberofelements)
+	md.flowequation.element_equation[numpy.nonzero(noneflag)]=0
+	md.flowequation.element_equation[numpy.nonzero(hutterflag)]=1
+	md.flowequation.element_equation[numpy.nonzero(macayealflag)]=2
+	md.flowequation.element_equation[numpy.nonzero(pattynflag)]=3
+	md.flowequation.element_equation[numpy.nonzero(stokesflag)]=4
+	md.flowequation.element_equation[numpy.nonzero(macayealpattynflag)]=5
+	md.flowequation.element_equation[numpy.nonzero(macayealstokesflag)]=6
+	md.flowequation.element_equation[numpy.nonzero(pattynstokesflag)]=7
+
+	#border
+	md.flowequation.borderpattyn=nodeonpattyn
+	md.flowequation.bordermacayeal=nodeonmacayeal
+	md.flowequation.borderstokes=nodeonstokes
+
+	#Create vertices_type
+	md.flowequation.vertex_equation=numpy.zeros(md.mesh.numberofvertices)
+	pos=numpy.nonzero(nodeonhutter)
+	md.flowequation.vertex_equation[pos]=1
+	pos=numpy.nonzero(nodeonmacayeal)
+	md.flowequation.vertex_equation[pos]=2
+	pos=numpy.nonzero(nodeonpattyn)
+	md.flowequation.vertex_equation[pos]=3
+	pos=numpy.nonzero(nodeonhutter)
+	md.flowequation.vertex_equation[pos]=1
+	pos=numpy.nonzero(nodeonmacayealpattyn)
+	md.flowequation.vertex_equation[pos]=5
+	pos=numpy.nonzero(nodeonstokes)
+	md.flowequation.vertex_equation[pos]=4
+	if numpy.any(stokesflag):
+		pos=numpy.nonzero(numpy.logical_not(nodeonstokes))
+		if not (numpy.any(pattynflag) or numpy.any(macayealflag)):
+			md.flowequation.vertex_equation[pos]=0
+	pos=numpy.nonzero(nodeonpattynstokes)
+	md.flowequation.vertex_equation[pos]=7
+	pos=numpy.nonzero(nodeonmacayealstokes)
+	md.flowequation.vertex_equation[pos]=6
+
+	#figure out solution types
+	md.flowequation.ishutter=float(numpy.any(md.flowequation.element_equation==1))
+	md.flowequation.ismacayealpattyn=float(numpy.any(numpy.logical_or(md.flowequation.element_equation==2,md.flowequation.element_equation==3)))
+	md.flowequation.isstokes=float(numpy.any(md.flowequation.element_equation==4))
+
+	return md
+
+	#Check that tiling can work:
+	if numpy.any(md.flowequation.bordermacayeal) and numpy.any(md.flowequation.borderpattyn) and numpy.any(md.flowequation.borderpattyn + md.flowequation.bordermacayeal !=1):
+		raise TypeError("error coupling domain too irregular")
+	if numpy.any(md.flowequation.bordermacayeal) and numpy.any(md.flowequation.borderstokes) and numpy.any(md.flowequation.borderstokes + md.flowequation.bordermacayeal !=1):
+		raise TypeError("error coupling domain too irregular")
+	if numpy.any(md.flowequation.borderstokes) and numpy.any(md.flowequation.borderpattyn) and numpy.any(md.flowequation.borderpattyn + md.flowequation.borderstokes !=1):
+		raise TypeError("error coupling domain too irregular")
+
+	return md
+
Index: /issm/trunk-jpl/src/m/parameterization/setmask.m
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setmask.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/setmask.m	(revision 13009)
@@ -0,0 +1,49 @@
+function md=setmask(md,floatingicename,groundedicename)
+%SETMASK - establish boundaries between grounded and floating ice.
+%
+%   By default, ice is considered grounded. The contour floatingicename defines nodes 
+%   for which ice is floating. The contour groundedicename defines nodes inside an floatingice, 
+%   that are grounded (ie: ice rises, islands, etc ...)
+%   All input files are in the Argus format (extension .exp).
+%
+%   Usage:
+%      md=setmask(md,floatingicename,groundedicename)
+%
+%   Examples:
+%      md=setmask(md,'all','');
+%      md=setmask(md,'Iceshelves.exp','Islands.exp');
+
+%some checks on list of arguments
+if ((nargin~=3) | (nargout~=1)),
+	help mask
+	error('mask error message');
+end
+
+%Get assigned fields
+x=md.mesh.x;
+y=md.mesh.y;
+elements=md.mesh.elements;
+
+%Assign elementonfloatingice, elementongroundedice, vertexongroundedice and vertexonfloatingice. Only change at your own peril! This is synchronized heavily with the GroundingLineMigration module. {{{
+elementonfloatingice=FlagElements(md,floatingicename);
+elementongroundedice=FlagElements(md,groundedicename);
+
+%Because groundedice nodes and elements can be included into an floatingice, we need to update. Remember, all the previous 
+%arrays come from domain outlines that can intersect one another: 
+elementonfloatingice=double((elementonfloatingice & ~elementongroundedice));
+elementongroundedice=double(~elementonfloatingice);
+
+%the order here is important. we choose vertexongroundedice as default on the grounding line.
+vertexonfloatingice=zeros(md.mesh.numberofvertices,1);
+vertexongroundedice=zeros(md.mesh.numberofvertices,1);
+vertexongroundedice(md.mesh.elements(find(elementongroundedice),:))=1;
+vertexonfloatingice(find(~vertexongroundedice))=1;
+%}}}
+
+%Return: 
+md.mask.elementonfloatingice=elementonfloatingice;
+md.mask.vertexonfloatingice=vertexonfloatingice;
+md.mask.elementongroundedice=elementongroundedice;
+md.mask.vertexongroundedice=vertexongroundedice;
+md.mask.vertexonwater=zeros(md.mesh.numberofvertices,1);
+md.mask.elementonwater=zeros(md.mesh.numberofelements,1);
Index: /issm/trunk-jpl/src/m/parameterization/setmask.py
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setmask.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/setmask.py	(revision 13009)
@@ -0,0 +1,55 @@
+from numpy import *
+import FlagElements as fe
+
+def setmask(md, floatingicename, groundedicename):
+	#SETMASK - establish boundaries between grounded and floating ice.
+	#
+	#   By default, ice is considered grounded. The contour floatingicename defines nodes 
+	#   for which ice is floating. The contour groundedicename defines nodes inside an floatingice, 
+	#   that are grounded (ie: ice rises, islands, etc ...)
+	#   All input files are in the Argus format (extension .exp).
+	#
+	#   Usage:
+	#      md=setmask(md,floatingicename,groundedicename)
+	#
+	#   Examples:
+	#      md=setmask(md,'all','');
+	#      md=setmask(md,'Iceshelves.exp','Islands.exp');
+
+	#%Get assigned fields
+	x = md.mesh.x
+	y = md.mesh.y
+	elements = md.mesh.elements
+
+	#Assign elementonfloatingice, elementongroundedice, vertexongroundedice and vertexonfloatingice. Only change at your own peril! This is synchronized heavily with the GroundingLineMigration module. {{{
+	elementonfloatingice = fe.FlagElements(md, floatingicename)
+	elementongroundedice = fe.FlagElements(md, groundedicename) 
+
+	#Because groundedice nodes and elements can be included into an floatingice, we need to update. Remember, all the previous 
+	#arrays come from domain outlines that can intersect one another: 
+
+	elementonfloatingice = logical_and(elementonfloatingice,~elementongroundedice)
+	elementongroundedice = ~elementonfloatingice
+
+	#the order here is important. we choose vertexongroundedice as default on the grounding line.
+	vertexonfloatingice = zeros(md.mesh.numberofvertices,'bool')
+	vertexongroundedice = zeros(md.mesh.numberofvertices,'bool')
+
+	pos=argwhere(elementongroundedice==1)
+	pos=md.mesh.elements[pos,:]-1
+	if pos.size:
+		vertexongroundedice[pos]=True
+
+	pos=argwhere(~vertexongroundedice)
+	if pos.size:
+		vertexonfloatingice[pos]=True;
+	#%}}}
+
+	#Return: 
+	md.mask.elementonfloatingice = double(elementonfloatingice)
+	md.mask.vertexonfloatingice = double(vertexonfloatingice)
+	md.mask.elementongroundedice = double(elementongroundedice)
+	md.mask.vertexongroundedice = double(vertexongroundedice)
+	md.mask.vertexonwater = zeros(md.mesh.numberofvertices)
+	md.mask.elementonwater = zeros(md.mesh.numberofelements)
+	return md
Index: /issm/trunk-jpl/src/m/parameterization/setmask2.m
===================================================================
--- /issm/trunk-jpl/src/m/parameterization/setmask2.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/parameterization/setmask2.m	(revision 13009)
@@ -0,0 +1,148 @@
+function md=setmask2(md,landname,floatingicename,groundedicename)
+%GEOGRAPHY2 - establish land, ice sheet and ice shelf areas in a domains.
+%
+%   Usage:
+%      md=setmask2(md,landname,floatingicename,groundedicename)
+%
+%   Examples:
+%      md=setmask2(md,'LandName.exp','Iceshelves.exp','Islands.exp');
+
+%Get assigned fields
+x=md.mesh.x;
+y=md.mesh.y;
+elements=md.mesh.elements;
+
+%recover elements and nodes on land.
+if ischar(landname),
+	[vertexonland,elementonland]=ContourToMesh(elements,x,y,landname,'element and node',2);
+elseif isfloat(landname),
+	if size(landname,1)~=md.mesh.numberofelements,
+		error('Landname for area must be of same size as number of elements in model');
+	end
+	elementonland=landname;
+	vertexonland=zeros(md.mesh.numberofvertices,1);
+	vertexonland(md.mesh.elements(find(elementonland),:))=1;
+else
+	error('Invalid area option option');
+end
+
+%Now, build the connectivity tables for this mesh.
+if size(md.mesh.vertexconnectivity,1)~=md.mesh.numberofvertices,
+	md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+end
+if size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements,
+	md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity);
+end
+
+%any element with 3 nodes on land should be on land:
+elementsonwater=find(~elementonland);
+wrongelements=elementsonwater(find(( vertexonland(md.mesh.elements(elementsonwater,1)) + vertexonland(md.mesh.elements(elementsonwater,2)) + vertexonland(md.mesh.elements(elementsonwater,3)) ...
+                  )==3));
+elementonland(wrongelements)=1;
+
+%any element with its barycentre on land should be on land: (only if landname is an expfile)
+if ischar(landname),
+weights={[1;1;1],[2;1;1],[1;2;1],[1;1;2]};
+	for i=1:length(weights),
+		xelem=x(md.mesh.elements)*weights{i}/sum(weights{i});
+		yelem=y(md.mesh.elements)*weights{i}/sum(weights{i});
+	end
+	baryonland=ContourToNodes(xelem,yelem,landname,1);
+	pos=find(~baryonland); elementonland(pos)=0;
+	pos=find(baryonland); elementonland(pos)=1;
+end
+
+%figure out which elements on land are actually in the middle of the ocean!
+pos1=find(elementonland); 
+connectedtoland=md.mesh.elementconnectivity(pos1,:);
+pos=find(connectedtoland); connectedtoland(pos)=1-elementonland(connectedtoland(pos));
+connectedtolandsum=sum(connectedtoland,2);
+waterelements=pos1(find(connectedtolandsum==3));
+elementonland(waterelements)=0;
+
+%figure out which elements on water  are actually in the middle of the land!
+pos1=find(~elementonland); 
+connectedtowater=md.mesh.elementconnectivity(pos1,:);
+pos=find(connectedtowater); connectedtowater(pos)=elementonland(connectedtowater(pos));
+connectedtowatersum=sum(connectedtowater,2);
+landelements=pos1(find(connectedtowatersum==3));
+elementonland(landelements)=1;
+
+%recover arrays of ice shelf nodes and elements, and ice sheet nodes and elements.
+elementonfloatingice=FlagElements(md,floatingicename);
+elementongroundedice=FlagElements(md,groundedicename);
+
+%Because groundedice nodes and elements can be included into an floatingice, we need to update. Remember, all the previous 
+%arrays come from domain outlines that can intersect one another: 
+vertexonfloatingice=zeros(md.mesh.numberofvertices,1);
+vertexongroundedice=zeros(md.mesh.numberofvertices,1);
+elementonfloatingice=double((elementonfloatingice & ~elementongroundedice));
+elementongroundedice=double(~elementonfloatingice);
+vertexonfloatingice(md.mesh.elements(find(elementonfloatingice),:))=1;
+vertexongroundedice(md.mesh.elements(find(elementongroundedice),:))=1;
+
+%now correct, so that none of the floatingice and groundedice elements and nodes are in the water.
+pos=find(~elementonland);
+elementonfloatingice(pos)=0; 
+elementongroundedice(pos)=0;
+
+pos=find(~vertexonland);
+vertexonfloatingice(pos)=0; 
+vertexongroundedice(pos)=0;
+
+%create vertexonwater and elementonwater: 
+vertexonwater=double(~vertexonland);
+elementonwater=double(~elementonland);
+
+%correct for islands:
+vertexonfloatingice=double(vertexonfloatingice & ~vertexongroundedice);
+elementonfloatingice=double(elementonfloatingice & ~elementongroundedice);
+
+%now, groundedices are everything except iceshelves and water
+vertexongroundedice=double(~vertexonfloatingice & ~vertexonwater);
+elementongroundedice=double(~elementonfloatingice & ~elementonwater);
+
+%Deal with segments on neumann:
+
+%Get current connectivity
+mesh.elementconnectivity=md.mesh.elementconnectivity;
+
+%put 0 for elements on water
+pos=find(mesh.elementconnectivity);
+mesh.elementconnectivity(pos)=mesh.elementconnectivity(pos).*(~elementonwater(mesh.elementconnectivity(pos)));
+
+%put line of ones for elements on water
+pos=find(elementonwater);
+mesh.elementconnectivity(pos,:)=1;% line of ones for elements on water so they won't be considered
+
+%resort lines (zeros must be at the last column for findsegments)
+mesh.elementconnectivity=sort(mesh.elementconnectivity,2,'descend');
+
+%call findsegments to build segment using THIS conectivity
+md.mesh.segments=findsegments(md,'mesh.elementconnectivity',mesh.elementconnectivity);
+
+%some final checks: 
+%check that no node thinks it's on an ice shelf or ice sheet, and lies actually in the middle of the water.
+nodesgrounded=find(~vertexonwater);
+lengthconnectivity=size(md.mesh.vertexconnectivity,2);
+groundedcounters=md.mesh.vertexconnectivity(nodesgrounded,lengthconnectivity);
+groundedconnectivity=md.mesh.vertexconnectivity(nodesgrounded,1:lengthconnectivity-1);
+pos=find(groundedconnectivity);
+groundedconnectivity(pos)=elementonwater(groundedconnectivity(pos));
+groundedsum=sum(groundedconnectivity,2);
+errorflags=find(groundedsum==groundedcounters);
+errornodes=nodesgrounded(errorflags);
+
+vertexonwater(errornodes)=1;
+vertexongroundedice(errornodes)=0;
+vertexonfloatingice(errornodes)=0;
+
+%Return: 
+md.mask.vertexonfloatingice=vertexonfloatingice;
+md.mask.elementonfloatingice=elementonfloatingice;
+md.mask.vertexonwater=vertexonwater;
+md.mask.elementonwater=elementonwater;
+md.mask.vertexongroundedice=vertexongroundedice;
+md.mask.elementongroundedice=elementongroundedice;
+
+md.mesh.segmentmarkers(:)=1;
Index: /issm/trunk-jpl/src/m/partition/AreaAverageOntoPartition.m
===================================================================
--- /issm/trunk-jpl/src/m/partition/AreaAverageOntoPartition.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/partition/AreaAverageOntoPartition.m	(revision 13009)
@@ -0,0 +1,55 @@
+function partvector=AreaAverageOntoPartition(md,vector,layer)
+%AREAAVERAGEONTOPARTITION 
+%   compute partition values for a certain vector expressed on the vertices of the mesh.
+%   Use area weighted average.
+%
+%   Usage:
+%      average=AreaAverageOntoPartition(md,vector)
+%      average=AreaAverageOntoPartition(md,vector,layer) %if in 3D, chose which layer is partitioned
+
+%some checks
+if md.mesh.dimension==3,
+	if nargin~=3,
+		error('layer should be provided onto which Area Averaging occurs');
+	end
+	%save 3D model
+	md3d=md;
+	
+	md.mesh.elements=md.mesh.elements2d;
+	md.mesh.x=md.mesh.x2d;
+	md.mesh.y=md.mesh.y2d;
+	md.mesh.numberofvertices=md.mesh.numberofvertices2d;
+	md.mesh.numberofelements=md.mesh.numberofelements2d;
+	md.qmu.vertex_weight=[];
+	md.mesh.vertexconnectivity=[];
+
+	%run connectivity routine
+	md=adjacency(md);
+
+	%finally, project vector: 
+	vector=project2d(md3d,vector,layer);
+	md.qmu.partition=project2d(md3d,md3d.qmu.partition,layer);
+end
+
+%ok, first check that part is Matlab indexed
+part=md.qmu.partition+1;
+
+%some check: 
+if md.qmu.numberofpartitions~=max(part),
+	error('AreaAverageOntoPartition error message: ''npart'' should be equal to max(md.qmu.partition)');
+end
+
+%initialize output
+partvector=zeros(max(part),1);
+
+%start weight average
+weightedvector=vector.*md.qmu.vertex_weight;
+for i=1:max(part),
+	pos=find(part==i);
+	partvector(i)=sum(weightedvector(pos))/sum(md.qmu.vertex_weight(pos));
+end
+
+%in 3D, restore 3D model:
+if md.mesh.dimension==3,
+	md=md3d;
+end
Index: /issm/trunk-jpl/src/m/partition/adjacency.m
===================================================================
--- /issm/trunk-jpl/src/m/partition/adjacency.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/partition/adjacency.m	(revision 13009)
@@ -0,0 +1,26 @@
+function md=adjacency(md);
+%ADJACENCY -  compute adjacency matrix, list of vertices and list of weights.
+%
+%  function to create the adjacency matrix from the connectivity table.
+%
+%  the required output is:
+%    md.adj_mat     (double [sparse nv x nv], vertex adjacency matrix)
+%    md.qmu.vertex_weight        (double [nv], vertex weights)
+
+indi=[md.mesh.elements(:,1);md.mesh.elements(:,2);md.mesh.elements(:,3)];
+indj=[md.mesh.elements(:,2);md.mesh.elements(:,3);md.mesh.elements(:,1)];
+values=1;
+
+md.qmu.adjacency=sparse(indi,indj,values,md.mesh.numberofvertices,md.mesh.numberofvertices);
+md.qmu.adjacency=double([md.qmu.adjacency | md.qmu.adjacency']);
+
+%now, build vwgt:
+areas=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+
+%get node connectivity
+md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices);
+
+connectivity=md.mesh.vertexconnectivity(:,1:end-1);
+pos=find(connectivity);
+connectivity(pos)=areas(connectivity(pos))/3;
+md.qmu.vertex_weight=sum(connectivity,2);
Index: /issm/trunk-jpl/src/m/partition/flagedges.m
===================================================================
--- /issm/trunk-jpl/src/m/partition/flagedges.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/partition/flagedges.m	(revision 13009)
@@ -0,0 +1,45 @@
+function [xsegments ysegments]=flagedges(elements,x,y,partition);
+%FLAGEDGES - return pairs of x,y segments, delimiting partitions.
+%
+%   Usage:
+%      [xsegments ysegments]=flagedges(elements,x,y,partition)
+
+xsegments=[];
+ysegments=[];
+
+for i=1:size(elements,1),
+	m1=partition(elements(i,1));
+	m2=partition(elements(i,2));
+	m3=partition(elements(i,3));
+	x1=x(elements(i,1));
+	x2=x(elements(i,2));
+	x3=x(elements(i,3));
+	y1=y(elements(i,1));
+	y2=y(elements(i,2));
+	y3=y(elements(i,3));
+
+	if (m1~=m2) & (m1~=m3) & (m2~=m3),
+		xmiddle=(x1+x2+x3)/3;
+		ymiddle=(y1+y2+y3)/3;
+		xsegments=[xsegments; (x1+x2)/2 xmiddle];
+		xsegments=[xsegments; (x1+x3)/2 xmiddle];
+		xsegments=[xsegments; (x2+x3)/2 xmiddle];
+		ysegments=[ysegments; (y1+y2)/2 ymiddle];
+		ysegments=[ysegments; (y1+y3)/2 ymiddle];
+		ysegments=[ysegments; (y2+y3)/2 ymiddle];
+	end
+
+	if (m1==m2) & (m1~=m3),
+		xsegments=[xsegments; (x1+x3)/2 (x2+x3)/2];
+		ysegments=[ysegments; (y1+y3)/2 (y2+y3)/2];
+	end
+	if (m1==m3) & (m2~=m3),
+		xsegments=[xsegments; (x1+x2)/2 (x2+x3)/2];
+		ysegments=[ysegments; (y1+y2)/2 (y2+y3)/2];
+	end
+
+	if (m2==m3) & (m1~=m3),
+		xsegments=[xsegments; (x1+x2)/2 (x1+x3)/2];
+		ysegments=[ysegments; (y1+y2)/2 (y1+y3)/2];
+	end
+end
Index: /issm/trunk-jpl/src/m/partition/partitioner.m
===================================================================
--- /issm/trunk-jpl/src/m/partition/partitioner.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/partition/partitioner.m	(revision 13009)
@@ -0,0 +1,107 @@
+function md=partitioner(md,varargin)
+%PARTITIONER - partition mesh 
+%
+%   List of options to partitioner: 
+%
+%   package: 'chaco', 'metis' or 'scotch'
+%   npart: number of partitions.
+%   weighting: 'on' or 'off': default off
+%   section:  1 by defaults(1=bisection, 2=quadrisection, 3=octasection)
+%   recomputeadjacency:  'on' by default (set to 'off' to compute existing one)
+%   Output: md.qmu.partition recover the partition vector
+%   
+%   Usage:
+%      md=partitioner(md,'package','chaco','npart',100,'weighting','on');
+%
+
+%get options: 
+options=pairoptions(varargin{:});
+
+%set defaults
+options=addfielddefault(options,'package','chaco');
+options=addfielddefault(options,'npart',10);
+options=addfielddefault(options,'weighting','on');
+options=addfielddefault(options,'section',1);
+options=addfielddefault(options,'recomputeadjacency','on');
+
+%get package: 
+package=getfieldvalue(options,'package');
+npart=getfieldvalue(options,'npart');
+recomputeadjacency=getfieldvalue(options,'recomputeadjacency');
+
+if(md.mesh.dimension==3),
+	%partitioning essentially happens in 2D. So partition in 2D, then 
+	%extrude the partition vector vertically. 
+	md3d=md; %save  for later
+	md.mesh.elements=md.mesh.elements2d;
+	md.mesh.x=md.mesh.x2d;
+	md.mesh.y=md.mesh.y2d;
+	md.mesh.numberofvertices=md.mesh.numberofvertices2d;
+	md.mesh.numberofelements=md.mesh.numberofelements2d;
+	md.qmu.vertex_weight=[];
+	md.mesh.vertexconnectivity=[];
+end
+
+%adjacency matrix if needed:
+if strcmpi(recomputeadjacency,'on'),
+	md=adjacency(md);
+else
+	disp('skipping adjacency matrix computation as requested in the options');
+end
+
+
+if strcmpi(package,'chaco'),
+
+	%  default method (from chaco.m)
+	method=[1 1 0 0 1 1 50 0 .001 7654321]';
+	method(1)=3;    %  global method (3=inertial (geometric))
+	method(3)=0;    %  vertex weights (0=off, 1=on)
+	
+	%specify bisection
+	method(6)=getfieldvalue(options,'section');%  ndims (1=bisection, 2=quadrisection, 3=octasection)
+
+	%are we using weights? 
+	if strcmpi(getfieldvalue(options,'weighting'),'on'),
+		weights=floor(md.qmu.vertex_weight/min(md.qmu.vertex_weight));
+		method(3)=1;
+	else 
+		weights=[];
+	end
+	
+	%  partition into nparts
+	part=Chaco(md.qmu.adjacency,weights,[],md.mesh.x, md.mesh.y ,md.mesh.z,method,npart,[])'+1; %index partitions from 1 up. like metis.
+
+elseif strcmpi(package,'scotch'),
+
+	%are we using weights? 
+	if strcmpi(getfieldvalue(options,'weighting'),'on'),
+		weights=floor(md.qmu.vertex_weight/min(md.qmu.vertex_weight));
+	end
+	maptab=Scotch(md.qmu.adjacency,[],weights,[],'cmplt',[npart]);
+	
+	part=maptab(:,2);%index partitions from 1 up. like metis.
+
+
+elseif strcmpi(package,'linear'),
+
+	part=1:1:md.mesh.numberofvertices;
+
+elseif strcmpi(package,'metis'),
+
+	[element_partitioning,part]=MeshPartition(md.mesh,md.qmu.numberofpartitions);
+
+else
+
+	error(['partitioner error message: could not find ' package ' partitioner']);
+	help partitioner
+end
+
+%extrude if we are in 3D:
+if md.mesh.dimension==3,
+	md3d.qmu.vertex_weight=md.qmu.vertex_weight;
+	md3d.qmu.adjacency=md.qmu.adjacency;
+	md=md3d;
+	part=project3d(md,'vector',part','type','node');
+end
+
+md.qmu.partition=part;
Index: /issm/trunk-jpl/src/m/plot/applyoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/applyoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/applyoptions.m	(revision 13009)
@@ -0,0 +1,509 @@
+function applyoptions(md,data,options)
+%APPLYOPTIONS - apply the options to current plot
+%
+%   Usage:
+%      applyoptions(md,data,options)
+%
+%   See also: PLOTMODEL, PARSE_OPTIONS
+		
+
+%some defaults
+if isfield(md.mesh,'hemisphere'),
+	if strcmpi(md.mesh.hemisphere,'n'), options=addfielddefault(options,'hemisphere','n'); 
+	elseif strcmpi(md.mesh.hemisphere,'s'), options=addfielddefault(options,'hemisphere','s'); 
+	end
+end
+
+%fontsize
+fontsize=getfieldvalue(options,'fontsize',14);
+
+%fontweight
+fontweight=getfieldvalue(options,'fontweight','normal');
+
+%title
+if exist(options,'title')
+	titlevalue=getfieldvalue(options,'title');
+	if iscell(titlevalue),
+		title(titlevalue,'FontSize',fontsize,'FontWeight',fontweight);
+	else
+		if ~isnan(titlevalue),
+			title(titlevalue,'FontSize',fontsize,'FontWeight',fontweight);
+		end
+	end
+end
+
+%xlabel, ylabel and zlabel
+if exist(options,'xlabel');
+	xlabel(getfieldvalue(options,'xlabel'),'FontSize',fontsize,'FontWeight',fontweight);
+end
+if exist(options,'ylabel');
+	ylabel(getfieldvalue(options,'ylabel'),'FontSize',fontsize,'FontWeight',fontweight);
+end
+if exist(options,'zlabel');
+	zlabel(getfieldvalue(options,'zlabel'),'FontSize',fontsize,'FontWeight',fontweight);
+end
+
+%xticks, yticks and zticks
+if exist(options,'xtick'), set(gca,'XTick',getfieldvalue(options,'xtick')); end
+if exist(options,'ytick'), set(gca,'YTick',getfieldvalue(options,'ytick')); end
+if exist(options,'ztick'), set(gca,'ZTick',getfieldvalue(options,'ztick')); end
+
+%view 
+if md.mesh.dimension==3 & ~exist(options,'layer'),
+	view(getfieldvalue(options,'view',3));
+else
+	view(getfieldvalue(options,'view',2));
+end
+
+%axis
+set(gca,'FontSize',getfieldvalue(options,'axisfontsize',fontsize));;
+if exist(options,'axis')
+	eval(['axis ' getfieldvalue(options,'axis')]);
+else
+	if ((md.mesh.dimension==2) | exist(options,'layer')),
+		axis tight equal;
+	else
+		axis auto tight
+	end
+end
+
+%box
+if exist(options,'box')
+	eval(['box ' getfieldvalue(options,'box')]);
+end
+
+%xlim, ylim and zlim
+if exist(options,'xlim');
+	xlim(getfieldvalue(options,'xlim'));
+end
+if exist(options,'ylim');
+	ylim(getfieldvalue(options,'ylim'));
+end
+if exist(options,'zlim');
+	zlim(getfieldvalue(options,'zlim'));
+end
+
+%latlon
+%Must be done here (before xlim and ylim??) so that it uses the same xlim and ylim as plot_overlay
+%these are changed by axis that follows
+if ~strcmpi(getfieldvalue(options,'latlon','off'),'off')
+	latlonoverlay(md,options);
+end
+
+%Basinzoom
+if exist(options,'basin');
+	basinzoom(options);
+end
+
+%ShowBasins
+if strcmpi(getfieldvalue(options,'showbasins','off'),'on')
+	showbasins(options);
+end
+
+%Caxis
+if exist(options,'caxis'),
+	caxis(getfieldvalue(options,'caxis'));
+end
+
+%shading
+if exist(options,'shading'),
+	shading(getfieldvalue(options,'shading'));
+end
+
+%grid
+if exist(options,'grid'),
+	if strcmpi(getfieldvalue(options,'grid'),'on'),
+		grid on;
+	end
+end
+
+%colormap
+c = getcolormap(options);
+h = colormap(c);
+
+%wrapping
+if exist(options,'wrapping'),
+	if ~exist(options,'colormap'),
+		h=jet;
+	end
+	colormap(repmat(h,getfieldvalue(options,'wrapping',1),1));
+end
+
+%colorbar
+if getfieldvalue(options,'colorbar',1)==1,
+	if exist(options,'colorbarcornerposition'),
+		c=colorbar(getfieldvalue(options,'colorbarcornerposition'),'peer',gca);
+	else 
+		c=colorbar('peer',gca);
+	end
+	set(c,'FontSize',getfieldvalue(options,'colorbarfontsize',fontsize),'YColor',getfieldvalue(options,'FontColor','k'));
+	if exist(options,'wrapping')
+		lim=get(c,'Ylim');
+		lim=[lim(1) lim(1)+(lim(2)-lim(1))/getfieldvalue(options,'wrapping')];
+		set(c,'Ylim',lim);
+	end
+	if exist(options,'colorbarpos'),
+		set(c,'Position',getfieldvalue(options,'colorbarpos'));
+	end
+	if exist(options,'log'),
+		nlab=5;
+		logvalue=getfieldvalue(options,'log');
+
+		scaleminmax=caxis;
+		Min=min(scaleminmax);
+		Max=max(scaleminmax);
+		set(c,'YLim',[Min Max]); % set colorbar limits
+		set(c,'YTick',linspace(Min,Max,nlab));     % set tick mark locations
+
+		labels = cell(1,nlab);
+		tick_vals = linspace(Min,Max,nlab);
+		tick_vals = exp(log(logvalue)*tick_vals);
+		warning off MATLAB:log:logOfZero;
+		for i = 1:nlab
+			labels{i} = sprintf('%-3.4g',round_ice(tick_vals(i),2));
+			%labels{i} = sprintf('%-.4g',round_ice(tick_vals(i),2));
+		end
+		warning on MATLAB:log:logOfZero;
+		set(c,'YTickLabel',labels);
+	end 
+ 	if exist(options,'cbYLim'); 
+		set(c,'YLim',getfieldvalue(options,'cbYLim'));
+	end
+	if exist(options,'colorbartitle'),
+		set(get(c,'title'),'FontSize',getfieldvalue(options,'colorbarfontsize',fontsize),'String',getfieldvalue(options,'colorbartitle'),...
+			'Color',getfieldvalue(options,'FontColor','k'));
+	end
+	if exist(options,'colorbarYLabel'),
+		set(get(c,'Ylabel'),'FontSize',getfieldvalue(options,'colorbarfontsize',fontsize),'String',getfieldvalue(options,'colorbarYLabel'),...
+			'Color',getfieldvalue(options,'FontColor','k'),'Interpreter',getfieldvalue(options,'Interpreter','none'));
+	end
+	if exist(options,'colorbarwidth'),
+		posaxes=get(gca,'Position');
+		alpha=getfieldvalue(options,'colorbarwidth',1);
+		position=get(c,'Position');
+		dx=position(3);
+		newdx=dx*alpha;
+		position(1)=position(1)+(dx-newdx)/2;
+		position(3)=newdx;
+		set(c,'Position',position);
+		set(gca,'Position',posaxes);
+	end
+	if exist(options,'colorbarheight'),
+		posaxes=get(gca,'Position');
+		alpha=getfieldvalue(options,'colorbarheight',1);
+		position=get(c,'Position');
+		dy=position(4);
+		newdy=dy*alpha;
+		position(2)=position(2)+(dy-newdy)/2;
+		position(4)=newdy;
+		set(c,'Position',position);
+		set(gca,'Position',posaxes);
+	end
+	if exist(options,'cbYTickLabel');
+		tick_vals=getfieldvalue(options,'cbYTickLabel');
+		if ~isnumeric(tick_vals) & strcmp(tick_vals,'on')
+			tick_vals=get(c,'YTick')';
+			if exist(options,'log')
+				logval= getfieldvalue(options,'log');
+				for i= 1:size(tick_vals,1)
+					tick_vals(i)= logval^(tick_vals(i));
+				end
+			elseif size(tick_vals,1) == 3
+				tick_vals=[tick_vals(1); mean(tick_vals(1:2)); tick_vals(2); ...
+					mean(tick_vals(2:3)); tick_vals(3)];
+				set(c,'YTick',tick_vals);
+			end
+		end
+		labels = cell(1,size(tick_vals,1));
+		for i = 1:size(tick_vals,1)
+			labels{i} = sprintf('%-3.4g',round_ice(tick_vals(i),2));
+		end
+		set(c,'YTickLabel',labels);
+	end
+
+elseif getfieldvalue(options,'colorbar',1)==0,
+	colorbar('off');
+else
+	%do nothing
+	
+end
+
+
+%area
+if exist(options,'area'),
+	antzoom(getfieldvalue(options,'area'));
+end
+
+%expdisp
+filename=(getfieldvalue(options,'expdisp'));
+style=(getfieldvalue(options,'expstyle'));
+for i=1:length(getfieldvalue(options,'expdisp')),
+	filenamei=filename{i};
+	stylei=style{i};
+	expdisp(filenamei,gcf,stylei,getfieldvalue(options,'linewidth',1),getfieldvalue(options,'unit',1));
+end
+
+%text (default value is empty, not NaN...)
+if exist(options,'text');
+	textstring=getfieldvalue(options,'text');
+	textweight=getfieldvalue(options,'textweight','b');
+	textsize=getfieldvalue(options,'textsize');
+	textcolor=getfieldvalue(options,'textcolor');
+	textposition=getfieldvalue(options,'textposition');
+	textrotation=getfieldvalue(options,'textrotation');
+	for i=1:length(getfieldvalue(options,'text'));
+		textstringi=textstring{i};
+		textweighti=textweight{i};
+		textsizei=textsize{i};
+		textcolori=textcolor{i};
+		textpositioni=textposition{i};
+		textrotationi=textrotation{i};
+		h=text(textpositioni(1),textpositioni(2),10,textstringi,'FontSize',textsizei,'FontWeight',textweighti,'Color',textcolori,'Rotation',textrotationi);
+		set(h,'Clipping','on'); %prevent text from appearing outside of the box
+	end
+end
+
+%north arrow
+if exist(options,'northarrow'),
+	northarrow(getfieldvalue(options,'northarrow'));
+end
+
+%Scale ruler
+if exist(options,'scaleruler'),
+	scaleruler(options);
+end
+
+%streamliness
+if exist(options,'streamlines'),
+	plot_streamlines(md,options);
+end
+
+%contours
+if exist(options,'contourlevels'),
+	plot_contour(md,data,options);
+end
+
+%YTickLabel
+if exist(options,'yticklabel'),
+	set(gca,'YTickLabel',getfieldvalue(options,'YTickLabel'));
+end
+
+%XTickLabel
+if exist(options,'xticklabel'),
+	set(gca,'XTickLabel',getfieldvalue(options,'XTickLabel'));
+end
+
+%xtick
+if exist(options,'xtick'),
+	set(gca,'xtick',getfieldvalue(options,'xtick'));
+end
+
+%ytick
+if exist(options,'ytick'),
+	set(gca,'ytick',getfieldvalue(options,'ytick'));
+end
+
+%Axis positions
+if exist(options,'offsetaxispos'),
+	offset=getfieldvalue(options,'offsetaxispos');
+	P=get(gca,'pos');
+	P(1)=P(1)+offset(1);
+	P(2)=P(2)+offset(2);
+	P(3)=P(3)+offset(3);
+	P(3)=P(4)+offset(4);
+	set(gca,'pos',P);
+end
+if exist(options,'axispos'),
+	Axis=getfieldvalue(options,'axispos');
+	hold on
+	set(gca,'pos',Axis);
+end
+
+
+%position of figure
+if exist(options,'figposition'),
+	
+	figposition=getfieldvalue(options,'figposition');
+	if ischar(figposition),
+		if strcmpi(figposition,'larour'),
+			set(gcf,'Position',[1604 4 1594 1177]);
+		elseif strcmpi(figposition,'larour2'),
+			set(gcf,'Position',[756    62   827   504]);
+		elseif strcmpi(figposition,'mathieu'),
+			set(gcf,'Position',[300 1 1580 1150]);
+		elseif strcmpi(figposition,'fullscreen'),
+			set(gcf,'Position',get(0,'ScreenSize'));
+		elseif strcmpi(figposition,'halfright'),
+			screen=get(0,'ScreenSize');
+			left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25;
+			set(gcf,'Position',fix([left+widt/2 bott widt/2 heig]));
+		elseif strcmpi(figposition,'halfleft'),
+			screen=get(0,'ScreenSize');
+			left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25;
+			set(gcf,'Position',fix([left bott widt/2 heig]));
+		elseif strcmpi(figposition,'square'),
+			screen=get(0,'ScreenSize');
+			left=screen(1); bott=screen(2); widt=min(screen(3)-25,screen(4)-25);
+			set(gcf,'Position',fix([left+(screen(3)-widt) bott widt widt]));
+		elseif strcmpi(figposition,'portrait'),
+			%reformat with letter paper size (8.5" x 11")
+			screen=get(0,'ScreenSize');
+			left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25;
+			portrait=fix([left+widt-(heig*8.5/11) bott heig*8.5/11 heig]);
+			set(gcf,'Position',portrait)
+		elseif strcmpi(figposition,'landscape'),
+			%reformat with letter paper size (8.5" x 11")
+			screen=get(0,'ScreenSize');
+			left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25;
+			landscape=fix([left+widt-(heig*11/8.5) bott heig*11/8.5 heig]);
+			set(gcf,'Position',landscape)
+		else
+			disp('''figposition'' string not supported yet');
+		end
+	else
+		set(gcf,'Position',figposition);
+	end
+
+end
+
+%axes position
+if exist(options,'axesPosition')
+	set(gca,'Position',getfieldvalue(options,'axesPosition'));
+end
+
+%showregion
+if strcmpi(getfieldvalue(options,'showregion','off'),'on'),
+	%Keep pointer of main axis
+	maingca=gca;
+	%get inset relative position (x,y,width,height)
+	insetpos=getfieldvalue(options,'insetpos',[0.02 0.70 0.18 0.18]);
+	%get current plos position
+	cplotpos=get(maingca,'pos');
+	%compute inset position
+	PosInset=[cplotpos(1)+insetpos(1)*cplotpos(3),cplotpos(2)+insetpos(2)*cplotpos(4), insetpos(3)*cplotpos(3), insetpos(4)*cplotpos(4)];
+	axes('pos',PosInset);
+	axis equal off
+	%box off
+	if strcmpi(md.mesh.hemisphere,'n') | strcmpi(md.mesh.hemisphere,'north'),
+		A=expread([ jplsvn() '/projects/Exp/GreenlandBoxFront.exp']);
+		[A.x A.y]=ll2xy(A.x,A.y,+1,45,70);
+		A.x = A.x(1:30:end);
+		A.y = A.y(1:30:end);
+	elseif strcmpi(md.mesh.hemisphere,'s') | strcmpi(md.mesh.hemisphere,'south'),
+		A=expread([ jplsvn() '/projects/Exp/Antarctica.exp']);
+	else
+		error('applyoptions error message: hemisphere not defined');
+	end
+	offset=3*10^4;
+	Ax=[min(A.x)-offset max(A.x)+offset];
+	Ay=[min(A.y)-offset max(A.y)+offset];
+	%if we are zooming on a basin, don't take the mesh for the boundaries!
+	if exist(options,'basin'),
+		[mdx mdy]=basinzoom(options);
+	else
+		mdx=[min(md.mesh.x)-offset max(md.mesh.x)+offset];
+		mdy=[min(md.mesh.y)-offset max(md.mesh.y)+offset];
+	end
+	line(A.x,A.y,ones(size(A.x)),'color','b');
+	patch([Ax(1)  Ax(2)  Ax(2)  Ax(1) Ax(1)],[Ay(1)  Ay(1)  Ay(2)  Ay(2) Ay(1)],[1 1 1],'EdgeColor',[0 0 0],'LineWidth',1,'FaceLighting','none')
+	patch([mdx(1) mdx(2) mdx(2) mdx(1)],[mdy(1) mdy(1) mdy(2) mdy(2)],ones(4,1),'EdgeColor',[0 0 0],'FaceColor','r','FaceAlpha',0.5)
+	colorbar('off');
+	%back to main gca
+	set(gcf,'CurrentAxes',maingca)
+end
+
+%flag edges of a partition
+if exist(options,'partitionedges')
+	[xsegments ysegments]=flagedges(md.mesh.elements,md.mesh.x,md.mesh.y,md.qmu.partition);
+	xsegments=xsegments*getfieldvalue(options,'unit',1);
+	ysegments=ysegments*getfieldvalue(options,'unit',1);
+	color=getfieldvalue(options,'partitionedgescolor','r-');
+	linewidth=getfieldvalue(options,'linewidth',1);
+	hold on;
+	for i=1:length(xsegments),
+		plot(xsegments(i,:),ysegments(i,:),color,'LineWidth',linewidth);
+	end
+end
+
+%Scatter
+if exist(options,'scatter')
+	data=getfieldvalue(options,'scatter');
+	hold on
+	plot_scatter(data(:,1),data(:,2),getfieldvalue(options,'scattersize',3),data(:,3),options);
+end
+
+%backgroundcolor
+set(gca,'color',getfieldvalue(options,'backgroundcolor','none'));
+
+%figurebackgrounbcolor
+set(gcf,'color',getfieldvalue(options,'figurebackgroundcolor','w'));
+
+%lighting
+if strcmpi(getfieldvalue(options,'light','off'),'on'),
+	set(gca,'FaceLighting','gouraud','FaceColor','interp','AmbientStrength',0.5);
+	light('Position',[0 0.1 0.1],'Style','infinite');
+end
+
+%cloud of points: 
+if exist(options,'cloud'),
+	field=getfieldvalue(options,'cloud');
+	x=field(:,1);
+	y=field(:,2);
+	%unit multiplier:
+	if exist(options,'unit'),
+		unit=getfieldvalue(options,'unit');
+		x=x*unit;
+		y=y*unit;
+	end
+	hold on,p=plot(x,y,'k.');
+	markersize=getfieldvalue(options,'markersize',5);
+	color=getfieldvalue(options,'cloudcolor','k');
+	set(p,'Color',color);
+end
+
+%========================%
+%OK VERY LAST STEP: INSET|
+%========================%
+if exist(options,'inset'),
+
+	%Keep pointer of main axis
+	maingca=gca;
+	%get inset relative position (x,y,width,height)
+	insetpos=getfieldvalue(options,'insetpos',[0.56 0.55 0.35 0.35]);
+	%get current plot position
+	cplotpos=get(gca,'pos');
+	%compute inset position
+	PosInset=[cplotpos(1)+insetpos(1)*cplotpos(3),cplotpos(2)+insetpos(2)*cplotpos(4), insetpos(3)*cplotpos(3), insetpos(4)*cplotpos(4)];
+	%show pos
+	X1=getfieldvalue(options,'insetx',xlim);
+	Y1=getfieldvalue(options,'insety',ylim);
+	if strcmpi(getfieldvalue(options,'showinset','off'),'on')
+		line(X1([1 2 2 1 1]),Y1([1 1 2 2 1]),zeros(1,5),'Color','k','LineWidth',2);
+	end
+
+	%Get current figure
+	ax1=gca;
+
+	%plot inset
+	axes('pos',PosInset);
+	copyobj(get(ax1,'children'),gca);
+	patch('Faces',[1 2 3 4 1],'Vertices',[X1([1 2 2 1])' Y1([1 1 2 2])'],'FaceColor','None','EdgeColor','k','LineWidth',2);
+
+	%applay options
+	options=removefield(options,'text',0);
+	options=removefield(options,'title',0);
+	options=removefield(options,'xlabel',0);
+	options=removefield(options,'ylabel',0);
+	options=removefield(options,'inset',0);
+	options=removefield(options,'offsetaxispos',0);
+	options=removefield(options,'showregion',0);
+	options=changefieldvalue(options,'colorbar',0);
+	options=changefieldvalue(options,'latlon','off');
+	options=changefieldvalue(options,'axis','equal off');
+	options=changefieldvalue(options,'xlim',getfieldvalue(options,'insetx',xlim));
+	options=changefieldvalue(options,'ylim',getfieldvalue(options,'insety',ylim));
+	applyoptions(md,data,options);
+
+	%back to main gca
+	set(gcf,'CurrentAxes',maingca)
+end
Index: /issm/trunk-jpl/src/m/plot/arrow.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/arrow.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/arrow.m	(revision 13009)
@@ -0,0 +1,60 @@
+function arrow(x0,y0,x1,y1,varargin)
+%ARROW - plot arrow, using (x0,y0) and (x1,y1) as initial and end points. options can be specified.
+%
+%   Usage:
+%      arrow(x1,y1,x2,y2,options)
+%      where options is a lit of paired arguments of string OR enums
+%      options can be: 
+%            'ratio': default .5 (ratio headarrow/length)
+%            'widthratio': default is 1/10 of length
+
+
+%recover options
+options=pairoptions(varargin{:});
+ratio=getfieldvalue(options,'ratio',.5);
+widthratio=getfieldvalue(options,'widthratio',.1);
+color=getfieldvalue(options,'color','k');
+
+%compute some values out of (x1,y1) and (x2,y2)
+length=sqrt((x1-x0)^2+(y1-y0)^2);
+width=length*widthratio;
+
+%Build the two points Ap and Bp
+x=zeros(2,1);
+y=zeros(2,1);
+x(1)=x0; y(1)=y0;
+x(2)=x1; y(2)=y1;
+
+Ap=[x(1)
+   y(1)];
+Bp=[x(2)
+   y(2)];
+
+%Build arrowhead first
+ang2=150*2*pi/360;
+rotation=[cos(ang2), sin(ang2); -sin(ang2), cos(ang2)];
+
+E=ratio*rotation*(Bp-Ap)+Bp;
+F=Bp;
+G=ratio*rotation'*(Bp-Ap)+Bp;
+H=Bp/4+E*3/8+G*3/8;
+
+%Build rectangle
+u=Bp-Ap;
+alpha=atan2(u(2),u(1));
+
+A=Ap-[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+ B=H-[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+C=H+[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+D=Ap+[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+
+%Plot arrow
+hold on
+p1=patch([A(1) B(1) C(1) D(1)],[A(2) B(2) C(2) D(2)],color);
+set(p1,'EdgeColor',color); set(p1,'FaceColor',color);
+p2=patch([E(1) F(1) G(1) H(1)],[E(2) F(2) G(2) H(2)],color);
+set(p2,'EdgeColor',color); set(p2,'FaceColor',color);
Index: /issm/trunk-jpl/src/m/plot/checkplotoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/checkplotoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/checkplotoptions.m	(revision 13009)
@@ -0,0 +1,206 @@
+function options=checkplotoptions(md,options);
+%PARSE_OPTIONS - build a structure that holds all plot options
+%
+%   Usage:
+%      options=checkplotoptions(md,options);
+%
+%   See also: PLOTMODEL
+
+%units
+if exist(options,'unit'),
+	if strcmpi(getfieldvalue(options,'unit'),'km')
+		options=changefieldvalue(options,'unit',10^-3);
+	end
+	if strcmpi(getfieldvalue(options,'unit'),'100km')
+		options=changefieldvalue(options,'unit',10^-5);
+	end
+
+end
+
+%density
+if exist(options,'density'),
+	density=getfieldvalue(options,'density');
+	options=changefieldvalue(options,'density',abs(ceil(density)));
+end
+
+%Show section
+if exist(options,'showsection'),
+	if strcmpi(getfieldvalue(options,'showsection'),'on')
+		options=changefieldvalue(options,'showsection',4);
+	end
+end
+
+%smooth values
+if exist(options,'smooth'),
+	if strcmpi(getfieldvalue(options,'smooth'),'on')
+		options=changefieldvalue(options,'smooth',0);
+	end
+end
+
+%contouronly values
+if exist(options,'contouronly'),
+	if strcmpi(getfieldvalue(options,'contouronly'),'on')
+		options=changefieldvalue(options,'contouronly',1);
+	end
+end
+
+%Colorbar;
+if exist(options,'colorbar'),
+	if strcmpi(getfieldvalue(options,'colorbar'),'on')
+		options=changefieldvalue(options,'colorbar',1);
+	elseif strcmpi(getfieldvalue(options,'colorbar'),'off')
+			options=changefieldvalue(options,'colorbar',0);
+	end
+end
+	
+%text
+if exist(options,'text'),
+	%1: textvalue
+	textvalues=getfieldvalue(options,'text');
+	%ischar if only one expstyle -> create a cell
+	if ischar(textvalues),
+		textvalues={textvalues};
+		numtext=1;
+	elseif iscell(textvalues),
+		numtext=length(textvalues);
+	else
+		error('plot error message: ''text'' option should be either a string or a cell');
+	end
+
+	%2: textweight
+	if exist(options,'textweight'),
+		textweightvalues=getfieldvalue(options,'textweight');
+		%ischar if only one textweight -> create a cell
+		if ischar(textweightvalues),
+			textweightvalues={textweightvalues};
+		elseif ~iscell(textweightvalues);
+			error('plot error message: ''textweight'' option should be either a string or a cell');
+		end
+	else
+		textweightvalues={'n'};
+	end
+	textweightvalues=repmat(textweightvalues,1,numtext); textweightvalues(numtext+1:end)=[];
+	%3: textsize
+	if exist(options,'textsize'),
+		textsizevalues=getfieldvalue(options,'textsize');
+		%ischar if only one textsize -> create a cell
+		if isnumeric(textsizevalues),
+			textsizevalues={textsizevalues};
+		elseif ~iscell(textsizevalues);
+			error('plot error message: ''textsize'' option should be either a number or a cell');
+		end
+	else
+		textsizevalues={14};
+	end
+	textsizevalues=repmat(textsizevalues,1,numtext); textsizevalues(numtext+1:end)=[];
+	%4: textcolor
+	if exist(options,'textcolor'),
+		textcolorvalues=getfieldvalue(options,'textcolor');
+		%ischar if only one textcolor -> create a cell
+		if ischar(textcolorvalues),
+			textcolorvalues={textcolorvalues};
+		elseif ~iscell(textcolorvalues);
+			error('plot error message: ''textcolor'' option should be either a string or a cell');
+		end
+	else
+		textcolorvalues={'k'};
+	end
+	textcolorvalues=repmat(textcolorvalues,1,numtext); textcolorvalues(numtext+1:end)=[];
+	%4: textposition
+	if exist(options,'textposition'),
+		textpositionvalues=getfieldvalue(options,'textposition');
+		%ischar if only one textposition -> create a cell
+		if isnumeric(textpositionvalues),
+			textpositionvalues={textpositionvalues};
+		elseif ~iscell(textpositionvalues);
+			error('plot error message: ''textposition'' option should be either a string or a cell');
+		end
+	else
+		error('plot error message: ''textposition'' option is missing');
+	end
+	%6: textrotation
+	if exist(options,'textrotation'),
+		textrotationvalues=getfieldvalue(options,'textrotation');
+		%ischar if only one textsize -> create a cell
+		if isnumeric(textrotationvalues),
+			textrotationvalues={textrotationvalues};
+		elseif ~iscell(textrotationvalues);
+			error('plot error message: ''textrotation'' option should be either a number or a cell');
+		end
+	else
+		textrotationvalues={0};
+	end
+	textrotationvalues=repmat(textrotationvalues,1,numtext); textrotationvalues(numtext+1:end)=[];
+	options=changefieldvalue(options,'text',textvalues);
+	options=changefieldvalue(options,'textsize',textsizevalues);
+	options=changefieldvalue(options,'textweight',textweightvalues);
+	options=changefieldvalue(options,'textcolor',textcolorvalues);
+	options=changefieldvalue(options,'textposition',textpositionvalues);
+	options=changefieldvalue(options,'textrotation',textrotationvalues);
+end
+
+%expdisp
+expdispvaluesarray=cell(0,0);
+expstylevaluesarray=cell(0,0);
+expstylevalues=cell(0,0);
+if exist(options,'expstyle'),
+	expstylevalues=getfieldvalue(options,'expstyle');
+	%ischar if only one expstyle -> create a cell
+	if ischar(expstylevalues),
+		expstylevalues={expstylevalues};
+	end
+end
+if exist(options,'expdisp'),
+	expdispvalues=getfieldvalue(options,'expdisp');
+	%ischar if only one expstyle -> create a cell
+	if ischar(expdispvalues),
+		expdispvalues={expdispvalues};
+	end
+	for i=1:length(expdispvalues)
+		expdispvaluesarray{end+1}=expdispvalues{i};
+		if (length(expstylevalues)>=i),
+			expstylevaluesarray{end+1}=expstylevalues{i};
+		else
+			expstylevaluesarray{end+1}='g-';
+		end
+	end
+end
+options=changefieldvalue(options,'expstyle',expstylevaluesarray);
+options=changefieldvalue(options,'expdisp',expdispvaluesarray);
+
+%latlonnumbering
+if exist(options,'latlonclick'),
+	if strcmpi(getfieldvalue(options,'latlonclick'),'on')
+		options=changefieldvalue(options,'latlonclick',1);
+	end
+end
+
+%north arrow
+if exist(options,'northarrow'),
+	if strcmpi(getfieldvalue(options,'northarrow'),'on')
+		%default values
+		Lx=max(md.mesh.y)-min(md.mesh.y);
+		Ly=max(md.mesh.y)-min(md.mesh.y);
+		%default values
+		options=changefieldvalue(options,'northarrow',[min(md.mesh.x)+1/6*Lx   min(md.mesh.y)+5/6*Ly   1/15*Ly   0.25   1/250*Ly]);
+	end
+end
+
+%scale ruler
+if exist(options,'scaleruler'),
+	if strcmpi(getfieldvalue(options,'scaleruler'),'on')
+		%default values
+		Lx=max(md.mesh.y)-min(md.mesh.y);
+		Ly=max(md.mesh.y)-min(md.mesh.y);
+		%default values
+		options=changefieldvalue(options,'scaleruler',[min(md.mesh.x)+6/8*Lx   min(md.mesh.y)+1/10*Ly   10^(ceil(log10(Lx)))/5 floor(Lx/100) 5]);
+	end
+end
+
+%Log scale (LOTS of changes to be performed
+if exist(options,'log'),
+	if exist(options,'caxis')
+		options=changefieldvalue(options,'caxis',log(getfieldvalue(options,'caxis'))/log(getfieldvalue(options,'log')));
+	end
+	options=changefieldvalue(options,'cutoff',log(getfieldvalue(options,'cutoff',1.5))/log(getfieldvalue(options,'log')));
+end
Index: /issm/trunk-jpl/src/m/plot/colormaps/getcolormap.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/colormaps/getcolormap.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/colormaps/getcolormap.m	(revision 13009)
@@ -0,0 +1,55 @@
+function map = getcolormap(options)
+%GETCOLORMAP - get colormap from options
+%
+%   Usage:
+%      map = getcolormap(options)
+
+%default is jet
+if ~exist(options,'colormap'),
+	map = jet;
+	return
+end
+
+map = getfieldvalue(options,'colormap');
+if isnumeric(map);
+	%user provided a full colormap
+	return;
+end
+
+%OK this is an in-house colormap
+if ~ischar(map), error('colormap format not supported'); end
+
+if strcmpi(map,'Ala'),
+	map = jet(256);
+	map = map(128:end,:);
+elseif strcmpi(map,'redblue'),
+	map = hsv(256);
+	map = rgb2hsv(map);
+	map(:,2)       = max(min( abs(map(:,1)-0.5)/0.5 ,1),0);
+	map(1:128,1)   = 0.7;
+	map(129:end,1) = 1;
+	map = hsv2rgb(map);
+elseif strcmpi(map,'Rignot'),
+	alpha=getfieldvalue(options,'alpha',1);
+	map = hsv(256);
+	map = rgb2hsv(map);
+	map(:,2) = max(min( (0.1+map(:,1)).^(1/alpha) ,1),0);
+	map = hsv2rgb(map);
+elseif strcmpi(map,'Rignot2'),
+	alpha=getfieldvalue(options,'alpha',1);
+	map = hsv(256);
+	map = rgb2hsv(map);
+	map(:,2) = max(min( (0.1+map(:,1)).^(1/alpha) ,1),0);
+	map = hsv2rgb(map);
+	map=flipud(map);
+elseif strcmpi(map,'Seroussi'),
+	alpha=getfieldvalue(options,'alpha',1);
+	map = hsv(256);
+	map = flipud(map);
+	map = map(1:floor(0.7*size(map,1)),:);
+	map = rgb2hsv(map);
+	map(:,2) = max(min( (0.1+map(:,1)).^(1/alpha) ,1),0);
+	map = hsv2rgb(map);
+else
+	eval(['map = ' map ';']);
+end
Index: /issm/trunk-jpl/src/m/plot/colormaps/haxby.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/colormaps/haxby.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/colormaps/haxby.m	(revision 13009)
@@ -0,0 +1,36 @@
+function map = haxby(m);
+%HAXBY - Haxby color map
+%   HAXBY(M) returns an M-by-3 matrix containing a colormap with Haxby's
+%   colors, commonly used for displaying bathymetry data.
+%   HAXBY, by itself, is the same length as the current colormap.
+%
+%   Colormap is based on the colors used by W. F. Haxby's Gravity
+%   field of World's oceans, 1985, developed for geoid and gravity maps.
+%   The version used here is formed from a linear interpolation of
+%   the GMT color table used by MB-System by David W. Caress and Dale N. Chayes.
+%   <http://www.ldeo.columbia.edu/res/pi/MB-System>
+
+if nargin < 1, m = size(get(gcf,'colormap'),1); end
+
+ncolors=11;
+c=[...
+	37     57   175
+	40    127   251
+	50    190   255
+	106   235   255
+	138   236   174
+	205   255   162
+	240   236   121
+	255   189    87
+	255   161    68
+	255   186   133
+	255   255   255];
+
+pp=1:(m-1)/(ncolors-1):m;
+r=interp1(pp,c(:,1),1:m);
+g=interp1(pp,c(:,2),1:m);
+b=interp1(pp,c(:,3),1:m);
+map=[r' g' b']/255;
+
+%Fix bug of interp1 (M. Morlighem)
+map(find(map>1))=1;
Index: /issm/trunk-jpl/src/m/plot/colormaps/lbmap.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/colormaps/lbmap.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/colormaps/lbmap.m	(revision 13009)
@@ -0,0 +1,109 @@
+function map = lbmap(n,scheme)
+%LBMAP Returns specified Light-Bertlein colormap.
+%
+%   LBMAP(N,SCHEME) returns an Nx3 colormap. SCHEME can be one of the
+%   following strings:
+%
+%       'Blue'       Single-hue progression to purlish-blue (default)
+%       'BlueGray'   Diverging progression from blue to gray
+%       'BrownBlue'  Orange-white-purple diverging scheme
+%       'RedBlue'    Modified spectral scheme
+%
+%   If N is not specified, the size of the colormap is determined by the
+%   current figure. If no figure exists, MATLAB creates one.
+%
+%Example 1: 7-color single-hue blue (default)
+%   load penny
+%   imagesc(P)
+%   colormap(lbmap(7))
+%   colorbar
+%
+%Example 2: 11-color modified spectrum
+%   load penny
+%   imagesc(P)
+%   colormap(lbmap(11,'RedBlue'))
+%   colorbar
+%
+%   See also HSV, GRAY, HOT, BONE, COPPER, PINK, FLAG, COLORMAP, RGBPLOT.
+
+% Reference:
+% A. Light & P.J. Bartlein, "The End of the Rainbow? Color Schemes for
+% Improved Data Graphics," Eos,Vol. 85, No. 40, 5 October 2004.
+% http://geography.uoregon.edu/datagraphics/EOS/Light&Bartlein_EOS2004.pdf
+
+% Copyright 2007-2010 The MathWorks, Inc.
+
+%defensive programming
+error(nargchk(0,2,nargin))
+error(nargoutchk(0,1,nargout))
+
+%defaults
+if nargin<2
+	scheme = 'Blue';
+end
+if nargin<1
+	n = size(get(gcf,'colormap'),1);
+end
+
+%valid schemes
+switch lower(scheme)
+	case 'blue'
+		baseMap = BlueMap;
+	case 'bluegray'
+		baseMap = BlueGrayMap;
+	case 'brownblue'
+		baseMap = BrownBlueMap;
+	case 'redblue'
+		baseMap = RedBlueMap;
+	otherwise
+		error(['Invalid scheme ' scheme])
+	end
+	idx1 = linspace(0,1,size(baseMap,1));
+	idx2 = linspace(0,1,n);
+	map = interp1(idx1,baseMap,idx2);
+
+function baseMap = BlueMap
+	baseMap = [243 246 248;
+	224 232 240;
+	171 209 236;
+	115 180 224;
+	35 157 213;
+	0 142 205;
+	0 122 192]/255;
+
+function baseMap = BlueGrayMap
+	%DivergingBlueGray
+	baseMap = [  0 170 227;
+	53 196 238;
+	133 212 234;
+	190 230 242;
+	217 224 230;
+	146 161 170;
+	109 122 129;
+	65  79  81]/255;
+
+function baseMap = BrownBlueMap
+	baseMap = [144 100  44;
+	187 120  54;
+	225 146  65;
+	248 184 139;
+	244 218 200;
+	241 244 245;
+	207 226 240;
+	160 190 225;
+	109 153 206;
+	70  99 174;
+	24  79 162]/255;
+
+function baseMap = RedBlueMap
+	baseMap = [175  53  71;
+	216  82  88;
+	239 133 122;
+	245 177 139;
+	249 216 168;
+	242 238 197;
+	216 236 241;
+	154 217 238;
+	68 199 239;
+	0 170 226;
+	0 116 188]/255;
Index: /issm/trunk-jpl/src/m/plot/imagescnan.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/imagescnan.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/imagescnan.m	(revision 13009)
@@ -0,0 +1,303 @@
+function [h,hcb] = imagescnan(x,y,U,varargin)
+%IMAGESCNAN Scale data and display as image with uncolored NaNs.
+%
+%   Syntax
+%               imagescnan(x,y,U)
+%               imagescnan(x,y,U,...,colormask)
+%               imagescnan(x,y,U,...,color)
+%               imagescnan(x,y,U,...,cbfit_opt)
+%           h = imagescnan(...);
+%     [h,hcb] = imagescnan(...,cbfit_opt);
+%
+%   Input:
+%     x          - X-axis vector data. Optional, i.e., can be empty.
+%                  Default: 1:n (rows index).
+%     y          - Y-axis vector data. Optional, i.e., can be empty.
+%                  Default: 1:m (column index).
+%     U          - Matrix [m x n] data or an RGB image [m x n x 3] (with/
+%                  without NaNs). 
+%     colormask  - Logical matrix indicating the U elements to be
+%                  uncolored, if is empty then ISNAN(U) is used. Or it can
+%                  be a single value which will be uncolored.
+%                  Default: ~isfinite(U) (NaNs and Infs elements uncolored)
+%     color      - A vector with 3 elements specifying the [R G B] color
+%                  for the NaNs color. It can be specified by the known
+%                  char colors: 'k', etcerera. Optional.  
+%                  Default: get(gca,'color') (axes background color)
+%     cbfit_opt  - Cell array with the options to call COLORBARFIT.
+%                  Default: COLORBARFIT function is not used by default.
+%
+%   Output:
+%     h   - Image handle. Optional
+%     hcb - Colorbar handle. Optional
+%
+%   Description:
+%      This function draws a matrix data as an image with uncolored NaN's
+%      elements using IMAGESC. The difference between IMAGESC and the
+%      PCOLOR, MESH or SURF function is that EVERY element is colored and
+%      no one is interpolated, besides, the pixels are centered with the
+%      axis value, although it is a flat image.
+%
+%      The color mask is added because IMAGESC do not work with NaN's, in
+%      fact it colors them with the lower value of the current colormap.
+%      
+%      The cbfit_opt is include in order to be able to define a diferent
+%      color map with the COLORBARFIT function which can be found at:
+%           http://www.mathworks.com/matlabcentral/fileexchange/.
+%      If this function is not found, a normal COLORBAR is generated.
+%
+%      The data and the colorbar are scaled with the current colormap, so,
+%      the use of COLORMAP after this function doesn't affects the
+%      generated image and colorbar! Therefore, COLORMAP and CAXIS should
+%      be used before this function.
+%
+%      Notes: * The inputs arguments for the COLORBARFIT function are 3
+%               plus the normal COLORBAR function options, for this reason,
+%               if the former is not found, the latter is used ignoring
+%               these first 3 options. Anyway, to generate a colorbar, at
+%               least an empty cell is needed for cbfit_opt = {[]}.
+%   
+%   Examples:
+%
+%      % Compares with normal IMAGESC:
+%       N = 100;
+%       PNaNs = 0.10;
+%       X = peaks(N);
+%       X(round(1 + (N^2-1).*rand(N^2*PNaNs,1))) = NaN;
+%       subplot(221), imagesc(X)
+%        title('With IMAGESC: ugly NaNs')
+%       subplot(222), imagescnan([],[],X) 
+%        title('With IMAGESCNAN: uncolored NaNs')
+%
+%      % Compares with SPY:
+%       subplot(223), spy(isnan(X))
+%        title('SPY NaNs')
+%       subplot(224), imagescnan([],[],isnan(X),0), axis equal tight
+%        title('No-NaNs with IMAGESCNAN')
+%
+%   See also IMAGE, IMAGESC, COLORBAR, IMREAD, IMWRITE and COLORBARFIT by
+%   Carlos Vargas. 
+
+%   Copyright 2008 Carlos Adrian Vargas Aguilera
+%   $Revision: 1.1 $  $Date: 2009/04/03 22:56:05 $
+
+%   Written by
+%   M.S. Carlos Adrian Vargas Aguilera
+%   Physical Oceanography PhD candidate
+%   CICESE 
+%   Mexico, 2008
+%   nubeobscura@hotmail.com
+%
+%   Download from:
+%   http://www.mathworks.com/matlabcentral/fileexchange/loadAuthor.do?objec
+%   tType=author&objectId=1093874
+
+%   1.0     Released (30/06/2008)
+%   1.1     Fixed bug when CAXIS used.
+%   1.2     Colorbar freezed colormap.
+%   1.3     Fixed bug in color vector input (Found by Greg King) and now
+%           accets RGB image as input.
+
+%% INPUTS:
+
+% Error checking:
+% Note: At least 3 inputs and no more than 6:
+if nargin<3 || nargin>6
+ error('Imagescnan:IncorrectInputNumber',...
+       'Input arguments must be at least 3 and less than 7.')
+end
+
+% Check the x,y,U:
+% Note: x,y should be the axes data.
+m = size(U);
+if numel(m)>3
+ error('Imagescnan:IncorrectInputSize',...
+       'Input image must be a matrix or an RGB image.')
+else
+ if isempty(x) || numel(x)~=m(2)
+  %warning('Imagescnan:IncorrectInputSize',...
+  %        'Index column axis has been used.')
+  x = 1:m(2); 
+ end
+ if isempty(y) || numel(y)~=m(1)
+  %warning('Imagescnan:IncorrectInputSize',...
+  %        'Index row axis has been used.')
+  y = 1:m(1); 
+ end
+end
+
+% Get color limits:
+% Note: If you would like to use specific color limits, use CAXIS before
+%       this function.
+switch get(gca,'CLimMode')
+ case 'manual'
+  clim = caxis;
+ otherwise
+  clim = [min(U(:)) max(U(:))];
+end
+
+% Parse inputs and defaults:
+% Note: * Mask color will be the not-finite elements plus the elements
+%         indicated by the user.
+%       * Default colormask is the current axes background.
+%       * Default currentmap is current figure colormap (probably JET).
+colormask = ~isfinite(U);
+color_nan = get(gca,'color');
+color_map = get(gcf,'colormap'); 
+cbfit_opt = [];
+ycolorbarfit = (exist('colorbarfit','file')==2);
+if nargin>3
+ while ~isempty(varargin)
+  if     iscell(varargin{1})
+   if length(varargin{1})<3
+    error('Imagescnan:IncorrectInputType',...
+     'Options for COLORBARFIT must be at least 3, although empty.')
+   end
+   caxis(clim)
+   cbfit_opt = varargin{1};
+   if ycolorbarfit
+    colorbarfit(cbfit_opt{:})
+    color_map = get(gcf,'colormap');
+   else
+    % warning('Imagescnan:ColorBarFitNotFound',...
+    %  'COLORBARFIT function not found, used default COLORBAR.') 
+   end
+   varargin(1) = [];
+  elseif ischar(varargin{1})
+   switch varargin{1}
+    case 'y', color_nan = [1 1 0];
+    case 'm', color_nan = [1 0 0];
+    case 'c', color_nan = [0 1 1];
+    case 'r', color_nan = [1 0 0];
+    case 'g', color_nan = [0 1 0];
+    case 'b', color_nan = [0 0 1];
+    case 'w', color_nan = [1 1 1];
+    case 'k', color_nan = [0 0 0];
+   otherwise
+   error('Imagescnan:InvalidColor',...
+    'Color char must be one of: ''ymcrgbwk''.')
+   end
+   varargin(1) = [];
+  elseif islogical(varargin{1})
+   if numel(varargin{1})~=numel(U)
+    error('Imagescnan:InvalidMask',...
+     'The logical mask must have the same elements as the matrix.')
+   end
+   colormask = varargin{1} | colormask;
+   varargin(1) = [];
+  elseif length(varargin{1})==3
+   if (max(varargin{1})>1) || (min(varargin{1})<0) % Fixed BUG 2008/07/11
+    error('Imagescnan:InvalidColor',...
+     'The color must be on the range of [0 1].')
+   end
+   color_nan = varargin{1};
+   varargin(1) = [];
+  elseif length(varargin{1})==1
+   colormask = (U==varargin{1}) | colormask;
+   varargin(1) = [];
+  else
+   error('Imagescnan:IncorrectInputType',...
+    'Incorrect optional(s) argument(s).')
+  end
+ end
+end
+
+
+%% MAIN:
+
+% Matrix data to RGB:
+if numel(m)==2
+
+ % Sets to double data:
+ if ~isfloat(U)
+  U = double(U);
+ end
+
+ % Normalizes and rounds data to range [0 N]:
+ N = size(color_map,1);
+ U = (U - clim(1))/diff(clim);          % Fixed bug when CAXIS used
+ U = U*N;
+ if N<=256
+  U = uint8(U);
+ else
+  U = uint16(U);
+ end
+
+ % Scales data with colormap:
+ U = ind2rgb(U,color_map);              % 2D to 3D RGB values [0 1]
+else
+ % Already is an RGB image, so do nothing.
+end
+
+ % Set mask color to color_nan:
+ mn = prod(m(1:2));
+ ind = find(colormask);
+ U(ind)      = color_nan(1); % Red color
+ U(ind+mn)   = color_nan(2); % Green color
+ U(ind+mn*2) = color_nan(3); % Blue color
+
+ % Draws the RGB image:
+ h = imagesc(x,y,U,clim);
+
+%% OUTPUTS:
+
+% Calls to colorbarfit and freezes his colormap:
+if ~isempty(cbfit_opt)
+ % Creates a temporary colorbar:
+ if ycolorbarfit
+  hcb   = colorbarfit(cbfit_opt{:});
+ else
+  Nopt = min([3 length(cbfit_opt)]);
+  cbfit_opt(1:Nopt) = [];
+  hcb   = colorbar(cbfit_opt{:});
+ end
+ % Save image position:
+ ha    = gca; position = get(ha,'Position'); 
+ % Gets colorbar axes properties:
+ ghcb  = get(hcb);
+ CData = ind2rgb(get(ghcb.Children,'CData'),color_map);
+ XData = get(ghcb.Children,'XData');
+ YData = get(ghcb.Children,'YData');
+ % Move ticks because IMAGESC draws them like centered pixels:
+ XTick = ghcb.XTick;
+ YTick = ghcb.YTick;
+ if ~isempty(XTick)
+  XTick = XTick(1:end-1) + diff(XTick(1:2))/2;
+ end
+ if ~isempty(YTick)
+  YTick = YTick(1:end-1) + diff(YTick(1:2))/2;
+ end
+ % Deletes the colorbar:
+ delete(hcb)            
+ % Generates other colorbar:
+ hcb = axes('Position',ghcb.Position);
+ hcbim = imagesc(XTick,YTick,CData,'Parent',hcb); axis tight
+ set(hcbim,...
+  'HitTest','off',...
+  'Interruptible','off',...
+  'SelectionHighlight','off',...
+  'Tag','TMW_COLORBAR',...
+  'XData',XData,...
+  'YData',YData)
+ set(hcb,...
+  'XAxisLocation',ghcb.XAxisLocation,...
+  'YAxisLocation',ghcb.YAxisLocation,...
+  'XLim',ghcb.XLim,...
+  'YLim',ghcb.YLim,...
+  'XDir',ghcb.XDir,...
+  'YDir',ghcb.YDir,...
+  'XTick',ghcb.XTick,...
+  'YTick',ghcb.YTick,...
+  'XTickLabel',ghcb.XTickLabel,...
+  'YTickLabel',ghcb.YTickLabel,...
+  'ButtonDownFcn',@resetCurrentAxes,...
+  'Interruptible','off',...
+  'Tag','Colorbar')
+ % Returns the image position:
+ axes(ha), set(ha,'Position',position)
+end
+
+% Sets output:
+if ~nargout
+ clear h
+end
Index: /issm/trunk-jpl/src/m/plot/kmlgroundoverlay.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/kmlgroundoverlay.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/kmlgroundoverlay.m	(revision 13009)
@@ -0,0 +1,61 @@
+function kmlgroundoverlay(md,options);
+%KMLGROUNDOVERLAY: create ground overlay image in kml format
+%
+%
+%    options: 
+%         kmlfilename
+%         imagename
+%
+%    Usage: 
+%         kmlgroundoverlay(md,'kmlfilename','temp.kml','imagename','greenland.jpeg');
+%
+
+%first figure out if lat and long were computed!
+if (isempty(md.mesh.lat) | isempty(md.mesh.long)),
+	error('kmlgroundoverlay error message: project x,y onto lat,long fields of model!');
+end
+
+%process kml options
+kmlfilename=getfieldvalue(options,'kmlfilename','tempfile.kml');
+kmlroot=getfieldvalue(options,'kmlroot','./');
+kmlimagename=getfieldvalue(options,'kmlimagename','tempimage');
+kmlimagetype=getfieldvalue(options,'kmlimagetype','png');
+kmlresolution=getfieldvalue(options,'kmlresolution',1);
+kmlfolder=getfieldvalue(options,'kmlfolder','Ground Overlay');
+kmlfolderdescription=getfieldvalue(options,'kmlfolderdescription','');
+kmlgroundoverlayname=getfieldvalue(options,'kmlgroundoverlayname','');
+kmlgroundoverlaydescription=getfieldvalue(options,'kmlgroundoverlaydescription','');
+
+%figure out  min and max for lat and long of this image:
+west=min(md.mesh.long);
+east=max(md.mesh.long);
+south=min(md.mesh.lat);
+north=max(md.mesh.lat);
+
+%print image at high resolution
+printmodel([kmlroot '/' kmlimagename],kmlimagetype,'trim','on','resolution',kmlresolution,'margin','off','frame','off');
+
+%now write kml file
+fid=fopen([kmlroot '/' kmlfilename],'w');
+
+fprintf(fid,'%s\n','<?xml version="1.0" encoding="UTF-8"?>');
+fprintf(fid,'%s\n','<kml xmlns="http://www.opengis.net/kml/2.2">');
+fprintf(fid,'%s\n','<Folder>');
+fprintf(fid,'%s%s%s\n','<name>',kmlfolder,'</name>');
+fprintf(fid,'%s%s%s\n','<description>',kmlfolderdescription,'</description>');
+fprintf(fid,'%s\n','<GroundOverlay>');
+fprintf(fid,'%s%s%s\n','<name>',kmlgroundoverlayname,'</name>');
+fprintf(fid,'%s\n','<description>',kmlgroundoverlaydescription,'</description>');
+fprintf(fid,'%s%s.%s%s\n','<Icon>',kmlimagename,kmlimagetype,'</Icon>');
+fprintf(fid,'%s\n','<LatLonBox>');
+fprintf(fid,'%s%f%s\n','<north>',north,'</north>');
+fprintf(fid,'%s%f%s\n','<south>',south,'</south>');
+fprintf(fid,'%s%f%s\n','<east>',east,'</east>');
+fprintf(fid,'%s%f%s\n','<west>',west,'</west>');
+fprintf(fid,'%s\n','<rotation>0</rotation>');
+fprintf(fid,'%s\n','</LatLonBox>');
+fprintf(fid,'%s\n','</GroundOverlay>');
+fprintf(fid,'%s\n','</Folder>');
+fprintf(fid,'%s\n','</kml>');
+
+fclose(fid);
Index: /issm/trunk-jpl/src/m/plot/latlonoverlay.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/latlonoverlay.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/latlonoverlay.m	(revision 13009)
@@ -0,0 +1,149 @@
+function latlonoverlay(md,options)
+%LATLONOVERLAY - overlay latitude and longitude lines on current figure
+%
+%   latstep,lonstep, in latitude and longitude degreees, between two latitudinal, longitudinal profiles.
+%   color: [1 1 1] for example
+%   resolution: profile resolution ( in lat,lon degrees) 
+%   gap: gap (in meters) to plug lat,lon degree numbers;
+%
+%   Usage:
+%      latlonoverlay(options)
+
+%get options
+latlon=getfieldvalue(options,'latlon');
+numbering=getfieldvalue(options,'latlonnumbering','off');
+latlonclick=getfieldvalue(options,'latlonclick',0);
+fontsize=getfieldvalue(options,'fontsize',16);
+
+%recover arguments (set default parameters if needed)
+%1: latlon
+if ~iscell(latlon),
+	if ischar(latlon) & strcmpi(latlon,'on'),
+		%defaults
+		latstep=3; lonstep=3;
+		resolution=0.1;
+		color=[1 0 1];
+	else return; end
+else
+	if length(latlon)<2
+		error('latlonoverlay error message: at least 2 arguments are required, or use ''on'' option.');
+	end
+	if length(latlon)>3, color=latlon{4};      else color=[1 1 1]; end
+	if length(latlon)>2, resolution=latlon{3}; else resolution=0.1;end
+	latstep=latlon{1};
+	lonstep=latlon{2};
+end
+
+%2: numbering
+if ~iscell(numbering) & isnan(numbering),
+	numbering=false;
+else
+	if ~iscell(numbering),
+		if strcmpi(char(numbering),'on'),
+			%defaults
+			latgap=2; longap=2;
+			colornumber=color;
+			latangle=0; lonangle=0;
+			numbering=true;
+		else
+			numbering=false;
+		end
+	else
+		latgap=numbering{1}; longap=numbering{2};
+		colornumber=numbering{3};
+		latangle=numbering{4}; lonangle=numbering{5};
+		numbering=true;
+	end
+end
+
+%what are the x and y limits
+xlimits=getfieldvalue(options,'xlim',xlim);
+ylimits=getfieldvalue(options,'ylim',ylim);
+
+%lat
+for lat=-90:latstep:90
+	longitudes=0:resolution:360;
+	latitudes =lat*ones(size(longitudes));
+
+	if strcmpi(md.mesh.hemisphere,'n'),
+		if lat<0, continue; end
+		[x,y]=ll2xy(latitudes,longitudes,+1,45,70);
+	elseif strcmpi(md.mesh.hemisphere,'s'),
+		if lat>0, continue; end
+		[x,y]=ll2xy(latitudes,longitudes,-1, 0,71);
+	else error('field hemisphere should either be ''n'' or ''s'''); end
+
+	pos=find(x<=xlimits(2) & x>=xlimits(1) & y<=ylimits(2) & y>=ylimits(1));
+	if length(pos)<=1, continue; end
+	x=x(pos);y=y(pos);
+	l=line(x,y,'Color',color);
+
+	if numbering
+		ind=length(x)-2*latgap;
+		if (ind<=0), continue; end
+		xcorner=x(ind);            ycorner=y(ind);
+		xcorner2=x(max(ind-10,1)); ycorner2=y(max(ind-10,1));
+
+		if (xcorner>xlimits(1) & xcorner<xlimits(2) & ycorner>ylimits(1) & ycorner<ylimits(2)),
+			angle=mod((180)/pi*atan2((ycorner2-ycorner),(xcorner2-xcorner))+latangle,360);
+			if lat<0, label=[num2str(abs(lat)) '^{\circ}S'];
+			else      label=[num2str(abs(lat)) '^{\circ}N']; end
+			th=text(xcorner,ycorner,label);
+			set(th,'Color',colornumber,'Rotation',angle,'FontSize',fontsize,'HorizontalAlignment','center','VerticalAlignment','middle','Clipping','on');
+
+			%erase line and redraw it in two parts, to leave space for latitude number
+			delete(l);
+			line(x(1:ind-latgap),y(1:ind-latgap),'Color',color);hold on;
+			line(x(ind+latgap:end),y(ind+latgap:end),'Color',color);
+			set(gcf,'InvertHardcopy','off');
+		end
+
+	end
+end
+
+%lon
+for lon=-180:lonstep:180
+
+	if strcmpi(md.mesh.hemisphere,'n'),
+		latitudes =0:resolution:90;
+		longitudes=lon*ones(size(latitudes));
+		[x,y]=ll2xy(latitudes,longitudes,+1,45,70);
+	elseif strcmpi(md.mesh.hemisphere,'s'),
+		latitudes =-90:resolution:0;
+		longitudes=lon*ones(size(latitudes));
+		[x,y]=ll2xy(latitudes,longitudes,-1, 0,71);
+	else
+		error('field hemisphere should either be ''n'' or ''s'''); 
+	end
+
+
+	pos=find(x<=xlimits(2) & x>=xlimits(1) & y<=ylimits(2) & y>=ylimits(1));
+	if length(pos)<=1, continue; end
+	x=x(pos);y=y(pos);
+	l=line(x,y,'Color',color);
+
+	if numbering,
+		ind=length(x)-2*longap;
+		if (ind<=0), continue; end
+		xcorner=x(ind);            ycorner=y(ind);
+		xcorner2=x(max(ind-10,1)); ycorner2=y(max(ind-10,1));
+
+		if (xcorner>xlimits(1) & xcorner<xlimits(2) & ycorner>ylimits(1) & ycorner<ylimits(2)),
+			angle=mod((180)/pi*atan2((ycorner2-ycorner),(xcorner2-xcorner))+lonangle,360);
+			if lon<0, label=[num2str(abs(lon)) '^{\circ}W'];
+			else      label=[num2str(abs(lon)) '^{\circ}E']; end
+			th=text(xcorner,ycorner,label);
+			set(th,'Color',colornumber,'Rotation',angle,'FontSize',fontsize,'HorizontalAlignment','center','VerticalAlignment','middle','Clipping','on');
+
+			%erase line and redraw it in two parts, to leave space for latitude number
+			delete(l);
+			line(x(1:ind-longap),y(1:ind-longap),'Color',color);hold on;
+			line(x(ind+longap:end),y(ind+longap:end),'Color',color);
+		end
+
+	end
+end
+
+%Back to original limits
+xlim(xlimits);
+ylim(ylimits);
Index: /issm/trunk-jpl/src/m/plot/northarrow.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/northarrow.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/northarrow.m	(revision 13009)
@@ -0,0 +1,76 @@
+function northarrow(structure)
+%NORTHARROW - overlay an arrow pointing north on the current plot
+%
+%   Usage:
+%      northarrow(structure)
+
+%Go through structure and fill missing arguments
+if length(structure)<3
+	error('plotmodel error message: the position or the length of the North arrow is missing');
+elseif length(structure)==3
+	structure(4)=0.5; %default ratio headarrow/length
+	structure(5)=structure(3)/10; %default width =length/10
+elseif length(structure)==4
+	structure(5)=structure(3)/10; %default width =length/10
+elseif length(structure)==5
+	structure(6)=16; %default fontsize
+elseif length(structure)>6
+	error('plotmodel error message: to many input arguments for northarrow: [x0 y0 length [ratio width fontsize]]');
+end
+
+%retrieve north arrow parameters
+x0=structure(1);
+y0=structure(2);
+lengtharrow=structure(3);
+ratio=structure(4);
+width=structure(5);
+fontsize=structure(6);
+
+%Figure out angle to point towards north
+ang=atan2(y0,x0);
+
+%Build the two points Ap and Bp
+x=zeros(2,1);
+y=zeros(2,1);
+x(1)=x0;
+y(1)=y0;
+
+x(2)=x(1)+lengtharrow*cos(ang);
+y(2)=y(1)+lengtharrow*sin(ang);
+
+Ap=[x(1)
+   y(1)];
+Bp=[x(2)
+   y(2)];
+
+%Build arrowhead first
+ang2=150*2*pi/360;
+rotation=[cos(ang2), sin(ang2); -sin(ang2), cos(ang2)];
+
+E=ratio*rotation*(Bp-Ap)+Bp;
+F=Bp;
+G=ratio*rotation'*(Bp-Ap)+Bp;
+H=Bp/4+E*3/8+G*3/8;
+
+%Build rectangle
+u=Bp-Ap;
+alpha=atan2(u(2),u(1));
+
+A=Ap-[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+ B=H-[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+C=H+[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+D=Ap+[-width/2*sin(alpha)
+   width/2*cos(alpha)];
+
+%Plot arrow
+hold on
+p1=patch([A(1) B(1) C(1) D(1)],[A(2) B(2) C(2) D(2)],'Black');
+p2=patch([E(1) F(1) G(1) H(1)],[E(2) F(2) G(2) H(2)],'Black');
+
+%Text North
+xN=max([A(1) D(1) E(1) F(1) G(1)])+ratio/3*abs(lengtharrow);
+yN=mean([A(2) F(2) H(2)]);
+text(xN,yN,'North','FontSize',fontsize,'FontWeight','b');
Index: /issm/trunk-jpl/src/m/plot/plot_BC.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_BC.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_BC.m	(revision 13009)
@@ -0,0 +1,41 @@
+function plot_BC(md,options,width,i,data);
+
+%plot neuman
+plot_icefront(md,options,width,i,data)
+
+hold on
+
+%plot dirichlets
+h1=plot3(...
+	md.mesh.x(find(~isnan(md.diagnostic.spcvx(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.y(find(~isnan(md.diagnostic.spcvx(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.z(find(~isnan(md.diagnostic.spcvx(1:md.mesh.numberofvertices,1)))),...
+	'ro','MarkerSize',14,'MarkerFaceColor','r');
+h2=plot3(...
+	md.mesh.x(find(~isnan(md.diagnostic.spcvy(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.y(find(~isnan(md.diagnostic.spcvy(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.z(find(~isnan(md.diagnostic.spcvy(1:md.mesh.numberofvertices,1)))),...
+	'bo','MarkerSize',10,'MarkerFaceColor','b');
+h3=plot3(...
+	md.mesh.x(find(~isnan(md.diagnostic.spcvz(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.y(find(~isnan(md.diagnostic.spcvz(1:md.mesh.numberofvertices,1)))),...
+	md.mesh.z(find(~isnan(md.diagnostic.spcvz(1:md.mesh.numberofvertices,1)))),...
+	'yo','MarkerSize',6 ,'MarkerFaceColor','y');
+
+%update legend
+[legend_h,object_h,plot_h,text_strings]=legend();
+legend('off');
+text_strings{end+1}='vx Dirichlet';
+text_strings{end+1}='vy Dirichlet';
+if h3, text_strings{end+1}='vz Dirichlet'; end
+plot_h(end+1)=h1;
+plot_h(end+1)=h2;
+if h3, plot_h(end+1)=h3; end
+legend(plot_h,text_strings,'location','NorthEast')
+
+hold off
+
+%apply options
+options=addfielddefault(options,'title','Boundary conditions');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_basaldrag.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_basaldrag.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_basaldrag.m	(revision 13009)
@@ -0,0 +1,53 @@
+function plot_basaldrag(md,options,width,i,type);
+
+%PLOT_BASALDRAG - plot basal drag
+%
+%   Usage:
+%      plot_basaldrag(md,options,width,i,type);
+%
+%   See also: PLOTMODEL
+
+%check layer
+if md.mesh.dimension==3,
+	if getfieldvalue(options,'layer',1)~=1;
+		disp('plot_basaldrag warning: basal drag is displayed in the lower layer')
+		changefieldvalue(options,'layer',1);
+	end
+end
+
+%compute exponents
+s=averaging(md,1./md.friction.p,0);
+r=averaging(md,md.friction.q./md.friction.p,0);
+
+%compute horizontal velocity
+if strcmpi(type,'basal_drag')
+	ub=sqrt(md.initialization.vx.^2+md.initialization.vy.^2)/md.constants.yts;
+elseif strcmpi(type,'basal_dragx')
+	ub=md.initialization.vx/md.constants.yts;
+elseif strcmpi(type,'basal_dragy')
+	ub=md.initialization.vy/md.constants.yts;
+end
+
+%compute basal drag
+drag=(max(md.constants.g*(md.materials.rho_ice*md.geometry.thickness+md.materials.rho_water*md.geometry.bed),0)).^r.*(md.friction.coefficient).^2.*ub.^s/1000;
+
+%Figure out if this is a Section plot
+if exist(options,'sectionvalue')
+	plot_section(md,drag,options,width,i);
+	return;
+else
+
+	%process data and model
+	[x y z elements is2d isplanet]=processmesh(md,[],options);
+	[basal_drag datatype]=processdata(md,drag,options);
+
+	%plot basaldrag
+	subplot(width,width,i); 
+	plot_unit(x,y,z,elements,basal_drag,is2d,isplanet,datatype,options);
+
+	%apply options
+	options=addfielddefault(options,'title','Basal drag [kPa]');
+	options=addfielddefault(options,'view',2);
+	applyoptions(md,basal_drag,options);
+
+end
Index: /issm/trunk-jpl/src/m/plot/plot_boundaries.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_boundaries.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_boundaries.m	(revision 13009)
@@ -0,0 +1,39 @@
+function plot_boundaries(md,options,width,i);
+%PLOT_BOUNDARIES - plot mesh boundaries
+%
+%   Usage:
+%      plot_boundaries(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+subplot(width,width,i); 
+
+%process data and model
+if getfieldvalue(options,'layer',0)
+	options=removefield(options,'layer',1);
+end
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+for i=1:size(md.mesh.segments,1),
+	plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-');hold on;
+end
+
+%plot rifts if present: 
+if isstruct(md.rifts.riftstruct),
+	for i=1:size(md.rifts.riftstruct,1),
+		segments=md.rifts.riftstruct(i).segments;
+		for j=1:size(segments,1),
+			plot(x(segments(j,1:2)),y(segments(j,1:2)),'r.-');
+		end
+		text(x(segments(floor(size(segments,1)/4),1)),y(segments(floor(size(segments,1)/4),1)),['Rift #' num2str(i)]);
+		%point out the tips
+		plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'b*');
+		plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'b*');
+	end
+end
+
+%apply options
+options=addfielddefault(options,'title','Mesh boundaries');
+options=addfielddefault(options,'colorbar',0);
+options=addfielddefault(options,'view',2);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_contour.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_contour.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_contour.m	(revision 13009)
@@ -0,0 +1,245 @@
+function plot_contour(md,datain,options);
+%PLOT_CONTOUR - plot contours of a given field
+%
+%   Usage:
+%      plot_contour(md,data,options);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z index is2d isplanet]=processmesh(md,[],options);
+options=removefield(options,'log',0);
+[data datatype]=processdata(md,datain,options);
+
+%check is2d
+if ~is2d,
+	error('plot_contour error message: contour not supported for 3d meshes, project on a layer');
+end
+
+%first, process data: must be on nodes
+if datatype==1,
+	%elements -> take average
+	data=averaging(md,data,0);
+elseif datatype==2,
+	%nodes -> do nothing
+elseif datatype==3,
+	%quiver -> take norm
+	data=sqrt(sum(datain.*datain,2));
+else
+	error('datatype not supported yet');
+end
+
+%prepare colors
+if exist(options,'contouronly')
+	%remove the previous plots
+	cla
+end
+color=getfieldvalue(options,'contourcolor','y');
+linewidth=getfieldvalue(options,'linewidth',1);
+
+%get contours levels
+contourlevels=getfieldvalue(options,'contourlevels');
+if isnumeric(contourlevels),
+	levels=round_ice(linspace(max(data),min(data),contourlevels),2);
+else
+	levels=[];
+	for i=1:length(contourlevels)
+		levels(end+1)=contourlevels{i};
+	end
+	levels=sort(unique(levels),'descend');
+end
+numlevels=length(levels);
+
+%initialization of some variables
+numberofelements=size(index,1);
+elementslist=1:numberofelements;
+c=[];
+h=[];
+
+%get unique edges in mesh
+%1: list of edges
+edges=[index(:,[1,2]); index(:,[2,3]); index(:,[3,1])];
+%2: find unique edges
+[edges,I,J]=unique(sort(edges,2),'rows');
+%3: unique edge numbers
+vec=J;
+%4: unique edges numbers in each triangle (2 triangles sharing the same edge will have
+%   the same edge number)
+edges_tria=[vec(elementslist), vec(elementslist+numberofelements), vec(elementslist+2*numberofelements)];
+
+%segments [nodes1 nodes2]
+Seg1=index(:,[1 2]);
+Seg2=index(:,[2 3]);
+Seg3=index(:,[3 1]);
+
+%segment numbers [1;4;6;...]
+Seg1_num=edges_tria(:,1);
+Seg2_num=edges_tria(:,2);
+Seg3_num=edges_tria(:,3);
+
+%value of data on each tips of the segments
+Data1=data(Seg1);
+Data2=data(Seg2);
+Data3=data(Seg3);
+
+%get the ranges for each segment
+Range1=sort(Data1,2);
+Range2=sort(Data2,2);
+Range3=sort(Data3,2);
+
+for i=1:numlevels
+
+	level=levels(i);
+
+	%find the segments that contain this value
+	pos1=(Range1(:,1)<level & Range1(:,2)>level);
+	pos2=(Range2(:,1)<level & Range2(:,2)>level);
+	pos3=(Range3(:,1)<level & Range3(:,2)>level);
+
+	%get elements
+	poselem12=(pos1 & pos2);
+	poselem13=(pos1 & pos3);
+	poselem23=(pos2 & pos3);
+	poselem=find(poselem12 | poselem13 | poselem23);
+	numelems=length(poselem);
+
+	%if no element has been flagged, skip to the next level
+	if numelems==0,
+		continue,
+	end
+
+	%go through the elements and build the coordinates for each segment (1 by element)
+	x1=zeros(numelems,1);
+	x2=zeros(numelems,1);
+	y1=zeros(numelems,1);
+	y2=zeros(numelems,1);
+	edge_l=zeros(numelems,2);
+
+	for j=1:numelems,
+
+		weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1));
+		weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1));
+		weight3=(level-Data3(poselem(j),1))/(Data3(poselem(j),2)-Data3(poselem(j),1));
+
+		if poselem12(poselem(j));
+
+			x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1)));
+			x2(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1)));
+			y1(j)=y(Seg1(poselem(j),1))+weight1*(y(Seg1(poselem(j),2))-y(Seg1(poselem(j),1)));
+			y2(j)=y(Seg2(poselem(j),1))+weight2*(y(Seg2(poselem(j),2))-y(Seg2(poselem(j),1)));
+			edge_l(j,1)=Seg1_num(poselem(j));
+			edge_l(j,2)=Seg2_num(poselem(j));
+
+		elseif poselem13(poselem(j)),
+
+			x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1)));
+			x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1)));
+			y1(j)=y(Seg1(poselem(j),1))+weight1*(y(Seg1(poselem(j),2))-y(Seg1(poselem(j),1)));
+			y2(j)=y(Seg3(poselem(j),1))+weight3*(y(Seg3(poselem(j),2))-y(Seg3(poselem(j),1)));
+			edge_l(j,1)=Seg1_num(poselem(j));
+			edge_l(j,2)=Seg3_num(poselem(j));
+
+		elseif poselem23(poselem(j)),
+
+			x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1)));
+			x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1)));
+			y1(j)=y(Seg2(poselem(j),1))+weight2*(y(Seg2(poselem(j),2))-y(Seg2(poselem(j),1)));
+			y2(j)=y(Seg3(poselem(j),1))+weight3*(y(Seg3(poselem(j),2))-y(Seg3(poselem(j),1)));
+			edge_l(j,1)=Seg2_num(poselem(j));
+			edge_l(j,2)=Seg3_num(poselem(j));
+		else
+			%it shoud not go here
+		end
+	end
+
+	%now that we have the segments, we must try to connect them...
+
+	%loop over the subcontours
+	while ~isempty(edge_l),
+
+		%take the right edge of the second segment and connect it to the next segments if any
+		e1=edge_l(1,1);   e2=edge_l(1,2);
+		xc=[x1(1);x2(1)]; yc=[y1(1);y2(1)];
+
+		%erase the lines corresponding to this edge
+		edge_l(1,:)=[];
+		x1(1)=[]; x2(1)=[];
+		y1(1)=[]; y2(1)=[];
+
+		[ro1,co1]=find(edge_l==e1);
+
+		while ~isempty(ro1)
+
+			if co1==1,
+				xc=[x2(ro1);xc]; yc=[y2(ro1);yc];
+
+				%next edge:
+				e1=edge_l(ro1,2);
+
+			else
+				xc=[x1(ro1);xc]; yc=[y1(ro1);yc];
+
+				%next edge:
+				e1=edge_l(ro1,1);
+			end
+
+			%erase the lines of this
+			edge_l(ro1,:)=[];
+			x1(ro1)=[]; x2(ro1)=[];
+			y1(ro1)=[]; y2(ro1)=[];
+
+			%next connection
+			[ro1,co1]=find(edge_l==e1);
+		end
+
+		%same thing the other way (to the right)
+		[ro2,co2]=find(edge_l==e2);
+
+		while ~isempty(ro2)
+
+			if co2==1,
+				xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)];
+
+				%next edge:
+				e2=edge_l(ro2,2);
+			else
+				xc=[xc;x1(ro2)]; yc=[yc;y1(ro2)];
+
+				%next edge:
+				e2=edge_l(ro2,1);
+			end
+
+			%erase the lines of this
+			edge_l(ro2,:)=[];
+			x1(ro2)=[]; x2(ro2)=[];
+			y1(ro2)=[]; y2(ro2)=[];
+
+			%next connection
+			[ro2,co2]=find(edge_l==e2);
+		end
+
+		%we now have one subcontour ready to be plotted
+		zc=level*ones(length(xc)+1,1);
+		if getfieldvalue(options,'contouronly',0),
+			h=[h;patch('Xdata',[xc;NaN],'Ydata',[yc;NaN],'Zdata',zc,'Cdata',zc,'facecolor','none','edgecolor','flat','linewidth',linewidth)];
+			hold on      
+		else
+			h=[h;patch('Xdata',[xc;NaN],'Ydata',[yc;NaN],'facecolor','none','edgecolor',color,'linewidth',linewidth)];
+			hold on
+		end
+
+		% Update the CS data structure as per "contours.m"
+		% so that clabel works
+		c = horzcat(c,[level, xc'; length(xc), yc']);
+
+	end
+end
+
+%labels?
+if (~strcmpi(getfieldvalue(options,'contourticks','on'),'off') & ~isempty(c) & ~isempty(h))
+	if exist(options,'contouronly')
+		clabel(c,h);
+	else
+		clabel(c,h,'color',color,'FontSize',14);
+	end
+end
Index: /issm/trunk-jpl/src/m/plot/plot_drivingstress.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_drivingstress.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_drivingstress.m	(revision 13009)
@@ -0,0 +1,24 @@
+function plot_drivingstress(md,options,width,i);
+%PLOT_DRIVINGSTRESS - plot driving stress
+%
+%   Usage:
+%      plot_drivingstress(md,options,width,i);
+%
+%   See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
+
+%get driving stress
+[sx sy s]=drivingstress(md);
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[dstress datatype]=processdata(md,s,options);
+dstress=dstress/1000;
+
+%plot mesh quivervel
+subplot(width,width,i); 
+plot_unit(x,y,z,elements,dstress,is2d,isplanet,datatype,options)
+
+%apply options
+options=addfielddefault(options,'title','Driving stress [kPa]');
+options=addfielddefault(options,'view',2);
+applyoptions(md,dstress,options);
Index: /issm/trunk-jpl/src/m/plot/plot_edges.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_edges.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_edges.m	(revision 13009)
@@ -0,0 +1,34 @@
+function plot_edges(md,options,width,i,datai);
+%PLOT_SEGMENTS - plot edges, with different colors according to segment markers.
+%
+%   Usage:
+%      plot_edges(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh boundaries
+subplot(width,width,i); 
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+edges=md.mesh.edges;
+if isnan(edges)
+	error('edges in NaN')
+end
+
+if (md.mesh.dimension==2),
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	h1=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+	text(sum(x(edges(:,1:2)),2)/2,sum(y(edges(:,1:2)),2)/2,sum(z(edges(:,1:2)),2)/2,...
+		num2str(transpose(1:size(edges,1))),...
+		'backgroundcolor',[0.8 0.9 0.8],'HorizontalAlignment','center','VerticalAlignment','middle');
+else
+	error('plot_edges: 3d plot of edges not supported yet!');
+end
+
+%apply options
+options=addfielddefault(options,'title','Edges');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_elementnumbering.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_elementnumbering.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_elementnumbering.m	(revision 13009)
@@ -0,0 +1,57 @@
+function plot_elementnumbering(md,options,width,i);
+%PLOT_ELEMENTNUMBERING - plot element numbering
+%
+%   Usage:
+%      plot_elementnumbering(md,options,width,i);
+%
+%   See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
+
+subplot(width,width,i); 
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[elementnumbers datatype]=processdata(md,[1:md.mesh.numberofelements]',options);
+
+%plot
+if is2d
+	%plot mesh 
+	A=elements(:,1); B=elements(:,2); C=elements(:,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+
+	%numbering
+	text(sum(x(elements(:,1:3)),2)/3,sum(y(elements(:,1:3)),2)/3,sum(z(elements(:,1:3)),2)/3,...
+		num2str(transpose(1:size(elements,1))),...
+		'HorizontalAlignment','center','VerticalAlignment','middle');
+else
+	%plot mesh 
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3);
+	patch( 'Faces', [A B C],  'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','none','EdgeColor','black');
+
+	%numbering
+	text(sum(x(elements(:,1:6)),2)/6,sum(y(elements(:,1:6)),2)/6,sum(z(elements(:,1:6)),2)/6,...
+		num2str(transpose(1:size(elements,1))),...
+		'HorizontalAlignment','center','VerticalAlignment','middle');
+end
+
+%apply options
+options=addfielddefault(options,'title','Element numbering');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_elementstype.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_elementstype.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_elementstype.m	(revision 13009)
@@ -0,0 +1,131 @@
+function plot_elementstype(md,options,width,i);
+%PLOT_ELEMENTSTYPE - plot elements type
+%
+%   Usage:
+%      plot_elementstype(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[data datatype]=processdata(md,md.flowequation.element_equation,options);
+
+%edgecolor?
+edgecolor=getfieldvalue(options,'edgecolor','none');
+
+%plot
+subplot(width,width,i);
+
+if is2d
+	%Hutter elements
+	posH=find(data==1);
+	A=elements(posH,1); B=elements(posH,2); C=elements(posH,3); 
+	p1=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',1,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyeal element
+	posM=find(data==2);
+	A=elements(posM,1); B=elements(posM,2); C=elements(posM,3); 
+	p2=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',2,'FaceColor','flat','EdgeColor',edgecolor);
+	%Pattyn element
+	posP=find(data==3);
+	A=elements(posP,1); B=elements(posP,2); C=elements(posP,3); 
+	p3=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',3,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyealPattyn element
+	posMP=find(data==5);
+	A=elements(posMP,1); B=elements(posMP,2); C=elements(posMP,3); 
+	p5=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',5,'FaceColor','flat','EdgeColor',edgecolor);
+	%Stokes elements
+	posS=find(data==4);
+	A=elements(posS,1); B=elements(posS,2); C=elements(posS,3); 
+	p6=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',4,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyealStokes elements
+	posMS=find(data==6);
+	A=elements(posMS,1); B=elements(posMS,2); C=elements(posMS,3); 
+	p7=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',6,'FaceColor','flat','EdgeColor',edgecolor);
+	%PattynStokes elements
+	posPS=find(data==7);
+	A=elements(posPS,1); B=elements(posPS,2); C=elements(posPS,3); 
+	p8=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',7,'FaceColor','flat','EdgeColor',edgecolor);
+	%None elements
+	posNONE=find(data==0);
+	A=elements(posNONE,1); B=elements(posNONE,2); C=elements(posNONE,3); 
+	p9=patch( 'Faces', [A B C], 'Vertices', [x y z],'CData',0,'FaceColor','flat','EdgeColor',edgecolor);
+
+	legend([p1 p2 p3 p5 p6 p7 p8 p9],...
+		'Hutter''s elements','MacAyeal''s elements','Pattyn''s elements',...
+		'MacAyealPattyn''s elements','Stokes''s elements','MacAyealStokes''s elements','PattynStokes''s elements','None element');
+
+else
+	%Hutter elements
+	posH=find(data==1);
+	A=elements(posH,1); B=elements(posH,2); C=elements(posH,3); D=elements(posH,4); E=elements(posH,5); F=elements(posH,6);
+	p1=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 1,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 1,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 1,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 1,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 1,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyeal elements
+	posM=find(data==2);
+	A=elements(posM,1); B=elements(posM,2); C=elements(posM,3); D=elements(posM,4); E=elements(posM,5); F=elements(posM,6);
+	p2=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 2,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 2,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 2,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 2,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 2,'FaceColor','flat','EdgeColor',edgecolor);
+	%Pattyn elements
+	posP=find(data==3);
+	A=elements(posP,1); B=elements(posP,2); C=elements(posP,3); D=elements(posP,4); E=elements(posP,5); F=elements(posP,6);
+	p3=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 3,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 3,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 3,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 3,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 3,'FaceColor','flat','EdgeColor',edgecolor);
+	%Stokes elements
+	posS=find(data==4);
+	A=elements(posS,1); B=elements(posS,2); C=elements(posS,3); D=elements(posS,4); E=elements(posS,5); F=elements(posS,6);
+	p4=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 4,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 4,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 4,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 4,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 4,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyealPattyn elements
+	posP=find(data==5);
+	A=elements(posP,1); B=elements(posP,2); C=elements(posP,3); D=elements(posP,4); E=elements(posP,5); F=elements(posP,6);
+	p5=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 5,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 5,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 5,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 5,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 5,'FaceColor','flat','EdgeColor',edgecolor);
+	%PattynStokes elements
+	PosPS=find(data==7);
+	A=elements(PosPS,1); B=elements(PosPS,2); C=elements(PosPS,3); D=elements(PosPS,4); E=elements(PosPS,5); F=elements(PosPS,6);
+	p6=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 7,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 7,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 7,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 7,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 7,'FaceColor','flat','EdgeColor',edgecolor);
+	%MacAyealStokes elements
+	PosMS=find(data==6);
+	A=elements(PosMS,1); B=elements(PosMS,2); C=elements(PosMS,3); D=elements(PosMS,4); E=elements(PosMS,5); F=elements(PosMS,6);
+	p7=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 6,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 6,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 6,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 6,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 6,'FaceColor','flat','EdgeColor',edgecolor);
+	%None elements
+	PosNONE=find(data==0);
+	A=elements(PosNONE,1); B=elements(PosNONE,2); C=elements(PosNONE,3); D=elements(PosNONE,4); E=elements(PosNONE,5); F=elements(PosNONE,6);
+	p8=patch( 'Faces', [A B C],'Vertices', [x y z],'CData', 0,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', 0,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', 0,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', 0,'FaceColor','flat','EdgeColor',edgecolor);
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', 0,'FaceColor','flat','EdgeColor',edgecolor);
+
+	legend([p1 p2 p3 p4 p5 p6 p7 p8],...
+		'Hutter''s elements','MacAyeal''s elements','Pattyn''s elements','Stokes''s elements',...
+		'MacAyealPattyn''s elements','PattynStokes''s elements','MacAyealStokes''s elements','None elements');
+end
+
+%apply options
+options=addfielddefault(options,'title','Elements type');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_gridded.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_gridded.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_gridded.m	(revision 13009)
@@ -0,0 +1,64 @@
+function plot_gridded(md,data,options,plotlines,plotcols,i)
+%PLOT_OVERLAY - superimpose radar image to a given field
+%
+%   Usage:
+%      plot_gridded(md,options,plotlines,plotcols,i)
+%
+%   See also: PLOTMODEL
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[data datatype]=processdata(md,data,options);
+
+%check is2d
+if ~is2d, 
+	error('buildgridded error message: gridded not supported for 3d meshes, project on a layer');
+end
+
+%Get xlim and ylim (used to extract radar image)
+xlim=getfieldvalue(options,'xlim',[min(x) max(x)]);
+ylim=getfieldvalue(options,'ylim',[min(y) max(y)]);
+post=getfieldvalue(options,'posting',diff(xlim)/1000);
+
+%Interpolating data on grid
+[x_m y_m data_grid]=InterpFromMeshToGrid(elements,x,y,data,xlim(1),ylim(2),post,post,round(diff(ylim)/post),round(diff(xlim)/post),NaN);
+if size(data_grid,1)<3 | size(data_grid,2)<3,
+	error('data_grid size too small in plot_gridded, check posting and uni');
+end
+
+%Get and change colormap
+map    = getcolormap(options);
+lenmap = size(map,1);
+map    = [1 1 1; map];
+options=changefieldvalue(options,'colormap',map);
+
+%Process data_grid: add white in NaN and correct caxis accordingly
+if exist(options,'caxis'),
+	caxis_opt=getfieldvalue(options,'caxis');
+	data_grid(find(data_grid<caxis_opt(1)))=caxis_opt(1);
+	data_grid(find(data_grid>caxis_opt(2)))=caxis_opt(2);
+	data_min=caxis_opt(1);
+	data_max=caxis_opt(2);
+else
+	data_min=min(data_grid(:));
+	data_max=max(data_grid(:));
+end
+options = changefieldvalue(options,'cbYLim',[data_min data_max]);
+white   = data_min - (data_max-data_min)/(lenmap);
+options = changefieldvalue(options,'caxis',[white data_max]);
+data_grid(isnan(data_grid))=white;
+
+%Select plot area 
+subplotmodel(plotlines,plotcols,i,options);
+
+%shading interp;
+h=imagesc(xlim,ylim,data_grid);set(gca,'YDir','normal');
+
+%last step: mesh gridded?
+if exist(options,'edgecolor'),
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data_grid(1)*ones(size(x)),'FaceColor','none','EdgeColor',getfieldvalue(options,'edgecolor'));
+end
+
+%Apply options
+applyoptions(md,data,options);
Index: /issm/trunk-jpl/src/m/plot/plot_highlightelements.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_highlightelements.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_highlightelements.m	(revision 13009)
@@ -0,0 +1,51 @@
+function plot_highlightelements(md,options,width,i);
+%PLOT_HIGHLIGHTELEMENTS - plot selected elements
+%
+%   Usage:
+%      plot_highlightelements(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh boundaries
+subplot(width,width,i); 
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[elementnumbers datatype]=processdata(md,[1:md.mesh.numberofelements]',options);
+
+%plot
+if is2d
+	%plot mesh 
+	A=elements(:,1); B=elements(:,2); C=elements(:,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+else
+	%plot mesh 
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	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],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [0.9 0.5 0.5],'FaceColor','flat','EdgeColor','black');
+end
+
+%apply options
+if ~exist(options,'highlight')
+	disp('highlightelements warning : highlight option empty, not element highlighted');
+end
+options=addfielddefault(options,'title','Highlighted Elements');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_highlightvertices.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_highlightvertices.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_highlightvertices.m	(revision 13009)
@@ -0,0 +1,46 @@
+function plot_highlightvertices(md,options,width,i);
+%PLOT_HIGHLIGHTVERTICES - plot selected vertices
+%
+%   Usage:
+%      plot_highlightvertices(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[nodenumbers datatype]=processdata(md,[1:md.mesh.numberofvertices]',options);
+
+%plot
+subplot(width,width,i); 
+
+if is2d
+	%plot mesh 
+	A=elements(:,1); B=elements(:,2); C=elements(:,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	text(x(pos),y(pos),z(pos),num2str(transpose(pos)),...
+		'backgroundcolor',[1 0 0],'HorizontalAlignment','center','VerticalAlignment','middle');
+else
+	%plot mesh 
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	text(x(pos),y(pos),z(pos),num2str(transpose(pos)),...
+		'backgroundcolor',[1 0 0],'HorizontalAlignment','center','VerticalAlignment','middle');
+end
+
+%apply options
+if ~exist(options,'highlight')
+	disp('highlightvertices warning : highlight option empty, not node highlighted');
+end
+options=addfielddefault(options,'title','Highlighted Nodes');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_icefront.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_icefront.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_icefront.m	(revision 13009)
@@ -0,0 +1,106 @@
+function plot_icefront(md,options,width,i,data);
+%PLOT_ICEFRONT - plot segment on neumann BC
+%
+%   Usage:
+%      plot_icefront(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh boundaries
+subplot(width,width,i); 
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+icefront=md.diagnostic.icefront;
+
+if (md.mesh.dimension==2),
+
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	h1=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+
+	%highlight elements on neumann
+	pos=find(icefront(:,end)==1);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); 
+	h2=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	pos=find(icefront(:,end)==0);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); 
+	h3=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+
+	pos=find(icefront(:,end)==2);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); 
+	h3bis=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+
+	%display arrows pointing outward
+	xstart=mean(x(icefront(:,1:end-2)),2);
+	ystart=mean(y(icefront(:,1:end-2)),2);
+	length=sqrt((x(icefront(:,1))-x(icefront(:,2))).^2 + (y(icefront(:,1))-y(icefront(:,2))).^2 );
+	normal(:,1)=cos(atan2((x(icefront(:,1))-x(icefront(:,2))) , (y(icefront(:,2))-y(icefront(:,1)))));
+	normal(:,2)=sin(atan2((x(icefront(:,1))-x(icefront(:,2))) , (y(icefront(:,2))-y(icefront(:,1)))));
+	xend=xstart+length.*normal(:,1);
+	yend=ystart+length.*normal(:,2);
+	q=quiver(xstart,ystart,xend-xstart,yend-ystart); hold on;
+	h4=plot(xstart,ystart,'r*');
+else
+
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); D=elements(:,4); E=elements(:,5); F=elements(:,6);
+	h1=patch( 'Faces', [A B C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+
+	%highlight elements on neumann
+	pos=find(icefront(:,end)==1);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); D=elements(pos,4); E=elements(pos,5); F=elements(pos,6);
+	h2=patch( 'Faces', [A B C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','blue','EdgeColor','black');
+	pos=find(icefront(:,end)==0);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); D=elements(pos,4); E=elements(pos,5); F=elements(pos,6);
+	h3=patch( 'Faces', [A B C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+	pos=find(icefront(:,end)==2);
+	pos=icefront(pos,end-1);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); D=elements(pos,4); E=elements(pos,5); F=elements(pos,6);
+	h3bis=patch( 'Faces', [A B C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','cyan','EdgeColor','black');
+
+	%display arrows pointing outward
+	xstart=mean(x(icefront(:,1:end-2)),2);
+	ystart=mean(y(icefront(:,1:end-2)),2);
+	zstart=mean(z(icefront(:,1:end-2)),2);
+	length=sqrt((x(icefront(:,1))-x(icefront(:,2))).^2 + (y(icefront(:,1))-y(icefront(:,2))).^2 );
+	normal(:,1)=cos(atan2((x(icefront(:,1))-x(icefront(:,2))) , (y(icefront(:,2))-y(icefront(:,1)))));
+	normal(:,2)=sin(atan2((x(icefront(:,1))-x(icefront(:,2))) , (y(icefront(:,2))-y(icefront(:,1)))));
+	xend=xstart+length.*normal(:,1);
+	yend=ystart+length.*normal(:,2);
+	q=quiver3(xstart,ystart,zstart,xend-xstart,yend-ystart,zeros(numel(xstart),1)); hold on;
+	h4=plot3(xstart,ystart,zstart,'r*');
+end
+
+%legend (disable warnings)
+warning off
+legend([h2,h3,h3bis,q],'element on ice front (Water)','element on ice front (Air)','element on ice front (Ice)','normal vectors')
+warning on
+
+%apply options
+options=addfielddefault(options,'title','Neumann boundary conditions');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_importancefactors.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_importancefactors.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_importancefactors.m	(revision 13009)
@@ -0,0 +1,83 @@
+function plot_importancefactors(md,options,width,ii);
+%PLOT_IMPORTANCEFACTORS - plot importance factors
+%
+%   Usage:
+%      plot_importancefactors(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%first recover design variable descriptor
+if exist(options,'designvariable'),
+	descriptor=getfieldvalue(options,'designvariable');
+else
+	error('plot_importancefactors error message: Need to supply design variable descriptor');
+end
+descriptorlength=length(descriptor);
+
+%then recover responsfunction name
+if exist(options,'responsefunction'),
+	responsefunctiondescriptor=getfieldvalue(options,'responsefunction');
+else
+	error('plot_importancefactors error message: Need to supply response function descriptor');
+end
+
+%go through all response functions and find the one corresponding to the correct responsefunctiondescriptor
+responsefunctions=md.qmu.results{2};
+found=0;
+for i=1:length(responsefunctions),
+	if strcmpi(responsefunctions(i).descriptor,responsefunctiondescriptor),
+		found=i;
+		break;
+	end
+end
+if ~found,
+	error('plot_importancefactors error message: could not find correct response function');
+end
+responsefunctions=responsefunctions(found);
+nfun=size(responsefunctions.desvar,1);
+
+%Now recover response to the correct desgin variable
+importancefactors=zeros(md.qmu.numberofpartitions,1);
+count=0;
+for i=1:nfun,
+	desvar=responsefunctions.desvar{i};
+	if strncmpi(desvar,descriptor,descriptorlength),
+		count=count+1;
+		importancefactors(count)=responsefunctions.impfac(i);
+	end
+end
+if count==0,
+	error('plot_importancefactors error message: could not find to response functions with corresponding design variable');
+end
+
+%log?
+if exist(options,'log'),
+	logvalue=getfieldvalue(options,'log');
+	importancefactors=log(importancefactors)/log(logvalue);
+end
+
+%Ok, get partitioning.
+[epart npart]=MeshPartition(md,md.qmu.numberofpartitions);
+
+%distribute importance factor
+nodeimportance=importancefactors(npart);
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%edgecolor
+edgecolor=getfieldvalue(options,'edgecolor','none');
+
+%standard plot:
+subplot(width,width,ii);
+
+%ok, plot nodeimportance now.
+if is2d,
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', nodeimportance,'FaceColor','interp','EdgeColor',edgecolor);
+else
+	error('plot_importancefactors error message: 3d meshes not supported yet');
+end
+
+%apply options
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_manager.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_manager.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_manager.m	(revision 13009)
@@ -0,0 +1,204 @@
+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. 
+options=checkplotoptions(md,options);
+
+%get data to be displayed
+data=getfieldvalue(options,'data');
+
+%figure out if this is a special plot
+if ischar(data),
+
+	switch data,
+
+		case 'boundaries',
+			plot_boundaries(md,options,subplotwidth,i);
+			return;
+		case 'BC',
+			plot_BC(md,options,subplotwidth,i,data);
+			return;
+		case 'edges'
+			plot_edges(md,options,subplotwidth,i,data)
+			return
+		case 'elementnumbering',
+			plot_elementnumbering(md,options,subplotwidth,i);
+			return;
+		case 'highlightelements',
+			plot_highlightelements(md,options,subplotwidth,i);
+			return;
+		
+		case 'qmumean',
+			plot_qmumean(md,options,nlines,ncols,i);
+			return;
+		
+		case 'qmustddev',
+			plot_qmustddev(md,options,nlines,ncols,i);
+			return;
+		
+		case 'qmuhistnorm',
+			plot_qmuhistnorm(md,options,nlines,ncols,i);
+			return;
+
+		case 'qmu_mass_flux_segments',
+			plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
+			return;
+
+		case 'part_hist',
+			plot_parthist(md,options,nlines,ncols,i);
+			return;
+		case 'part_hist_n',
+			plot_parthistn(md,options,nlines,ncols,i);
+			return;
+		case 'part_hist_w',
+			plot_parthistw(md,options,nlines,ncols,i);
+			return;
+		case 'elements_type',
+			plot_elementstype(md,options,subplotwidth,i);
+			return;
+		case 'vertexnumbering',
+			plot_vertexnumbering(md,options,subplotwidth,i);
+			return;
+		case 'highlightvertices',
+			plot_highlightvertices(md,options,subplotwidth,i);
+			return;
+		case {'basal_drag','basal_dragx','basal_dragy'},
+			plot_basaldrag(md,options,subplotwidth,i,data);
+			return;
+		case 'driving_stress',
+			plot_drivingstress(md,options,subplotwidth,i);
+			return;
+		case 'mesh',
+			plot_mesh(md,options,nlines,ncols,i);
+			return;
+		case 'none',
+			if ~exist(options,'overlay'),
+				plot_none(md,options,nlines,ncols,i);
+				return;
+			end
+		case 'penalties',
+			plot_penalties(md,options,subplotwidth,i);
+			return;
+		case 'partition',
+			plot_partition(md,options,nlines,ncols,i);
+			return;
+		case 'referential',
+			plot_referential(md,options,nlines,ncols,i);
+			return;
+		case 'riftvel',
+			plot_riftvel(md,options,nlines,ncols,i);
+			return;
+		case 'riftnumbering',
+			plot_riftnumbering(md,options,nlines,ncols,i);
+			return;
+		case 'rifts',
+			plot_rifts(md,options,nlines,ncols,i);
+			return;
+		case 'riftrelvel',
+			plot_riftrelvel(md,options,nlines,ncols,i);
+			return;
+		case 'riftpenetration',
+			plot_riftpenetration(md,options,nlines,ncols,i);
+			return;
+		case 'riftfraction',
+			plot_riftfraction(md,options,nlines,ncols,i);
+			return;
+		case 'sarpwr',
+			plot_sarpwr(md,options,subplotwidth,i)
+			return
+		case 'icefront'
+			plot_icefront(md,options,subplotwidth,i,data)
+			return
+		case 'segments'
+			plot_segments(md,options,subplotwidth,i,data)
+			return
+		
+		case 'quiver'
+			data=[md.initialization.vx md.initialization.vy]; %Go ahead and try plot_unit
+
+		case {'strainrate_tensor','strainrate','strainrate_principal','strainrate_principalaxis1','strainrate_principalaxis2','strainrate_principalaxis3',...
+				'stress_tensor','stress','stress_principal','stress_principalaxis1','stress_principalaxis2','stress_principalaxis3',...
+				'deviatoricstress_tensor','deviatoricstress','deviatoricstress_principal','deviatoricstress_principalaxis1','deviatoricstress_principalaxis2','deviatoricstress_principalaxis3'},
+			plot_tensor(md,options,subplotwidth,i,data);
+			return;
+		case 'thermaltransient_results',
+			plot_thermaltransient_results(md,options,subplotwidth,i);
+			return;
+		case 'transient_movie',
+			plot_transient_movie(md,options,subplotwidth,i);
+			return;
+		case 'transient_results',
+			plot_transient_results(md,options,subplotwidth,i);
+
+		case 'transient_field',
+			plot_transient_field(md,options,subplotwidth,i);
+			return;
+
+	otherwise,
+
+		if ismember(data,properties('model')),
+			data=eval(['md.' data ';']);
+		else
+			error('plot error message: data provided not supported yet. Type plotdoc for help');
+		end
+	end
+end
+
+%Figure out if this is a semi-transparent plot.
+if exist(options,'overlay'),
+	plot_overlay(md,data,options,nlines,ncols,i);
+	return;
+end
+
+%Figure out if this is a semi-transparent plot.
+if exist(options,'gridded'),
+	plot_gridded(md,data,options,nlines,ncols,i);
+	return;
+end
+
+%Figure out if this is a Section plot
+if exist(options,'sectionvalue')
+	plot_section(md,data,options,nlines,ncols,i);
+	return;
+end
+
+%Figure out if this is a Profile plot
+if exist(options,'profile')
+	plot_profile(md,data,options,nlines,ncols,i);
+	return;
+end
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,data,options);
+[data2 datatype]=processdata(md,data,options);
+
+%standard plot:
+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(options,'colorbar',2);
+	if exist(options,'contourlevels'),
+		data2=data;
+	end
+end
+
+applyoptions(md,data2,options);
+
+%do ground overlay on kml plot_unit? 
+if (strcmpi(getfieldvalue(options,'kmlgroundoverlay','off'),'on')),
+	if ((nlines*ncols~=1) | (i~=1)),
+		error('cannot kmlgroundoverlay on multi-plots');
+	end
+	
+	%call routine to build kml file and image that goes with it.
+	kmlgroundoverlay(md,options);
+end
Index: /issm/trunk-jpl/src/m/plot/plot_mesh.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_mesh.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_mesh.m	(revision 13009)
@@ -0,0 +1,41 @@
+function plot_mesh(md,options,nlines,ncols,i);
+%PLOT_MESH - plot model mesh
+%
+%   Usage:
+%      plot_mesh(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+%retrieve some options
+linewidth=getfieldvalue(options,'linewidth',1);
+edgecolor=getfieldvalue(options,'edgecolor','black');
+
+%plot mesh
+if is2d
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+else
+	if ~isplanet,
+		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',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+		patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+		patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+		patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+		patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+	else
+		A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+		if (size(elements,2)==4), D=elements(:,4); else D=C; end
+		patch( 'Faces', [A B C D],  'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none','EdgeColor',edgecolor,'linewidth',linewidth);
+	end
+end
+
+%apply options
+options=addfielddefault(options,'title','Mesh');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_none.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_none.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_none.m	(revision 13009)
@@ -0,0 +1,20 @@
+function plot_none(md,options,nlines,ncols,i);
+%PLOT_NONE - plot nothing, just apply options
+%
+%   Usage:
+%      plot_mesh(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+return;
+
+options=addfielddefault(options,'colorbar','none');
+options=addfielddefault(options,'map','none');
+options=addfielddefault(options,'axis','equal');
+
+if exist(options,'overlay'),
+	plot_overlay(md,'none',options,nlines,ncols,i);
+	return;
+end
+
+%apply options
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_overlay.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_overlay.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_overlay.m	(revision 13009)
@@ -0,0 +1,154 @@
+function plot_overlay(md,data,options,plotlines,plotcols,i)
+%PLOT_OVERLAY - superimpose radar image to a given field
+%
+%   Usage:
+%      plot_overlay(md,options,plotlines,plotcols,i)
+%
+%   See also: PLOTMODEL
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+if strcmpi(data,'none'),
+	radaronly=1;
+	data=NaN*ones(md.mesh.numberofvertices,1);
+	datatype=1;
+else
+	radaronly=0;
+	[data datatype]=processdata(md,data,options);
+end
+
+%check is2d
+if ~is2d, 
+	error('buildoverlay error message: overlay not supported for 3d meshes, project on a layer');
+end
+if datatype==3,
+	error('buildoverlay error message: overlay not supported for quiver plots');
+end
+
+
+%radar power
+if ~any(isnan(md.radaroverlay.x)) & ~any(isnan(md.radaroverlay.y)) & ~any(isnan(md.radaroverlay.pwr)),
+	disp('plot_overlay info: the radar image held by the model is being used');
+	xlim=[min(md.radaroverlay.x) max(md.radaroverlay.x)];
+	ylim=[min(md.radaroverlay.y) max(md.radaroverlay.y)];
+else
+	disp('Extracting radar image...');
+	%Get xlim and ylim (used to extract radar image)
+	xlim=getfieldvalue(options,'xlim',[min(x) max(x)])/getfieldvalue(options,'unit',1);
+	ylim=getfieldvalue(options,'ylim',[min(y) max(y)])/getfieldvalue(options,'unit',1);
+	options=addfielddefault(options,'xlim',xlim);
+	options=addfielddefault(options,'ylim',ylim);
+	md=radarpower(md,options);
+end
+contrast = getfieldvalue(options,'contrast',1);  
+radar = (md.radaroverlay.pwr).^(contrast);
+radar = radar./max(radar(:));
+%radar(find(radar==0))=1; %Change background from black to white
+
+%InterpFromMeshToGrid
+xmin=min(md.radaroverlay.x);
+ymax=max(md.radaroverlay.y);
+xspacing=(max(md.radaroverlay.x)-min(md.radaroverlay.x))/(length(md.radaroverlay.x));
+yspacing=(max(md.radaroverlay.y)-min(md.radaroverlay.y))/(length(md.radaroverlay.y));
+nlines=length(md.radaroverlay.y);
+ncols =length(md.radaroverlay.x);
+disp('Interpolating data on grid...');
+if radaronly,
+	x_m=xmin:xspacing:xmin+ncols*xspacing;
+	y_m=ymax-nlines*yspacing:yspacing:ymax;
+	data_grid=NaN*ones(nlines,ncols);
+else
+	[x_m y_m data_grid]=InterpFromMeshToGrid(elements,x/getfieldvalue(options,'unit',1),y/getfieldvalue(options,'unit',1),...
+		data,xmin,ymax,xspacing,yspacing,nlines,ncols,NaN);
+end
+
+%Process data_grid (For processing, it is better not to have nan)
+pos=find(isinf(data_grid));
+if ~isempty(pos),
+	disp('Warning: removing Infs from vector (probably log(0)?)');
+	data_grid(pos)=NaN;
+end
+if exist(options,'caxis'),
+	caxis_opt=getfieldvalue(options,'caxis');
+	data_grid(find(data_grid<caxis_opt(1)))=caxis_opt(1);
+	data_grid(find(data_grid>caxis_opt(2)))=caxis_opt(2);
+	data_min=caxis_opt(1);
+	data_max=caxis_opt(2);
+else
+	data_min=min(data_grid(:));
+	data_max=max(data_grid(:));
+end
+data_nan=find(isnan(data_grid));
+data_grid(data_nan)=data_min; 
+
+%Special colormaps that require hsv treatment
+colorm=getfieldvalue(options,'colormap','Rignot');
+if strcmpi(colorm,'Rignot') | strcmpi(colorm,'Seroussi') | strcmpi(colorm,'redblue')
+	if strcmpi(colorm,'Rignot'),
+		transparency=getfieldvalue(options,'alpha',1);
+		h=(data_grid-data_min)/(data_max-data_min+eps);
+		if radaronly, h(:)=0; end
+		s=max(min((0.1+h).^(1/transparency),1),0);
+	elseif strcmpi(colorm,'Seroussi'),
+		transparency=getfieldvalue(options,'alpha',1);
+		h=1-(data_grid-data_min)/(data_max-data_min+eps)*0.7;
+		if radaronly, h(:)=0; end
+		s=max(min((0.1+h).^(1/transparency),1),0);
+	elseif strcmpi(colorm,'redblue')
+		data_mean=data_min+(data_max-data_min)/2;
+		h=1*ones(size(data_grid));
+		h(find(data_grid<data_mean))=0.7;
+		s=max(min(abs(data_grid-data_mean)/(data_max-data_mean) ,1),0);
+	else
+		error('colormap not supported yet. (''Rignot'' and ''redblue'' are the only cupported colormaps)');
+	end
+	%(S) Saturation is 0 in NaNs
+	s(data_nan)=0;
+	%(V) intensity is based on radar image
+	v=radar; %use radar power as intensity
+
+	%Transform HSV to RGB
+	image_hsv=zeros(size(data_grid,1),size(data_grid,2),3);
+	image_hsv(:,:,1)=h; clear h;
+	image_hsv(:,:,2)=s; clear s;
+	image_hsv(:,:,3)=v; clear v;
+	image_rgb=hsv2rgb(image_hsv);
+else
+	colorm = getcolormap(options);
+	len    = size(colorm,1);
+
+	ind = ceil((len-1)*(data_grid-data_min)/(data_max - data_min + eps) +1);
+	ind(find(ind>len))=len;
+	image_rgb=zeros(size(data_grid,1),size(data_grid,2),3);
+	r=colorm(:,1); image_rgb(:,:,1)=r(ind); clear r;
+	g=colorm(:,2); image_rgb(:,:,2)=g(ind); clear g;
+	b=colorm(:,3); image_rgb(:,:,3)=b(ind); clear b;
+
+	%Now add radarmap
+	r = image_rgb(:,:,1).*radar;  r(data_nan) = radar(data_nan);  image_rgb(:,:,1) = r;  clear r;
+	g = image_rgb(:,:,2).*radar;  g(data_nan) = radar(data_nan);  image_rgb(:,:,2) = g;  clear g;
+	b = image_rgb(:,:,3).*radar;  b(data_nan) = radar(data_nan);  image_rgb(:,:,3) = b;  clear b;
+end
+
+%Select plot area 
+subplotmodel(plotlines,plotcols,i,options);
+
+%Plot: 
+imagesc(md.radaroverlay.x*getfieldvalue(options,'unit',1),md.radaroverlay.y*getfieldvalue(options,'unit',1),image_rgb);set(gca,'YDir','normal');
+
+%last step: mesh overlay?
+if exist(options,'edgecolor'),
+	hold on
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none',...
+		'EdgeColor',getfieldvalue(options,'edgecolor'),'LineWidth',getfieldvalue(options,'linewidth',1));
+end
+
+%Apply options, without colorbar and without grid
+options=changefieldvalue(options,'colormap',colorm);              % We used an HSV colorbar
+if ~isnan(data_min),
+	options=changefieldvalue(options,'caxis',[data_min data_max]); % force caxis so that the colorbar is ready
+end
+options=addfielddefault(options,'axis','equal off');              % default axis
+applyoptions(md,data,options);
+drawnow
Index: /issm/trunk-jpl/src/m/plot/plot_parthist.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_parthist.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_parthist.m	(revision 13009)
@@ -0,0 +1,34 @@
+function plot_parthist(md,options,nlines,ncols,i);
+%PLOT_PARTHIST - plot partitioning histogram
+%
+%   Usage:
+%      plot_parthist(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+imin=min(md.qmu.partition);
+imax=max(md.qmu.partition);
+
+part=zeros(imax-imin+1,2);
+
+for i=imin:imax
+    ind=find(md.qmu.partition == i);
+    part(i-imin+1,1)=length(ind);
+	part(i-imin+1,2)=sum(md.vertex_weight(ind));
+end
+
+subplot(2,1,1)
+bar(imin:imax,part(:,1));
+xlim([imin-0.5 imax+0.5])
+title('Number of Nodes in Each Partition')
+
+subplot(2,1,2)
+bar(imin:imax,part(:,2));
+xlim([imin-0.5 imax+0.5])
+title('Total Weight in Each Partition')
Index: /issm/trunk-jpl/src/m/plot/plot_parthistn.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_parthistn.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_parthistn.m	(revision 13009)
@@ -0,0 +1,43 @@
+function plot_parthist(md,options,nlines,ncols,i);
+%PLOT_PARTHIST - plot partitioning histogram
+%
+%   Usage:
+%      plot_parthist(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+imin=min(md.qmu.partition);
+imax=max(md.qmu.partition);
+
+part=zeros(imax-imin+1,2);
+
+for i=imin:imax
+    ind=find(md.qmu.partition == i);
+    part(i-imin+1,1)=length(ind);
+	part(i-imin+1,2)=sum(md.vertex_weight(ind));
+end
+
+%subplot(2,1,1)
+bar(imin:imax,part(:,1));
+%xlim([imin-0.5 imax+0.5])
+%title('Number of Nodes in Each Partition')
+options=addfielddefault(options,'xlim',[imin-0.5 imax+0.5]);
+options=addfielddefault(options,'title','Number of Nodes in Each Partition');
+options=addfielddefault(options,'colorbar','off');
+
+%subplot(2,1,2)
+%bar(imin:imax,part(:,2));
+%xlim([imin-0.5 imax+0.5])
+%title('Total Weight in Each Partition')
+%options=addfielddefault(options,'xlim',[imin-0.5 imax+0.5]);
+%options=addfielddefault(options,'title','Total Weight in Each Partition');
+%options=addfielddefault(options,'colorbar','off');
+
+%apply options
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_parthistw.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_parthistw.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_parthistw.m	(revision 13009)
@@ -0,0 +1,43 @@
+function plot_parthist(md,options,nlines,ncols,i);
+%PLOT_PARTHIST - plot partitioning histogram
+%
+%   Usage:
+%      plot_parthist(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+imin=min(md.qmu.partition);
+imax=max(md.qmu.partition);
+
+part=zeros(imax-imin+1,2);
+
+for i=imin:imax
+    ind=find(md.qmu.partition == i);
+    part(i-imin+1,1)=length(ind);
+	part(i-imin+1,2)=sum(md.vertex_weight(ind));
+end
+
+%subplot(2,1,1)
+%bar(imin:imax,part(:,1));
+%xlim([imin-0.5 imax+0.5])
+%title('Number of Nodes in Each Partition')
+%options=addfielddefault(options,'xlim',[imin-0.5 imax+0.5]);
+%options=addfielddefault(options,'title','Number of Nodes in Each Partition');
+%options=addfielddefault(options,'colorbar','off');
+
+%subplot(2,1,2)
+bar(imin:imax,part(:,2));
+%xlim([imin-0.5 imax+0.5])
+%title('Total Weight in Each Partition')
+options=addfielddefault(options,'xlim',[imin-0.5 imax+0.5]);
+options=addfielddefault(options,'title','Total Weight in Each Partition');
+options=addfielddefault(options,'colorbar','off');
+
+%apply options
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_penalties.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_penalties.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_penalties.m	(revision 13009)
@@ -0,0 +1,48 @@
+function plot_penalties(md,options,width,i);
+%PLOT_PENALTIES - plot penalties
+%
+%   Usage:
+%      plot_penalties(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh penalties
+subplot(width,width,i); 
+
+%units
+if exist(options,'unit'),
+	unit=getfieldvalue(options,'unit');
+	x=x*unit;
+	y=y*unit;
+	z=z*unit;
+end
+
+if ~md.mesh.dimension==3,
+	error('no penalties to plot for ''2d'' model');
+elseif isempty(md.penalties),
+	disp('no penalty applied in this model');
+	return;
+else
+	%plot mesh
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	hold on;
+	for (i=1:size(md.penalties,1)),
+		P1=plot3(x(md.penalties(i,1)),y(md.penalties(i,1)),z(md.penalties(i,1)),'ro','MarkerSize',15,'MarkerFaceColor','r');
+		P2=plot3(x(md.penalties(i,:)),y(md.penalties(i,:)),z(md.penalties(i,:)),'bo-','LineWidth',2,'MarkerSize',8,'MarkerFaceColor','b');
+	end
+	legend([P1 P2],'MacAyeal''s penalized nodes','Pattyn''s penalized nodes');
+end
+
+%apply options
+options=addfielddefault(options,'title','Penalties');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_profile.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_profile.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_profile.m	(revision 13009)
@@ -0,0 +1,55 @@
+function plot_profile(md,data,options,nlines,ncols,ii)
+%PLOT_SECTION - plot a given field on a profile
+%
+%   Usage:
+%      plot_profile(md,data,options,nlines,ncols,i)
+%
+%   See also: PLOTMODEL
+
+%process model
+[x_m y_m z_m elements_m is2d isplanet]=processmesh(md,[],options);
+if is2d, error('only 3d model supported'); end
+
+%Get number of curves and generate random colors
+numcurves=size(data,2);
+colorm=getfieldvalue(options,'colormap','lines');
+color=eval([ colorm '(numcurves);']);
+options=removefield(options,'colormap',0); %back to default colormap
+
+%Get coordinates
+location=getfieldvalue(options,'profile');
+if ~isnumeric(location) | numel(location)~=2,
+	error('location provided not supported (should be [x y])');
+end
+xprof=location(1);
+yprof=location(2);
+
+%Loop over number of curves
+for i=1:numcurves,
+
+	%Process data
+	[datai datatype]=processdata(md,data(:,i),options);
+
+	%resolution
+	if exist(options,'resolution'),
+		resolution=getfieldvalue(options,'resolution');
+	else %Default resolution
+		resolution=[100];
+		disp(['plot_profile warning: no resolution specified, using default: ' num2str(resolution) ]);
+	end
+
+	%Compute profile value
+	[z,data_interp]=ProfileValues(md,datai,xprof,yprof,resolution);
+
+	%plot profile
+	subplot(nlines,ncols,ii)
+	plot(data_interp,z,'color',color(i,:),'LineWidth',getfieldvalue(options,'linewidth',1),'LineStyle','-');
+	hold on;
+end
+
+%apply options
+options=addfielddefault(options,'title','Profile');
+options=addfielddefault(options,'colorbar',0);
+options=addfielddefault(options,'ylabel','z');
+options=addfielddefault(options,'view',2);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_qmu_mass_flux_segments.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_qmu_mass_flux_segments.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_qmu_mass_flux_segments.m	(revision 13009)
@@ -0,0 +1,49 @@
+function plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
+%PLOT_QMU_MASS_FLUX_SEGMENTS - plot segments from the qmu analysis of mass fluxes
+%
+%   Usage:
+%      plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
+%
+
+subplot(nlines,ncols,i); 
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+allsegments=md.qmu.mass_flux_segments;
+
+if (md.mesh.dimension==2),
+
+	%recover segments
+	hold on
+	for i=1:length(allsegments),
+		segments=allsegments{i};
+
+		%plot semgnets
+		for j=1:length(segments),
+			plot([segments(j,1) segments(j,3)],[segments(j,2) segments(j,4)]);
+		end
+		text(segments(j,1),segments(j,2),['Profile #' num2str(i)]);
+
+		%plot normals
+		
+		for j=1:length(segments),
+			xstart=mean([segments(j,1) segments(j,3)]);
+			ystart=mean([segments(j,2) segments(j,4)]);
+			length1=sqrt((segments(j,1)-segments(j,3)).^2 + (segments(j,2)-segments(j,4)).^2);
+			normal(:,1)=cos(atan2(segments(j,1)-segments(j,3) , segments(j,4)-segments(j,2)));
+			normal(:,2)=sin(atan2(segments(j,1)-segments(j,3) , segments(j,4)-segments(j,2)));
+			xend=xstart+length1.*normal(:,1);
+			yend=ystart+length1.*normal(:,2);
+			plot([xstart xend],[ystart yend],'r-');
+		end
+
+	end
+else
+	error('plot_qmu_mass_flux_segments: 3d plot of segments not supported yet!');
+end
+
+%apply options
+options=addfielddefault(options,'title','Mass Flux segments and normals');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_qmuhistnorm.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_qmuhistnorm.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_qmuhistnorm.m	(revision 13009)
@@ -0,0 +1,48 @@
+function plot_qmuhistnorm(md,options,nlines,ncols,index);
+
+%prepare plot
+subplot(nlines,ncols,index); 
+hold on
+
+
+%recover histnorm data
+if ~exist(options,'qmudata')
+	error('plot_qmuhistnorm error message: option qmudata is required');
+else
+	qmudata=getfieldvalue(options,'qmudata');
+end
+
+%process options for the qmu plot: 
+
+%    hmin          (numeric, minimum for histogram)
+%    hmax          (numeric, maximum for histogram)
+%    hnint         (numeric, number of intervals for histogram)
+%    ymin1         (numeric, minimum of histogram y-axis)
+%    ymax1         (numeric, maximum of histogram y-axis)
+%    ymin2         (numeric, minimum of cdf y-axis)
+%    ymax2         (numeric, maximum of cdf y-axis)
+%    cdfplt        (char, 'off' to turn off cdf line plots)
+%    cdfleg        (char, 'off' to turn off cdf legends)
+%
+
+qmuoptions='';
+
+if exist(options,'hmin'), hmin=getfieldvalue(options,'hmin'); qmuoptions=[qmuoptions ',''hmin'',' num2str(hmin)]; end
+if exist(options,'hmax'), hmax=getfieldvalue(options,'hmax'); qmuoptions=[qmuoptions ',''hmax'',' num2str(hmax)]; end
+if exist(options,'hnint'), hnint=getfieldvalue(options,'hnint'); qmuoptions=[qmuoptions ',''hnint'',' num2str(hnint)]; end
+if exist(options,'ymin1'), ymin1=getfieldvalue(options,'ymin1'); qmuoptions=[qmuoptions ',''ymin1'',' num2str(ymin1)]; end
+if exist(options,'ymax1'), ymax1=getfieldvalue(options,'ymax1'); qmuoptions=[qmuoptions ',''ymax1'',' num2str(ymax1)]; end
+if exist(options,'ymin2'), ymin2=getfieldvalue(options,'ymin2'); qmuoptions=[qmuoptions ',''ymin2'',' num2str(ymin2)]; end
+if exist(options,'ymax2'), ymax2=getfieldvalue(options,'ymax2'); qmuoptions=[qmuoptions ',''ymax2'',' num2str(ymax2)]; end
+if exist(options,'cdfplt'), cdfplt=getfieldvalue(options,'cdfplt'); qmuoptions=[qmuoptions ',''cdfplt'',''' cdfplt '''']; end
+if exist(options,'cdfleg'), cdfleg=getfieldvalue(options,'cdfleg'); qmuoptions=[qmuoptions ',''cdfleg'',''' cdfleg '''']; end
+if exist(options,'nrmplt'), nrmplt=getfieldvalue(options,'nrmplt'); qmuoptions=[qmuoptions ',''nrmplt'',''' nrmplt '''']; end
+if exist(options,'EdgeColor'), EdgeColor=getfieldvalue(options,'EdgeColor'); qmuoptions=[qmuoptions ',''EdgeColor'',''' EdgeColor '''']; end
+if exist(options,'FaceColor'), FaceColor=getfieldvalue(options,'FaceColor'); qmuoptions=[qmuoptions ',''FaceColor'',''' FaceColor '''']; end
+
+%use qmu plot
+eval(['plot_hist_norm(qmudata' qmuoptions ');']);
+
+%apply options
+options=changefieldvalue(options,'colorbar','off');
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_qmumean.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_qmumean.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_qmumean.m	(revision 13009)
@@ -0,0 +1,59 @@
+function plot_qmumean(md,options,nlines,ncols,i);
+%PLOT_QMUMEAN - plot mean of a scaled response 
+%
+%   Usage:
+%      plot_qmumean(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+%edgecolor
+edgecolor=getfieldvalue(options,'edgecolor','none');
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%find response function
+if exist(options,'qmudata'), 
+	descriptor=getfieldvalue(options,'qmudata'); 
+	if ~ischar(descriptor),
+		error('plot_qmumean error message:  descriptor should be a string');
+	end
+else 
+	error('plot_qmumean error message:  provide descriptor of response function in ''qmudata'' option');
+end
+
+%go pick up the response: 
+allresponses=md.qmu.results.dresp_out;
+responses=zeros(md.qmu.numberofpartitions,1);
+
+count=1;
+for i=1:length(allresponses),
+	d=allresponses(i).descriptor;
+	if strncmpi(d,'scaled_',7),
+		d=d(8:end);
+		if strncmpi(d,descriptor,length(descriptor)),
+			responses(count)=allresponses(i).mean;
+			count=count+1;
+		end
+	end
+end
+
+%log?
+if exist(options,'log'),
+	responses=log(responses)/log(getfieldvalue(options,'log'));
+end
+
+%now, project onto vertices
+responses_on_node=responses(md.qmu.partition+1);
+
+%plot
+A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', responses_on_node,'FaceColor','interp','EdgeColor',edgecolor);
+
+%apply options
+options=addfielddefault(options,'title',['Mean distribution of ' descriptor]);
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_qmunormplot.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_qmunormplot.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_qmunormplot.m	(revision 13009)
@@ -0,0 +1,45 @@
+%
+%  plot a normal probability plot of the response functions.
+%
+%  []=plot_normplot(rfunc)
+%
+function []=plot_qmunormplot(rfunc,width,ii)
+
+if ~nargin
+    help plot_normplot
+    return
+end
+
+%%  assemble the data into a matrix
+
+desc=cell (1,length(rfunc));
+for i=1:length(rfunc)
+    ldata(i)=length(rfunc(i).sample);
+end
+data=zeros(max(ldata),length(rfunc));
+
+for i=1:length(rfunc)
+    desc(i)=cellstr(rfunc(i).descriptor);
+    data(1:ldata(i),i)=rfunc(i).sample;
+end
+
+%standard plot:
+subplot(width,width,ii);
+
+%%  draw the plot
+
+%  draw normal probability plot
+
+normplot(data)
+ax1=gca;
+
+%  add the annotation
+
+title('Normal Probability Plot of Design Variables and/or Response Functions')
+xlabel('Value')
+ylabel('Probability')
+
+hleg1=legend(ax1,desc,'Location','EastOutside',...
+             'Orientation','vertical','Interpreter','none');
+
+end
Index: /issm/trunk-jpl/src/m/plot/plot_qmustddev.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_qmustddev.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_qmustddev.m	(revision 13009)
@@ -0,0 +1,60 @@
+function plot_qmustddev(md,options,nlines,ncols,i);
+%PLOT_QMUMEAN - plot stddev of a scaled response 
+%
+%   Usage:
+%      plot_qmustddev(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh
+subplot(nlines,ncols,i); 
+
+%edgecolor
+edgecolor=getfieldvalue(options,'edgecolor','none');
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%find response function
+if exist(options,'qmudata'), 
+	descriptor=getfieldvalue(options,'qmudata'); 
+	if ~ischar(descriptor),
+		error('plot_qmustddev error message:  descriptor should be a string');
+	end
+else 
+	error('plot_qmustddev error message:  provide descriptor of response function in ''qmudata'' option');
+end
+
+%go pick up the response: 
+allresponses=md.qmu.results.dresp_out;
+responses=zeros(md.qmu.numberofpartitions,1);
+
+count=1;
+for i=1:length(allresponses),
+	d=allresponses(i).descriptor;
+	if strncmpi(d,'scaled_',7),
+		d=d(8:end);
+		if strncmpi(d,descriptor,length(descriptor)),
+			responses(count)=allresponses(i).stddev/allresponses(i).mean*100;
+			count=count+1;
+		end
+	end
+end
+
+%log?
+if exist(options,'log'),
+	responses=log(responses)/log(getfieldvalue(options,'log'));
+end
+
+
+%now, project onto vertices
+responses_on_node=responses(md.qmu.partition+1);
+
+%plot
+A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', responses_on_node,'FaceColor','interp','EdgeColor',edgecolor);
+
+%apply options
+options=addfielddefault(options,'title',['Stddev  distribution of ' descriptor ' in %']);
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_quiver.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_quiver.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_quiver.m	(revision 13009)
@@ -0,0 +1,26 @@
+function plot_quiver(x,y,u,v,options),
+%PLOT_QUIVER - quiver plot with colors
+%
+%   to be perfected tomorrow
+%
+%   Usage:
+%      plot_quiver(x,y,u,v,options)
+%
+%   Example:
+%      plot_quiver(md.mesh.x,md.mesh.y,md.initialization.vx,md.initialization.vy,options);
+
+%process fields
+[quivers,palette]=quiver_process(x,y,u,v,options);
+
+%loop over the number of colors
+hold on
+h=[];
+for i=1:quivers.numcolors
+	pos=find(quivers.colorind==i);
+	hprime=quiver(quivers.x(pos),quivers.y(pos),quivers.u(pos),quivers.v(pos),...
+		'Color',palette(i,:),'ShowArrowHead','on','AutoScale','off');
+	h=[h;hprime];
+end
+
+%take care of colorbar
+quiver_colorbar(quivers,options);
Index: /issm/trunk-jpl/src/m/plot/plot_quiver3.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_quiver3.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_quiver3.m	(revision 13009)
@@ -0,0 +1,104 @@
+function plot_quiver3(x,y,z,u,v,w,options),
+%PLOT_QUIVER3 - 3d quiver plot with colors
+%
+%   to be perfected tomorrow
+%
+%   Usage:
+%      plot_quiver3(x,y,z,u,v,w,options)
+%
+%   Example:
+%      plot_quiver(md.mesh.x,md.mesh.y,md.mesh.z,md.initialization.vx,md.initialization.vy,md.initialization.vz,options);
+
+%keep only non NaN elements
+pos=find(~isnan(x) & ~isnan(y) & ~isnan(z) & ~isnan(u) & ~isnan(v) & ~isnan(w));
+x=x(pos); y=y(pos); z=z(pos);
+u=u(pos); v=v(pos); w=w(pos);
+
+%get norm Min and Max
+Norm=sqrt(u.^2+v.^2+w.^2);
+Min=min(Norm);
+Max=max(Norm);
+
+%process options: scaling factor?
+scalingfactor=getfieldvalue(options,'scaling',0.40);
+
+%number of colors?
+colorlevels=getfieldvalue(options,'colorlevels',NaN);
+if isnumeric(colorlevels),
+	if isnan(colorlevels),
+		numcolors=30;
+	else
+		numcolors=colorlevels;
+	end
+	levels=round_ice(linspace(Min,Max,numcolors+1),2);
+else
+	levels=zeros(1,length(colorlevels)+2);
+	levels(1)=Min;
+	for i=1:length(colorlevels)
+		levels(i+1)=colorlevels{i};
+	end
+	levels(end)=Max;
+	levels=sort(unique(levels));
+	numcolors=length(levels)-1;
+end
+
+%set the colormap 
+if numcolors==2;
+	%blue and red
+	c=[0 0 1;1 0 0];
+elseif numcolors==3,
+	%blue yellow and red
+	c=[0 0 1;1 1 0;1 0 0];
+else
+	%let jet choose
+	c=colormap(jet(numcolors));
+end
+
+%Scale data
+if strcmpi(getfieldvalue(options,'autoscale','on'),'off'),
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	u=scalingfactor*sqrt(delta)*u./Norm;
+	v=scalingfactor*sqrt(delta)*v./Norm;
+else
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	u=scalingfactor*sqrt(delta)*u./max(Norm);
+	v=scalingfactor*sqrt(delta)*v./max(Norm);
+end
+
+%loop over the number of colors
+hold on
+h=[];
+for i=1:numcolors
+	pos=find( (Norm>=levels(i)) & (Norm<=levels(i+1)) );
+	hprime=quiver3(x(pos),y(pos),z(pos),u(pos),v(pos),w(pos),'Color',c(i,:),'ShowArrowHead','on','AutoScale','off');
+	h=[h;hprime];
+end
+
+%take care of colorbar
+if  ~strcmpi(getfieldvalue(options,'colorbar','on'),'off'),
+
+	%build ticks
+	hcb=colorbar('peer',gca,'location','EastOutside');
+	ticklabel=cell(1,length(levels));
+	for i=1:length(levels),
+		ticklabel{i}=num2str(round_ice(levels(i),3));
+	end
+	tickpos=1:numcolors+1;
+
+	%remove ticks if to many have been created
+	proportion=round(length(levels)/10);
+	if proportion>1,
+		ticklabel=ticklabel(1:proportion:end);
+		tickpos=tickpos(1:proportion:end);
+	end
+
+	%draw colorbar
+	set(hcb,'YTickLabel',ticklabel,'YTick',tickpos);
+	%position
+	if exist(options,'colorbarpos'),
+		set(hcb,'Position',getfieldvalue(options,'colorbarpos'));
+	end
+	%fontsize
+	fontsize=getfieldvalue(options,'fontsize',14);
+	set(hcb,'FontSize',fontsize);
+end
Index: /issm/trunk-jpl/src/m/plot/plot_referential.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_referential.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_referential.m	(revision 13009)
@@ -0,0 +1,91 @@
+function plot_referential(md,options,width,i,data);
+%PLOT_PRESSURELOAD - plot segment on neumann BC
+%
+%   Usage:
+%      plot_referential(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh boundaries
+subplot(width,width,i); 
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+referential=md.diagnostic.referential;
+
+Xhat=md.diagnostic.referential(:,1:3);
+pos=find(sum(isnan(Xhat),2));
+Xhat(pos,:)=repmat([1 0 0],size(pos,1),1);
+Xhatnorm=sqrt(Xhat(:,1).^2+Xhat(:,2).^2+Xhat(:,3).^2);
+Xhat=Xhat./[Xhatnorm Xhatnorm Xhatnorm];
+
+Zhat=md.diagnostic.referential(:,4:6);
+pos=find(sum(isnan(Zhat),2));
+Zhat(pos,:)=repmat([0 0 1],size(pos,1),1);
+Zhatnorm=sqrt(Zhat(:,1).^2+Zhat(:,2).^2+Zhat(:,3).^2);
+Zhat=Zhat./[Zhatnorm Zhatnorm Zhatnorm];
+
+Yhat=cross(Zhat,Xhat);
+
+if (md.mesh.dimension==2),
+
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	h1=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+
+	xstart=x;
+	ystart=y;
+	zstart=z;
+	edgex=max(md.mesh.x(elements),[],2)-min(md.mesh.x(elements),[],2);
+	len=min(edgex)/1.5;
+	%plot X axis
+	xend=xstart+len*Xhat(:,1);
+	yend=ystart+len*Xhat(:,2);
+	hx=quiver(xstart,ystart,xend-xstart,yend-ystart,'Color','blue','ShowArrowHead','on','AutoScale','off');
+	%plot Y axis
+	xend=xstart+len*Yhat(:,1);
+	yend=ystart+len*Yhat(:,2);
+	hy=quiver(xstart,ystart,xend-xstart,yend-ystart,'Color','red','ShowArrowHead','on','AutoScale','off');
+
+	legend([hx,hy],'local X direction','local Y direction')
+else
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); D=elements(:,4); E=elements(:,5); F=elements(:,6);
+	h1=patch( 'Faces', [A B C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+
+	xstart=x;
+	ystart=y;
+	zstart=z;
+	edgex=max(md.mesh.x(elements),[],2)-min(md.mesh.x(elements),[],2);
+	edgez=max(md.mesh.z(elements),[],2)-min(md.mesh.z(elements),[],2);
+	len=min(edgex)/1.5;
+	lenz=min(edgez)/1.5;
+	%plot X axis
+	xend=xstart+len*Xhat(:,1);
+	yend=ystart+len*Xhat(:,2);
+	zend=zstart+len*Xhat(:,3);
+	hx=quiver3(xstart,ystart,zstart,xend-xstart,yend-ystart,zend-zstart,'Color','blue','ShowArrowHead','on','AutoScale','off');
+	%plot Y axis
+	xend=xstart+len*Yhat(:,1);
+	yend=ystart+len*Yhat(:,2);
+	zend=zstart+len*Yhat(:,3);
+	hy=quiver3(xstart,ystart,zstart,xend-xstart,yend-ystart,zend-zstart,'Color','red','ShowArrowHead','on','AutoScale','off');
+	%plot Z axis
+	xend=xstart+lenz*Zhat(:,1);
+	yend=ystart+lenz*Zhat(:,2);
+	zend=zstart+lenz*Zhat(:,3);
+	hz=quiver3(xstart,ystart,zstart,xend-xstart,yend-ystart,zend-zstart,'Color','green','ShowArrowHead','on','AutoScale','off');
+
+	legend([hx,hy,hz],'local X direction','local Y direction','local Z direction')
+end
+
+%apply options
+options=addfielddefault(options,'title','Diagnostic referential');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_riftfraction.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_riftfraction.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_riftfraction.m	(revision 13009)
@@ -0,0 +1,48 @@
+function plot_riftfraction(md,options,nlines,ncols,index);
+%PLOT_RIFTFRACTION - plot rift fractions
+%
+%   Usage:
+%      plot_riftfraction(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%check that there is something in riftproperties
+if isnan(md.rifts.riftstruct.riftproperties),
+	error('plot_riftfraction error message: field riftproperies is empty, run the model first')
+end
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+subplot(nlines,ncols,index); 
+hold on
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-');
+end
+
+%first, build a vector of fractions, over all nodes. 
+fractions=zeros(md.mesh.numberofvertices,1);
+
+%complete the tips.
+for i=1:length(md.rifts.riftstruct), 
+	tips=md.rifts.riftstruct(i).tips;
+	fractions(tips)=1;
+end
+
+hold on;
+for i=1:length(md.rifts.riftstruct), 
+	segments=md.rifts.riftstruct(i).segments(:,1:2)';
+	xc=x(segments(:));
+	yc=y(segments(:));
+	zc=fractions(segments(:));
+	h2=patch('Xdata',xc,'Ydata',yc,'Zdata',zc,'Cdata',zc,'facecolor','none','edgecolor','flat');
+end
+legend([h1,h2],'mesh boundaries','rifts')
+hold off
+
+%apply options
+options=addfielddefault(options,'title','Rift ice/water fraction ???????'); %Eric, could you enter a better title?
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_riftnumbering.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_riftnumbering.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_riftnumbering.m	(revision 13009)
@@ -0,0 +1,94 @@
+function plot_riftnumbering(md,options,nlines,ncols,index);
+%PLOT_RIFTNUMBERING - plot rift penetration + numbering of all rift vertices, as well as rift numbers.
+%
+%   Usage:
+%      plot_riftnumbering(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+fontsize=getfieldvalue(options,'FontSize',8);
+
+subplot(nlines,ncols,index); 
+hold on
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-');
+end
+
+isp1=0;
+isp2=0;
+
+if isstruct(md.rifts.riftstruct),
+	%plot mesh boundaries
+	for i=1:size(md.mesh.segments,1),
+		h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-');
+	end
+	for i=1:size(md.rifts.riftstruct,1),
+		penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+		segments=md.rifts.riftstruct(i).segments;
+		for j=1:size(segments,1),
+			plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-');
+		end
+
+		normal=zeros(2,1);
+		for j=1:size(penaltypairs,1),
+			normal(1)=penaltypairs(j,5);
+			normal(2)=penaltypairs(j,6);
+
+			vx1=md.initialization.vx(penaltypairs(j,1)); 
+			vx2=md.initialization.vx(penaltypairs(j,2));
+			vy1=md.initialization.vy(penaltypairs(j,1)); 
+			vy2=md.initialization.vy(penaltypairs(j,2));
+			penetration=(vx2-vx1)*normal(1)+(vy2-vy1)*normal(2);
+			%if penetration is negative, plot in black, positive, plot in red;: ie: if rift is closing, black, if rift is opening, red.
+			if(penetration>0),
+				p2=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'ro-','LineWidth',1);
+				set(p2,'MarkerSize',3);
+				isp2=1;
+			else
+				p1=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'ko-','LineWidth',1);
+				set(p1,'MarkerSize',3);
+				isp1=1;
+			end
+		end
+
+		%point out the tips
+		h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*');
+		plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*');
+	end
+	if strcmpi(getfieldvalue(options,'legend','on'),'on'),
+		if isp1 & isp2
+			l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips','faults','rifts');
+		elseif isp1
+			l=legend([h1,h2,p1],'mesh boundaries','crack tips','faults');
+		elseif isp2
+			l=legend([h1,h2,p2],'mesh boundaries','crack tips','rifts');
+		else
+			l=legend([h1,h2],'mesh boundaries','crack tips');
+		end
+		set(l,'Location',getfieldvalue(options,'legend_location','NorthEast'));
+	end
+else
+	error('plot error message: no rifts available!');
+end
+
+%Now, plot rift vertices numbers.
+for i=1:size(md.rifts.riftstruct,1),
+	penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+	for j=1:size(penaltypairs,1),
+		node=penaltypairs(j,1);
+		t=text(x(node),y(node),[num2str(i) '.' num2str(j)]);
+		set(t,'FontSize',fontsize);
+	end
+end
+
+
+%apply options
+options=addfielddefault(options,'title','Rift/Fault location');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_riftpenetration.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_riftpenetration.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_riftpenetration.m	(revision 13009)
@@ -0,0 +1,82 @@
+function plot_rifpenetration(md,options,nlines,ncols,index);
+%PLOT_RIFTPENETRATION - plot rift penetration
+%
+%   Usage:
+%      plot_rifpenetration(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+subplot(nlines,ncols,index); 
+hold on
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k-');
+end
+
+isp1=0;
+isp2=0;
+
+if isstruct(md.rifts.riftstruct),
+	%plot mesh boundaries
+	for i=1:size(md.mesh.segments,1),
+		h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-');
+	end
+	for i=1:size(md.rifts.riftstruct,1),
+		penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+		segments=md.rifts.riftstruct(i).segments;
+		for j=1:size(segments,1),
+			plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-');
+		end
+
+		normal=zeros(2,1);
+		for j=1:size(penaltypairs,1),
+			normal(1)=penaltypairs(j,5);
+			normal(2)=penaltypairs(j,6);
+
+			vx1=md.initialization.vx(penaltypairs(j,1)); 
+			vx2=md.initialization.vx(penaltypairs(j,2));
+			vy1=md.initialization.vy(penaltypairs(j,1)); 
+			vy2=md.initialization.vy(penaltypairs(j,2));
+			penetration=(vx2-vx1)*normal(1)+(vy2-vy1)*normal(2);
+			%if penetration is negative, plot in black, positive, plot in red;: ie: if rift is closing, black, if rift is opening, red.
+			if(penetration>0),
+				p2=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'ro-','LineWidth',1);
+				set(p2,'MarkerSize',3);
+				isp2=1;
+			else
+				p1=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'ko-','LineWidth',1);
+				set(p1,'MarkerSize',3);
+				isp1=1;
+			end
+		end
+
+		%point out the tips
+		h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*');
+		plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*');
+	end
+	if strcmpi(getfieldvalue(options,'legend','on'),'on'),
+		if isp1 & isp2
+			l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips','faults','rifts');
+		elseif isp1
+			l=legend([h1,h2,p1],'mesh boundaries','crack tips','faults');
+		elseif isp2
+			l=legend([h1,h2,p2],'mesh boundaries','crack tips','rifts');
+		else
+			l=legend([h1,h2],'mesh boundaries','crack tips');
+		end
+		set(l,'Location',getfieldvalue(options,'legend_location','NorthEast'));
+	end
+else
+	error('plot error message: no rifts available!');
+end
+hold off
+
+%apply options
+options=addfielddefault(options,'title','Rift/Fault location');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_riftrelvel.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_riftrelvel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_riftrelvel.m	(revision 13009)
@@ -0,0 +1,115 @@
+function plot_riftrelvel(md,options,nlines,ncols,index);
+%PLOT_RIFTRELVEL - plot rift relative velocities
+%
+%   Usage:
+%      plot_riftrelvel(md,options,nlines,ncols,i);
+%
+%   See also: PLOTMODEL
+
+%some checks
+if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices),
+	error('plot_riftvel error message: vx and vy do not have the right size'),
+end
+if ~isstruct(md.rifts.riftstruct),
+	error('plot error message: no rifts available!');
+end
+options=addfielddefault(options,'scaling',2);
+
+%recover vx and vy:
+vx=getfieldvalue(options,'riftrelvel_vx',md.initialization.vx);
+vy=getfieldvalue(options,'riftrelvel_vy',md.initialization.vy);
+
+%set as NaN all velocities not on rifts
+u=NaN*ones(md.mesh.numberofvertices,1);
+v=NaN*ones(md.mesh.numberofvertices,1);
+for i=1:size(md.rifts.riftstruct,1),
+	penaltypairs=md.rifts.riftstruct(i).penaltypairs(:,[1 2]);
+	u(md.rifts.riftstruct(i).penaltypairs(:,1))=vx(penaltypairs(:,1))-vx(penaltypairs(:,2));
+	v(md.rifts.riftstruct(i).penaltypairs(:,1))=vy(penaltypairs(:,1))-vy(penaltypairs(:,2));
+end
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[vel datatype]=processdata(md,[u v],options);
+[quivers,palette]=quiver_process(x,y,vel(:,1),vel(:,2),options);
+
+%prepare plot
+subplot(nlines,ncols,index); 
+hold on
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k-');
+end
+
+%plot rifts vel
+h3=[];
+for i=1:quivers.numcolors
+	pos=find(quivers.colorind==i);
+	hprime=quiver(quivers.x(pos),quivers.y(pos),quivers.u(pos),quivers.v(pos),...
+		'Color',palette(i,:),'ShowArrowHead','on','AutoScale','off');
+	hprime=quiver(quivers.x(pos),quivers.y(pos),-quivers.u(pos),-quivers.v(pos),...
+		'Color',palette(i,:),'ShowArrowHead','on','AutoScale','off');
+	h3=[h3;hprime];
+end
+
+%plot rift velocities
+isp1=0;
+isp2=0;
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-');
+end
+for i=1:size(md.rifts.riftstruct,1),
+	
+	%get nodes on rift
+	penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+	segments=md.rifts.riftstruct(i).segments;
+	for j=1:size(segments,1),
+		plot(x(segments(j,1:2)),y(segments(j,1:2)),'k-');
+	end
+
+	normal=zeros(2,1);
+	for j=1:size(penaltypairs,1),
+		normal(1)=penaltypairs(j,5);
+		normal(2)=penaltypairs(j,6);
+
+		vx1=vx(penaltypairs(j,1)); vx2=vx(penaltypairs(j,2)); vy1=vy(penaltypairs(j,1)); vy2=vy(penaltypairs(j,2));
+		penetration=(vx2-vx1)*normal(1)+(vy2-vy1)*normal(2);
+		%if penetration is negative, plot in black, positive, plot in red;: ie: if rift is closing, black, if rift is opening, red.
+		if(penetration>0),
+			p2=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'*'); set(p2,'Color',[140 140 140]/255);
+			isp2=1;
+		else
+			p1=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'k*');
+			isp1=1;
+		end
+	end
+
+	%point out the tips
+	h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*');
+	plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*');
+	segments=md.rifts.riftstruct(i).segments(:,1:2);
+end
+%legend
+if strcmpi(getfieldvalue(options,'legend','on'),'on'),
+	if isp1 & isp2
+		l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips','faults','rifts');
+	elseif isp1
+		l=legend([h1,h2,p1],'mesh boundaries','crack tips','faults');
+	elseif isp2
+		l=legend([h1,h2,p2],'mesh boundaries','crack tips','rifts');
+	else
+		l=legend([h1,h2],'mesh boundaries','crack tips');
+	end
+set(l,'Location',getfieldvalue(options,'legend_location','NorthEast'));
+end
+hold off
+
+%apply options
+quiver_colorbar(quivers,options);
+options=changefieldvalue(options,'colorbar',2);
+options=addfielddefault(options,'title','Rift/Fault Relative Velocity');
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_rifts.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_rifts.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_rifts.m	(revision 13009)
@@ -0,0 +1,77 @@
+function plot_rifts(md,options,nlines,ncols,index);
+%PLOT_RIFTS - plot rifts in a mesh
+%
+%   Usage:
+%      plot_rifts(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot mesh
+subplot(nlines,ncols,index); 
+
+%offset to separate rift flanks.
+offset=getfieldvalue(options,'offset',500);
+if isstruct(md.rifts.riftstruct),
+	
+	for i=1:size(md.rifts.riftstruct,1),
+		penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+		normal=zeros(2,1);
+		for j=1:size(penaltypairs,1),
+			normal(1)=penaltypairs(j,5);
+			normal(2)=penaltypairs(j,6);
+			x(penaltypairs(j,1))=x(penaltypairs(j,1))-normal(1)*offset;
+			y(penaltypairs(j,1))=y(penaltypairs(j,1))-normal(2)*offset;
+		end
+		if length(md.rifts.riftstruct(i).tips)==3,
+			tip=md.rifts.riftstruct(i).tips(3);
+			%who is tip connected to? 
+			if isconnected(md.mesh.elements,penaltypairs(1,1),tip),
+				normal(1)=penaltypairs(1,5);
+				normal(2)=penaltypairs(1,6);
+				x(tip)=x(tip)-normal(1)*offset;
+				y(tip)=y(tip)-normal(2)*offset;
+			end
+
+			if isconnected(md.mesh.elements,penaltypairs(1,2),tip),
+				normal(1)=penaltypairs(1,5);
+				normal(2)=penaltypairs(1,6);
+				x(tip)=x(tip)+normal(1)*offset;
+				y(tip)=y(tip)+normal(2)*offset;
+			end
+			if isconnected(md.mesh.elements,penaltypairs(end,1),tip),
+				normal(1)=penaltypairs(end,5);
+				normal(2)=penaltypairs(end,6);
+				x(tip)=x(tip)-normal(1)*offset;
+				y(tip)=y(tip)-normal(2)*offset;
+			end
+			if isconnected(md.mesh.elements,penaltypairs(end,2),tip),
+				normal(1)=penaltypairs(end,5);
+				normal(2)=penaltypairs(end,6);
+				x(tip)=x(tip)+normal(1)*offset;
+				y(tip)=y(tip)+normal(2)*offset;
+			end
+		end
+	end
+end
+
+%plot mesh
+if is2d
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+else
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C ], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F ], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+end
+
+%apply options
+options=addfielddefault(options,'title','Rifts');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_riftvel.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_riftvel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_riftvel.m	(revision 13009)
@@ -0,0 +1,108 @@
+function plot_riftvel(md,options,nlines,ncols,index);
+%PLOT_RIFTVEL - plot rift velocity
+%
+%   Usage:
+%      plot_riftvel(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%some checks
+if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices),
+	error('plot_riftvel error message: vx and vy do not have the right size'),
+end
+if ~isstruct(md.rifts.riftstruct),
+	error('plot error message: no rifts available!');
+end
+options=addfielddefault(options,'scaling',2);
+
+%set as NaN all velocities not on rifts
+u=NaN*ones(md.mesh.numberofvertices,1);
+v=NaN*ones(md.mesh.numberofvertices,1);
+for i=1:size(md.rifts.riftstruct,1),
+	penaltypairs=md.rifts.riftstruct(i).penaltypairs(:,[1 2]);
+	u(penaltypairs(:))=md.initialization.vx(penaltypairs(:));
+	v(penaltypairs(:))=md.initialization.vy(penaltypairs(:));
+end
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[vel datatype]=processdata(md,[u v],options);
+[quivers,palette]=quiver_process(x,y,vel(:,1),vel(:,2),options);
+
+%prepare plot
+subplot(nlines,ncols,index); 
+hold on
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-');
+end
+
+%plot rifts vel
+h3=[];
+for i=1:quivers.numcolors
+	pos=find(quivers.colorind==i);
+	hprime=quiver(quivers.x(pos),quivers.y(pos),quivers.u(pos),quivers.v(pos),...
+		'Color',palette(i,:),'ShowArrowHead','on','AutoScale','off');
+	h3=[h3;hprime];
+end
+
+%plot rift velocities
+isp1=0;
+isp2=0;
+
+%plot mesh boundaries
+for i=1:size(md.mesh.segments,1),
+	h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-');
+end
+
+for i=1:size(md.rifts.riftstruct,1),
+	%get nodes on rift
+	penaltypairs=md.rifts.riftstruct(i).penaltypairs;
+
+	segments=md.rifts.riftstruct(i).segments;
+	for j=1:size(segments,1),
+		plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-');
+	end
+
+	normal=zeros(2,1);
+	for j=1:size(penaltypairs,1),
+		normal(1)=penaltypairs(j,5);
+		normal(2)=penaltypairs(j,6);
+
+		vx1=md.initialization.vx(penaltypairs(j,1)); vx2=md.initialization.vx(penaltypairs(j,2)); vy1=md.initialization.vy(penaltypairs(j,1)); vy2=md.initialization.vy(penaltypairs(j,2));
+		penetration=(vx2-vx1)*normal(1)+(vy2-vy1)*normal(2);
+		%if penetration is negative, plot in black, positive, plot in red;: ie: if rift is closing, black, if rift is opening, red.
+		if(penetration>0),
+			p2=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'*'); set(p2,'Color',[140 140 140]/255);
+			isp2=1;
+		else
+			p1=plot(x(penaltypairs(j,1)) ,y(penaltypairs(j,1)),'k*');
+			isp1=1;
+		end
+	end
+
+	%point out the tips
+	h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*');
+	plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*');
+	segments=md.rifts.riftstruct(i).segments(:,1:2);
+end
+
+
+%legend
+if isp1 & isp2
+	legend([h1,h2,p1,p2],'mesh boundaries','rift tips',' rifts closing','rifts opening')
+elseif isp1
+	legend([h1,h2,p1],'mesh boundaries','rift tips',' rifts closing')
+elseif isp2
+	legend([h1,h2,p2],'mesh boundaries','rift tips','rifts opening')
+else
+	legend([h1,h2],'mesh boundaries','rift tips')
+end
+hold off
+
+%apply options
+quiver_colorbar(quivers,options);
+options=changefieldvalue(options,'colorbar',2);
+options=addfielddefault(options,'title','Rift Velocities');
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_sarpwr.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_sarpwr.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_sarpwr.m	(revision 13009)
@@ -0,0 +1,26 @@
+function plot_sarpwr(md,options,width,i);
+%PLOT_SARPWR - plot radar image
+%
+%   Usage:
+%      plot_sarpwr(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh sarpwr
+subplot(width,width,i); 
+
+%units
+if exist(options,'unit'),
+	unit=getfieldvalue(options,'unit');
+	md.mesh.x=md.mesh.x*unit;
+	md.mesh.y=md.mesh.y*unit;
+	md.mesh.z=md.mesh.z*unit;
+end
+					
+imagesc(md.radaroverlay.x,md.radaroverlay.y,double(md.radaroverlay.pwr)),set(gca,'YDir','normal');colormap(gray);
+
+%apply options
+options=addfielddefault(options,'colorbar',0);
+options=changefieldvalue(options,'colormap','gray');
+
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_scatter.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_scatter.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_scatter.m	(revision 13009)
@@ -0,0 +1,74 @@
+function plot_scatter(x,y,mksize,level),
+
+%check input
+if numel(x)~=numel(y) | numel(x)~=numel(level),
+	error('x, y and data should have the same size');
+end
+
+%Some processing
+Min=min(level);
+Max=max(level);
+Siz=length(level);
+nlab=10;
+
+%OK, should we create a new colorbar for the occasion?
+if isempty(findobj(gcf,'tag','TMW_COLORBAR')),
+	alreadyplot=false;
+else
+	alreadyplot=true;
+end
+
+%generate levels
+if (alreadyplot),
+	phch = get(findall(gcf,'type','image','tag','TMW_COLORBAR'),{'parent'});
+	h    = phch{1};
+	ylim=get(h,'YLim');
+	palette=colormap;
+	numcolors=size(palette,1);
+	levels=round_ice(linspace(ylim(1),ylim(2),numcolors+1),2);
+else
+	numcolors=30;
+	levels=round_ice(linspace(Min,Max,numcolors+1),2);
+	palette=colormap(jet(numcolors));
+end
+
+colorind=ones(Siz,1);
+for i=1:numcolors
+	pos=find((level>=levels(i)) & (level<=levels(i+1)) );
+	colorind(pos)=i;
+end
+colorind(find(level>levels(end)))=numcolors;
+
+%loop over the number of colors
+hold on
+hp=[];
+for i=1:numcolors
+	pos=find(colorind==i);
+	hprime=plot(x(pos),y(pos),...
+		'o','MarkerSize',mksize,'MarkerEdgeColor',palette(i,:),...
+		'MarkerFaceColor',palette(i,:));
+	hp=[hp;hprime];
+end
+
+if ~alreadyplot,
+	% format the colorbar
+	h    = colorbar;
+	nlab = abs(nlab);                       % number of labels must be positive
+	set(h,'YLim',[1 numcolors]);                  % set colorbar limits
+	set(h,'YTick',linspace(1,numcolors,nlab));    % set tick mark locations
+
+	labels = cell(1,nlab);
+	tick_vals = linspace(Min,Max,nlab);
+	warning off MATLAB:log:logOfZero;
+	for i = 1:nlab
+		if min(log10(abs(tick_vals))) <= 3, fm = '%-4.0f';   % fixed
+		else                                fm = '%-4.0E';   % floating
+		end
+		labels{i} = sprintf(fm,tick_vals(i));
+	end
+	warning on MATLAB:log:logOfZero;
+
+	% set tick label strings
+	set(h,'YTickLabel',labels);
+	%colorbar %one last time required sometimes
+end
Index: /issm/trunk-jpl/src/m/plot/plot_section.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_section.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_section.m	(revision 13009)
@@ -0,0 +1,210 @@
+function plot_section(md,data,options,nlines,ncols,i)
+%PLOT_SECTION - plot a given field on a section
+%
+%   Usage:
+%      plot_section(md,data,options,nlines,ncols,i)
+%
+%   See also: PLOTMODEL
+
+%How many subplots?
+if exist(options,'showsection')
+
+	%Compute the indexes of the 2 plots (one for the sectionvalue and one for showsection
+	upperplots=floor((i-1)/ncols);
+	if upperplots==0, leftplots=i-1; else leftplots=i-ncols*upperplots-1; end
+	index1=4*ncols*upperplots+2*leftplots+1;
+	index2=index1+1;
+	ncols=2*ncols;
+else
+	index1=i;
+end
+
+%process model
+[x_m y_m z_m elements_m is2d isplanet]=processmesh(md,[],options);
+
+%Get number of curves and generate random colors
+numcurves=size(data,2);
+colorm=getfieldvalue(options,'colormap','lines');
+color=eval([ colorm '(numcurves);']);
+options=removefield(options,'colormap',0); %back to default colormap
+
+%replug x and y onto model so that SectionValue treats the problem correctly
+md3d=md;
+if exist(options,'layer')
+	md.mesh.x=md.mesh.x2d; md.mesh.y=md.mesh.y2d; md.mesh.elements=md.mesh.elements2d; md.mesh.dimension=2;
+end
+
+%read contours: 
+profiles=expread(getfieldvalue(options,'sectionvalue'));
+numprofiles=length(profiles);
+
+%Loop over number of profiles: 
+for profile_i=1:numprofiles,
+	profile=profiles(profile_i);
+
+	%Loop over number of curves
+	for i=1:numcurves,
+
+		[datai datatype]=processdata(md3d,data(:,i),options);
+
+		%resolution
+		if exist(options,'resolution'),
+			resolution=getfieldvalue(options,'resolution');
+		else %Default resolution
+			resolution=[1000 10*md.mesh.numberoflayers];
+			disp(['plot_section warning: no resolution specified, use default resolution: [horizontal_resolution vertical_resolution]=[' num2str(resolution)  ']']);
+		end
+
+		%Compute section value
+		[elements,x,y,z,s,data_s]=SectionValues(md,datai,profile,resolution);
+
+		%units
+		if exist(options,'unit'),
+			unit=getfieldvalue(options,'unit');
+			x=x*unit;
+			y=y*unit;
+			z=z*unit;
+			s=s*unit;
+		end
+
+		%2D
+		if is2d,
+%		%plot section value
+%		hold on;
+%		subplot(nlines,ncols,index1)
+%		%subplot(1,3,[2 3])
+%		plot(s,data_s,'color',color(i,:),'LineWidth',getfieldvalue(options,'linewidth',1))
+%		%3D
+%	else
+%		%plot section value
+%		%if user requested view2: 2d plot with curvilinear coordinate
+%		if (getfieldvalue(options,'view',3)==2 )
+
+			%Show Section if requested by user
+			if exist(options,'showsection')
+
+				%compute number of labels
+				numlabels=min(getfieldvalue(options,'showsection'),length(s));
+				shift=fix(length(s)/numlabels);
+
+				%plot labels on current graph
+				hold on
+				text(s(1),data_s(1),'1','backgroundcolor',[0.8 0.9 0.8])
+				for i=2:numlabels-1
+					text(s(1+(i-1)*shift),data_s(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+				end
+				text(s(end),data_s(end),'end','backgroundcolor',[0.8 0.9 0.8])
+
+				%plot section only with labels
+				subplot(nlines,ncols,index2)
+				plot_unit(x_m,y_m,z_m,elements_m,data(:,i),is2d,isplanet,datatype,options)
+				hold on
+				text(x(1),y(1),'1','backgroundcolor',[0.8 0.9 0.8])
+				for i=2:numlabels-1
+					text(x(1+(i-1)*shift),y(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+				end
+				text(x(end),y(end),'end','backgroundcolor',[0.8 0.9 0.8])
+				plot(x,y,'-r')
+				axis([min(md.mesh.x)-1 max(md.mesh.x)+1 min(md.mesh.y)-1 max(md.mesh.y)+1])
+				view(2)
+			end
+
+			%plot section value
+			if(i==1), subplot(nlines,ncols,index1); end
+			plot(s,data_s,'color',color(i,:),'LineWidth',getfieldvalue(options,'linewidth',1))
+			hold on
+
+
+			%3D
+		else
+			%plot section value
+			%if user requested view2: 2d plot with curvilinear coordinate
+			if (getfieldvalue(options,'view',3)==2 )
+
+				%Show Section if requested by user
+				if exist(options,'showsection')
+
+					%compute number of labels
+					numlabels=min(getfieldvalue(options,'showsection'),length(s));
+					shift=fix(length(s)/numlabels);
+
+					%plot labels on current graph
+					hold on
+					text(s(1),z(1),'1','backgroundcolor',[0.8 0.9 0.8])
+					for i=2:numlabels-1
+						text(s(1+(i-1)*shift),z(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+					end
+					text(s(end),z(end),'end','backgroundcolor',[0.8 0.9 0.8])
+
+					%plot section only with labels
+					subplot(nlines,ncols,index2)
+					plot_unit(x_m,y_m,z_m,elements_m,data(:,i),is2d,datatype,options)
+					hold on
+					text(x(1),y(1),'1','backgroundcolor',[0.8 0.9 0.8])
+					for i=2:numlabels-1
+						text(x(1+(i-1)*shift),y(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+					end
+					text(x(end),y(end),'end','backgroundcolor',[0.8 0.9 0.8])
+					plot(x,y,'-r')
+					axis([min(md.mesh.x)-1 max(md.mesh.x)+1 min(md.mesh.y)-1 max(md.mesh.y)+1])
+					view(2)
+				end
+
+				subplot(nlines,ncols,index1)
+				A=elements(:,1); B=elements(:,2); C=elements(:,3);  D=elements(:,4); 
+				patch( 'Faces', [A B C D], 'Vertices', [s z zeros(length(s),1)],'FaceVertexCData',data_s,'FaceColor','interp','EdgeColor','none');
+
+			else
+
+				%Show Section if requested by user
+				if exist(options,'showsection')
+
+					%compute number of labels
+					numlabels=min(getfieldvalue(options,'showsection'),length(s));
+					shift=fix(length(x)/numlabels);
+
+					%plot labels on current graph
+					hold on
+					text(x(1),y(1),z(1),'1','backgroundcolor',[0.8 0.9 0.8])
+					for i=2:numlabels-1
+						text(x(1+(i-1)*shift),y(1+(i-1)*shift),z(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+					end
+					text(x(end),y(end),z(end),'end','backgroundcolor',[0.8 0.9 0.8])
+
+					%plot section only with labels
+					subplot(nlines,ncols,index2)
+					plot_unit(x_m,y_m,z_m,elements_m,data,is2d,datatype,options)
+					hold on
+					text(x(1),y(1),'1','backgroundcolor',[0.8 0.9 0.8])
+					for i=2:numlabels-1
+						text(x(1+(i-1)*shift),y(1+(i-1)*shift),num2str(i),'backgroundcolor',[0.8 0.9 0.8])
+					end
+					text(x(end),y(end),'end','backgroundcolor',[0.8 0.9 0.8])
+					plot(x,y,'-r')
+					axis([min(md.mesh.x)-1 max(md.mesh.x)+1 min(md.mesh.y)-1 max(md.mesh.y)+1])
+					view(2)
+				end
+
+				subplot(nlines,ncols,index1)
+				A=elements(:,1); B=elements(:,2); C=elements(:,3);  D=elements(:,4); 
+				patch( 'Faces', [A B C D], 'Vertices', [x y z],'FaceVertexCData',data_s,'FaceColor','interp','EdgeColor','none');
+				view(3)
+
+			end
+		end
+	end
+end
+
+%apply options
+options=addfielddefault(options,'title','Section value');
+if (md.mesh.dimension==2)
+	options=addfielddefault(options,'colorbar',0);
+end
+if ((md.mesh.dimension==2) | getfieldvalue(options,'view')==2 )
+	options=addfielddefault(options,'xlabel','Curvilinear coordinate');
+	options=addfielddefault(options,'axis','auto');
+end
+if (md.mesh.dimension==3 & getfieldvalue(options,'view')==2 )
+	options=addfielddefault(options,'ylabel','z');
+end
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_segments.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_segments.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_segments.m	(revision 13009)
@@ -0,0 +1,57 @@
+function plot_segments(md,options,width,i,datai);
+%PLOT_SEGMENTS - plot segments, with different colors according to segment markers.
+%
+%   Usage:
+%      plot_segments(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%plot mesh boundaries
+subplot(width,width,i); 
+
+%process mesh and data
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+segments=md.mesh.segments;
+
+if (md.mesh.dimension==2),
+	%plot mesh
+	A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+	h1=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	hold on;
+
+	%highlight elements on neumann
+	pos=segments(:,end);
+	A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); 
+	h2=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black');
+
+	if strcmpi(getfieldvalue(options,'segmentnumbering','off'),'on'),
+		text(sum(x(segments(:,1:2)),2)/2,sum(y(segments(:,1:2)),2)/2,sum(z(segments(:,1:2)),2)/2+1,...
+			num2str(md.mesh.segmentmarkers),...
+			'backgroundcolor',[0.8 0.9 0.8],'HorizontalAlignment','center','VerticalAlignment','middle');
+	end
+
+	%display arrows pointing outward
+	xstart=mean(x(segments(:,1:end-1)),2);
+	ystart=mean(y(segments(:,1:end-1)),2);
+	length=sqrt((x(segments(:,1))-x(segments(:,2))).^2 + (y(segments(:,1))-y(segments(:,2))).^2 );
+	normal(:,1)=cos(atan2((x(segments(:,1))-x(segments(:,2))) , (y(segments(:,2))-y(segments(:,1)))));
+	normal(:,2)=sin(atan2((x(segments(:,1))-x(segments(:,2))) , (y(segments(:,2))-y(segments(:,1)))));
+	xend=xstart+length.*normal(:,1);
+	yend=ystart+length.*normal(:,2);
+	q=quiver(xstart,ystart,xend-xstart,yend-ystart); hold on;
+	h3=plot(xstart,ystart,'r*');
+
+
+else
+	error('plot_segments: 3d plot of segments not supported yet!');
+end
+
+%legend (disable warnings)
+warning off
+legend([h2,q],'element on segment','normal vectors')
+warning on
+
+%apply options
+options=addfielddefault(options,'title','Segment boundaries');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_streamlines.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_streamlines.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_streamlines.m	(revision 13009)
@@ -0,0 +1,41 @@
+function plot_streamlines(md,options)
+%PLOT_STREAMLINES - plot stream lines on a figure
+%
+%   Usage:
+%      plot_streamlines(md,options)
+
+%process data and model
+[x y z index is2d isplanet]=processmesh(md,[],options);
+[u datatype]=processdata(md,md.initialization.vx,options);
+[v datatype]=processdata(md,md.initialization.vy,options);
+
+%some checks
+if ~is2d,
+	disp('plot_streamlines error: streamlines option not supported for 3d plots. Project on a layer')
+	return
+end
+
+%initialize flowpath
+streamlines=getfieldvalue(options,'streamlines');
+if ischar(streamlines) & strcmpi(streamlines,'on');
+	streamlines=60;
+end
+if iscell(streamlines)
+	x0=[]; y0=[];
+	for i=1:size(streamlines,2)
+		coord=streamlines{i};
+		x0=[x0;coord(1)]; y0=[y0;coord(2)];
+	end
+else
+	x0=x(1:ceil(length(x)/streamlines):end);
+	y0=y(1:ceil(length(x)/streamlines):end);
+end
+
+%Get flow lines
+flowpath=flowlines(index,x,y,u,v,x0,y0);
+
+%plot
+hold on
+for i=1:length(flowpath)
+	patch('Xdata',[flowpath(i).x;NaN],'Ydata',[flowpath(i).y;NaN],'facecolor','none','edgecolor','y');
+end
Index: /issm/trunk-jpl/src/m/plot/plot_tensor.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_tensor.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_tensor.m	(revision 13009)
@@ -0,0 +1,40 @@
+function plot_tensor(md,options,width,i,type);
+%PLOT_TENSOR - plot tensor components
+%
+%   Usage:
+%      plot_tensor(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+h=subplot(width,width,i); axis off; pos=get(h,'Position');
+
+plot_options.offsetx=pos(1);
+plot_options.offsety=pos(2);
+plot_options.width=pos(3);
+plot_options.height=pos(4);
+
+%Figure out tensor type:
+%FIXME does not work anymore
+if strncmpi(type,'strain',6),
+	tensor=md.results.strainrate;
+elseif strncmpi(type,'stress',6),
+	tensor=md.results.stress;
+elseif strncmpi(type,'deviatoricstress',16),
+	tensor=md.results.deviatoricstress;
+else
+	error('plot_tensor error message: unsupported type of tensor');
+end
+
+%Figure out type of plot being requested
+if strncmpi(fliplr(type),fliplr('tensor'),6) | strcmpi(type,'strainrate') | strcmpi(type,'deviatoricstress') | strcmpi(type,'stress'),
+	plot_tensor_components(md,options,width,i,tensor,type,plot_options);
+	return;
+elseif strncmpi(fliplr(type),fliplr('principal'),9),
+	plot_tensor_principal(md,options,width,i,tensor,type,plot_options);
+	return;
+elseif strncmpi(fliplr(type(1:end-1)),fliplr('principalaxis'),13),
+	plot_tensor_principalaxis(md,options,width,i,tensor,type,plot_options);
+	return;
+else
+	error('plot_tensor error message: unsurported type of plot');
+end
Index: /issm/trunk-jpl/src/m/plot/plot_tensor_components.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_tensor_components.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_tensor_components.m	(revision 13009)
@@ -0,0 +1,78 @@
+function plot_tensor_components(md,options,width,i,tensor,type,plot_options);
+%PLOT_TENSOR_COMPONENT - plot component of a tensor
+%
+%   Usage:
+%      plot_tensor_components(md,options,width,i,tensor,type,plot_option);
+%
+%   See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
+
+%Compute the indexes of the components plots
+upperplots=fix((i-1)/width);
+if upperplots==0, leftplots=i-1; else leftplots=i-width*upperplots-1; end
+if (md.mesh.dimension==2)%3 components -> 3 indexes
+	index1=4*width*upperplots+2*leftplots+1;
+	index2=index1+1;
+	index3=index1+width*2;
+elseif md.mesh.dimension==3%6 components -> 6 indexes
+	index1=3*3*width*upperplots+3*leftplots+1;
+	index2=index1+1;
+	index3=index1+2;
+	index4=index1+width*3;
+	index5=index4+1;
+	index6=index4+2;
+end
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[tensor.xx datatype]=processdata(md,tensor.xx,options);
+[tensor.yy datatype]=processdata(md,tensor.yy,options);
+[tensor.xy datatype]=processdata(md,tensor.xy,options);
+if  md.mesh.dimension==3
+	[tensor.xz datatype]=processdata(md,tensor.xz,options);
+	[tensor.yz datatype]=processdata(md,tensor.yz,options);
+	[tensor.zz datatype]=processdata(md,tensor.zz,options);
+end
+
+if ((md.mesh.dimension==2)),
+	subplot(2*width,2*width,index1),
+	plot_unit(x,y,z,elements,tensor.xx,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'xx')
+	subplot(2*width,2*width,index2),
+	plot_unit(x,y,z,elements,tensor.yy,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'yy')
+	subplot(2*width,2*width,index3),
+	plot_unit(x,y,z,elements,tensor.xy,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'xy')
+else
+	subplot(3*width,3*width,index1),
+	plot_unit(x,y,z,elements,tensor.xx,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'xx')
+	subplot(3*width,3*width,index2),
+	plot_unit(x,y,z,elements,tensor.yy,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'yy')
+	subplot(3*width,3*width,index3),
+	plot_unit(x,y,z,elements,tensor.zz,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'zz')
+	subplot(3*width,3*width,index4),
+	plot_unit(x,y,z,elements,tensor.xy,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'xy')
+	subplot(3*width,3*width,index5),
+	plot_unit(x,y,z,elements,tensor.xz,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'xz')
+	subplot(3*width,3*width,index6),
+	plot_unit(x,y,z,elements,tensor.yz,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'yz')
+end
+end
+
+function Apply_options_tensor(md,options,type,component)
+	%apply options
+	if ismember('_',type) %user plotet stress_tensor
+		strings=strsplit(type,'_');
+		string=strings{1};
+	else %default plot: user requested stress
+		string=type;
+	end
+	options=addfielddefault(options,'title',[upper(string(1)) string(2:end) ' ' component]);
+	applyoptions(md,[],options);
+end
Index: /issm/trunk-jpl/src/m/plot/plot_tensor_principal.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_tensor_principal.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_tensor_principal.m	(revision 13009)
@@ -0,0 +1,77 @@
+function plot_tensor_principal(md,options,width,i,tensor,type,plot_options);
+%PLOT_TENSOR_PRINCIPAL - plot principal values
+%
+%   Usage:
+%      plot_tensor_principal(md,options,width,i,tensor,type,plot_options);
+%
+%   See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
+
+%Compute the indexes of the components plots
+upperplots=fix((i-1)/width);
+if upperplots==0, leftplots=i-1; else leftplots=i-width*upperplots-1; end
+if (md.mesh.dimension==2)%3 components -> 3 indexes
+	index1=4*width*upperplots+2*leftplots+1;
+	index2=index1+1;
+	index3=index1+width*2;
+	index4=index3+1;
+	newwidth=2*width;
+elseif md.mesh.dimension==3%6 components -> 6 indexes
+	index1=3*3*width*upperplots+3*leftplots+1;
+	index2=index1+1;
+	index3=index1+2;
+	index4=index1+width*3;
+	index5=index4+1;
+	index6=index4+2;
+	newwidth=3*width;
+end
+
+%plot principal axis
+type1=[type 'axis1'];
+plot_tensor_principalaxis(md,options,newwidth,index1,tensor,type1,plot_options);
+type2=[type 'axis2'];
+plot_tensor_principalaxis(md,options,newwidth,index2,tensor,type2,plot_options);
+if  md.mesh.dimension==3
+	type3=[type 'axis3'];
+	plot_tensor_principalaxis(md,options,newwidth,index3,tensor,type3,plot_options);
+end
+
+%now plot principal values
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[tensor.principalvalue1 datatype]=processdata(md,tensor.principalvalue1,options);
+[tensor.principalvalue2 datatype]=processdata(md,tensor.principalvalue2,options);
+if  md.mesh.dimension==3
+	[tensor.principalvalue3 datatype]=processdata(md,tensor.principalvalue3,options);
+end
+
+if ((md.mesh.dimension==2)),
+	subplot(2*width,2*width,index3)
+	plot_unit(x,y,z,elements,tensor.principalvalue1,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'principal value 1')
+	subplot(2*width,2*width,index4)
+	plot_unit(x,y,z,elements,tensor.principalvalue2,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'principal value 2')
+else
+	subplot(3*width,3*width,index4)
+	plot_unit(x,y,z,elements,tensor.principalvalue1,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'principal value 1')
+	subplot(3*width,3*width,index5)
+	plot_unit(x,y,z,elements,tensor.principalvalue2,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'principal value 2')
+	subplot(3*width,3*width,index6)
+	plot_unit(x,y,z,elements,tensor.principalvalue3,is2d,isplanet,datatype,options)
+	Apply_options_tensor(md,options,type,'principal value 3')
+end
+end
+
+function Apply_options_tensor(md,options,type,component)
+%apply options
+if ismember('_',type) %user plotet stress_tensor
+	strings=strsplit(type,'_');
+	string=strings{1};
+else %default plot: user requested stress
+	string=type;
+end
+options=addfielddefault(options,'title',[upper(string(1)) string(2:end) ' ' component]);
+options=changefieldvalue(options,'colorbar',2);
+applyoptions(md,[],options);
+end
Index: /issm/trunk-jpl/src/m/plot/plot_tensor_principalaxis.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_tensor_principalaxis.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_tensor_principalaxis.m	(revision 13009)
@@ -0,0 +1,95 @@
+function plot_tensor_principalaxis(md,options,width,i,tensor,type,plot_options);
+%PLOT_TENSOR_PRINCIPALAXIS - plot ytensor principal axis
+%
+%   Usage:
+%      plot_tensor_principalaxis(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%prepare subplot
+subplot(width,width,i); 
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+if ((md.mesh.dimension==2)),
+	eval(['Vx=tensor.principalaxis' type(end) '(:,1); Vy=tensor.principalaxis' type(end) '(:,2);'])
+	eval(['value=tensor.principalvalue' type(end) ';']);
+	[Vx datatype]=processdata(md,Vx,options);
+	[Vy datatype]=processdata(md,Vy,options);
+	[value datatype]=processdata(md,value,options);
+else
+	eval(['Vx=tensor.principalaxis' type(end) '(:,1); Vy=tensor.principalaxis' type(end) '(:,2); Vz=tensor.principalaxis' type(end) '(:,3);'])
+	[Vx datatype]=processdata(md,Vx,options);
+	[Vy datatype]=processdata(md,Vy,options);
+	[Vz datatype]=processdata(md,Vz,options);
+	[value datatype]=processdata(md,value,options);
+end
+
+%take the center of each element if ~isonnode
+if datatype==1,
+	x=mean(md.mesh.x(md.mesh.elements'))'; y=mean(md.mesh.y(md.mesh.elements'))'; z=mean(md.mesh.z(md.mesh.elements'))';
+end
+
+%plot quivers
+if (md.mesh.dimension==2),
+
+	%density
+	if exist(options,'density')
+		density=getfieldvalue(options,'density');
+		x=x(1:density:end);
+		y=y(1:density:end);
+		Vx=Vx(1:density:end);
+		Vy=Vy(1:density:end);
+		value=value(1:density:end);
+	end
+
+	%scaling:
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	scale=0.5/max(sqrt((Vx.^2+Vy.^2)/delta));
+	Vx=scale*Vx; Vy=scale*Vy;
+
+	pos=find(value>=0);
+	q1=quiver(x(pos),y(pos),Vx(pos),Vy(pos),'Color','r','ShowArrowHead','off','AutoScale','off');
+	hold on
+	pos=find(value<0);
+	q2=quiver(x(pos),y(pos),Vx(pos),Vy(pos),'Color','b','ShowArrowHead','off','AutoScale','off');
+
+else
+	%density
+	if exist(options,'density')
+		density=getfieldvalue(options,'density');
+		x=x(1:density:end);
+		y=y(1:density:end);
+		z=z(1:density:end);
+		Vx=Vx(1:density:end);
+		Vy=Vy(1:density:end);
+		Vz=Vz(1:density:end);
+		value=value(1:density:end);
+	end
+
+	%scaling:
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	scale=0.5/max(sqrt((Vx.^2+Vy.^2)/delta));
+	Vx=scale*Vx; Vy=scale*Vy; Vz=scale*Vz;
+
+	pos=find(value>=0);
+	q1=quiver3(x(pos),y(pos),z(pos),Vx(pos),Vy(pos),Vz(pos),'Color','r','ShowArrowHead','off','AutoScale','off');
+	hold on
+	pos=find(value<0);
+	q2=quiver3(x(pos),y(pos),z(pos),Vx(pos),Vy(pos),Vz(pos),'Color','b','ShowArrowHead','off','AutoScale','off');
+end
+
+%legend
+if strcmpi(type(1:6),'strain')
+	legend([q1 q2],'extension','compression')
+elseif strcmpi(type(1:6),'stress')
+	legend([q1 q2],'compression','traction')
+end
+
+%apply options
+strings=strsplit(type,'_');
+string=strings{1};
+options=addfielddefault(options,'title',[upper(string(1)) string(2:end) ' principal axis ' type(end)]);
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plot_thermaltransient_results.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_thermaltransient_results.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_thermaltransient_results.m	(revision 13009)
@@ -0,0 +1,24 @@
+function plot_thermaltransient_results(md,options,width,i)
+%PLOT_THERMALTRANSIENT_RESULTS - plot  results of a thermal transient solution
+%
+%   Usage:
+%      plot_thermaltransient_results(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+string='plot(md';
+for i=1:length(md.thermaltransient_results),
+	string=[string ',''data'',''thermaltransient_results(' num2str(i) ').temperature'',''view'',3,''title'',''Temperature at time ' num2str(md.thermaltransient_results(i).time) ' a'''];
+end
+string=[string ',''figure'',1,''colorbar#all'',''on'',''view'',3,''fontsize'',' num2str(options.fontsize) ',''fontweight'',' options.fontweight ');'];
+eval(string);
+clear string;
+
+string='plot(md';
+for i=2:length(md.thermaltransient_results),
+	string=[string ',''data'',md.thermaltransient_results(' num2str(i) ').temperature-md.thermaltransient_results(' num2str(i-1) ').temperature,''view'',3,''title'',''Delta temperature at time ' num2str(md.thermaltransient_results(i).time) ' a'''];
+end
+string=[string ',''figure'',2,''colorbar#all'',''on'',''fontsize'',' num2str(options.fontsize) ',''fontweight'',' options.fontweight ');'];
+eval(string);
+clear string;
+
Index: /issm/trunk-jpl/src/m/plot/plot_transient_field.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_transient_field.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_transient_field.m	(revision 13009)
@@ -0,0 +1,43 @@
+function plot_transient_field(md,options,width,i,data)
+%PLOT_TRANSIENT_FIELD - plot transient results
+%
+%   Usage:
+%      plot_transient_field(md,options,width,i,data);
+%
+%   See also: PLOTMODEL
+
+%Check that they are transient results
+if (~isfield(md.results,'TransientSolution')),
+	error('plot_transient_field error message: no transient results in the model');
+end
+
+%Figure out the iterations to plot and check if it is possible
+transient=md.results.TransientSolution;
+maxiteration=size(transient,2);
+steps=getfieldvalue(options,'steps',1:1:maxiteration);
+
+if max(steps)>maxiteration | min(steps)<1,
+	error(['plot_transient_field error message: problem with the steps requested, must be an interger between 0 and ' num2str(maxiteration)]);
+end
+subplotwidth=ceil(sqrt(length(steps)));
+
+%Figure out the field to plot
+
+field=getfieldvalue(options,'field','Vel');
+
+%process mes only once
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+
+%plot data for all steps
+for i=1:length(steps),
+
+	%process data and change title if needed
+	[data datatype]=processdata(md,transient(steps(i)).(field),options);
+	options=changefieldvalue(options,'title',[field ' at time ' num2str(transient(steps(i)).time/md.constants.yts) ' a']);
+
+	%create plot of step i
+	subplot(subplotwidth,subplotwidth,i);
+	plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options)
+	applyoptions(md,data,options);
+
+end
Index: /issm/trunk-jpl/src/m/plot/plot_transient_movie.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_transient_movie.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_transient_movie.m	(revision 13009)
@@ -0,0 +1,70 @@
+function plot_transient_movie(md,options,width,i);
+%PLOT_TRANSIENT_MOVIE - plot a transient result as a movie
+%   Usage:
+%      plot_transient_movie(md,options,width,i);
+%
+%   See also: PLOTMODEL, PLOT_UNIT, PLOT_MANAGER
+
+	%prepare subplot
+	subplot(width,width,i); 
+
+	%xlim
+	if exist(options,'transient_movie_field'),
+		field=getfieldvalue(options,'transient_movie_field');
+	else
+		error('specify transient_movie_field in options list');
+	end
+
+	results=md.results.TransientSolution;
+	%loop over the time steps
+	if exist(options,'transient_movie_limit'),
+		limit=getfieldvalue(options,'transient_movie_limit');
+		steps=[limit(1):limit(end)];
+	else
+		steps=1:length(results);
+	end
+	results=md.results.TransientSolution;
+	nstep=1;
+	for i=steps
+
+		if ~isempty(results(i).(field)),
+			%process data
+			[x y z elements is2d isplanet]=processmesh(md,results(i).(field),options);
+			[data datatype]=processdata(md,results(i).(field),options);
+
+			titlestring=[field ' at time ' num2str(results(i).time/md.constants.yts) ' year'];
+			plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options)
+			apply_options_movie(md,options,titlestring);
+
+			if exist(options,'transient_movie_output'),
+				set(gcf,'Renderer','zbuffer','color','white'); %fixes a bug on Mac OS X (not needed in future Matlab version)
+				if nstep==1,
+					%initialize images and frame
+					frame=getframe(gcf);
+					[images,map]=rgb2ind(frame.cdata,256,'nodither');
+					images(1,1,1,length(steps))=0;
+				else
+					frame=getframe(gcf);
+					images(:,:,1,nstep) = rgb2ind(frame.cdata,map,'nodither');
+				end
+			else
+				pause(0.1)
+			end
+			nstep=nstep+1;
+		end
+	end
+
+	%output movie if requested.
+	if exist(options,'transient_movie_output'),
+		filename=getfieldvalue(options,'transient_movie_output');
+		imwrite(images,map,filename,'DelayTime',getfieldvalue(options,'transient_movie_time',2),'LoopCount',inf)
+	end
+
+end %function
+
+function apply_options_movie(md,options,titlestring)
+	%apply options
+	options=addfielddefault(options,'title',titlestring);
+	options=addfielddefault(options,'colorbar',1);
+	applyoptions(md,[],options);
+end
Index: /issm/trunk-jpl/src/m/plot/plot_transient_results.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_transient_results.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_transient_results.m	(revision 13009)
@@ -0,0 +1,77 @@
+function plot_transient_results(md,options,width,i)
+%PLOT_TRANSIENT_RESULTS - plot transient results
+%
+%   Usage:
+%      plot_transient_results(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+fontsize=getfieldvalue(options,'fontsize',14);
+fontweight=getfieldvalue(options,'fontweight','n');
+
+%Prepare window distribution
+%Get screen geometry
+mp = get(0, 'MonitorPositions');
+%Build window sizes
+if size(mp,1)>=2        %several monitors, use the second one
+	bdwidth=mp(2,1)+5; topbdwidth=mp(2,2)+20; W=mp(2,3)/3; H=mp(2,4)/2;
+else                    %only one monitor
+	bdwidth=5;         topbdwidth=20;         W=mp(1,3)/3; H=mp(1,4)/2;
+end
+pos1=[bdwidth  H+bdwidth  W-2*bdwidth  H-bdwidth-topbdwidth];
+pos2=pos1+[W 0 0 0]; pos3=pos1+[2*W 0 0 0]; pos4=pos1+[0 -H 0 0]; pos5=pos1+[W -H 0 0]; pos6=pos1+[2*W -H 0 0];
+%Create windows
+figure(1);close;
+figure('Position',pos1); figure('Position',pos2);figure('Position',pos3);figure('Position',pos4);figure('Position',pos5);figure('Position',pos6);
+
+string='plotmodel(md';
+for i=1:length(md.results.transient),
+	string=[string ',''data'',md.results.transient(' num2str(i) ').thickness,''title'',''Thickness at time ' num2str(md.results.transient(i).time) ' a'''];
+end
+string=[string ',''figure'',1,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');'];
+eval(string);
+clear string;
+
+string='plotmodel(md';
+for i=1:length(md.results.transient),
+	string=[string ',''data'',md.results.transient(' num2str(i) ').vel,''view'',3,''title'',''Velocity at time ' num2str(md.results.transient(i).time) ' a'''];
+end
+string=[string ',''figure'',2,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight  ''');'];
+eval(string);
+clear string;
+
+if md.mesh.dimension==3,
+	string='plotmodel(md';
+	for i=1:length(md.results.transient),
+		string=[string ',''data'',md.results.transient(' num2str(i) ').temperature,''view'',3,''title'',''Temperature at time ' num2str(md.results.transient(i).time) ' a'''];
+	end
+	string=[string ',''figure'',3,''colorbar#all'',''on'',''view'',3,''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight  ''');'];
+	eval(string);
+	clear string;
+end
+
+string='plotmodel(md';
+for i=2:length(md.results.transient),
+	string=[string ',''data'',md.results.transient(' num2str(i) ').thickness-md.results.transient(' num2str(i-1) ').thickness,''title'',''Delta thickness at time ' num2str(md.results.transient(i).time) ' a'''];
+end
+string=[string ',''figure'',4,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight  ''');'];
+eval(string);
+clear string;
+
+string='plotmodel(md';
+for i=2:length(md.results.transient),
+	string=[string ',''data'',md.results.transient(' num2str(i) ').vel-md.results.transient(' num2str(i-1) ').vel,''view'',3,''title'',''Delta velocity at time ' num2str(md.results.transient(i).time) ' a'''];
+end
+string=[string ',''figure'',5,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight  ''');'];
+eval(string);
+clear string;
+
+if md.mesh.dimension==3,
+	string='plotmodel(md';
+	for i=2:length(md.results.transient),
+		string=[string ',''data'',md.results.transient(' num2str(i) ').temperature-md.results.transient(' num2str(i-1) ').temperature,''view'',3,''title'',''Delta temperature at time ' num2str(md.results.transient(i).time) ' a'''];
+	end
+	string=[string ',''figure'',6,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight  ''');'];
+	eval(string);
+	clear string;
+end
Index: /issm/trunk-jpl/src/m/plot/plot_unit.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_unit.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_unit.m	(revision 13009)
@@ -0,0 +1,92 @@
+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=getfieldvalue(options,'edgecolor','none');
+
+switch datatype,
+
+	%element plot
+	case 1,
+
+		pos=find(~isnan(data)); %needed for element on water
+		if is2d,
+			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);
+		else
+			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);
+		end
+
+	%node plot
+	case 2,
+
+		if is2d,
+			A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+			patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+		else
+			if ~isplanet,
+				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
+				A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+				if size(elements,2)==4, D=elements(:,4); else D=C; end
+				patch( 'Faces', [A B C D],  'Vertices', [x y z],'FaceVertexCData', data(:),'FaceColor','interp','EdgeColor',edgecolor);
+			end
+		end
+
+	%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);
+		end
+
+	%Patch plot P1
+	case 4,
+
+		if is2d,
+			patch( 'Faces',elements,'Vertices',[x y],'CData',data,'FaceColor','interp','EdgeColor',edgecolor);
+		else
+			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],'CData', data,'FaceColor','interp','EdgeColor',edgecolor);
+			patch( 'Faces', [D E F], 'Vertices', [x y z],'CData', data,'FaceColor','interp','EdgeColor',edgecolor);
+			patch( 'Faces', [A B E D], 'Vertices', [x y z],'CData', data,'FaceColor','interp','EdgeColor',edgecolor);
+			patch( 'Faces', [B E F C ], 'Vertices', [x y z],'CData', data,'FaceColor','interp','EdgeColor',edgecolor);
+			patch( 'Faces', [C A D F ], 'Vertices', [x y z],'CData', data,'FaceColor','interp','EdgeColor',edgecolor);
+		end
+
+	%Patch plot P0
+	case 5,
+
+		if is2d,
+			A=elements(:,1); B=elements(:,2); C=elements(:,3); 
+			patch( 'Faces', [A B C], 'Vertices', [x y z],'CData', data(:),'FaceColor','flat','EdgeColor',edgecolor);
+		else
+			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],'CData', data,'FaceColor','flat','EdgeColor',edgecolor);
+			patch( 'Faces', [D E F],  'Vertices', [x y z],'CData', data,'FaceColor','flat','EdgeColor',edgecolor);
+			patch( 'Faces', [A B E D],'Vertices', [x y z],'CData', data,'FaceColor','flat','EdgeColor',edgecolor);
+			patch( 'Faces', [B E F C],'Vertices', [x y z],'CData', data,'FaceColor','flat','EdgeColor',edgecolor);
+			patch( 'Faces', [C A D F],'Vertices', [x y z],'CData', data,'FaceColor','flat','EdgeColor',edgecolor);
+		end
+
+	otherwise,
+		error(['case ' num2str(datatype) ' not supported']);
+
+	end
+end
Index: /issm/trunk-jpl/src/m/plot/plot_vertexnumbering.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_vertexnumbering.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plot_vertexnumbering.m	(revision 13009)
@@ -0,0 +1,51 @@
+function plot_vertexnumbering(md,options,width,i);
+%PLOT_VERTEXNUMBERING - plot vertex numbering
+%
+%   Usage:
+%      plot_vertexnumbering(md,options,width,i);
+%
+%   See also: PLOTMODEL
+
+%process data and model
+[x y z elements is2d isplanet]=processmesh(md,[],options);
+[vertexnumbers datatype]=processdata(md,[1:md.mesh.numberofvertices]',options);
+
+%plot
+subplot(width,width,i); 
+
+if is2d
+	%plot mesh 
+	A=elements(:,1); B=elements(:,2); C=elements(:,3);
+	patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%numbering
+	text(x,y,z,num2str(transpose(1:size(x,1))),...
+		'backgroundcolor',[0.8 0.9 0.8],'HorizontalAlignment','center','VerticalAlignment','middle');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	text(x(pos),y(pos),z(pos),num2str(transpose(pos)),...
+		'backgroundcolor',[1 0 0],'HorizontalAlignment','center','VerticalAlignment','middle');
+else
+	%plot mesh 
+	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', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [D E F],  'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [A B E D],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [B E F C],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+	patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black');
+
+	%numbering
+	text(x,y,z,num2str(transpose(1:size(x,1))),...
+		'backgroundcolor',[0.8 0.9 0.8],'HorizontalAlignment','center','VerticalAlignment','middle');
+
+	%Highlight
+	pos=getfieldvalue(options,'highlight',[]);
+	text(x(pos),y(pos),z(pos),num2str(transpose(pos)),...
+		'backgroundcolor',[1 0 0],'HorizontalAlignment','center','VerticalAlignment','middle');
+end
+
+%apply options
+options=addfielddefault(options,'title','Node numbering');
+options=addfielddefault(options,'colorbar',0);
+applyoptions(md,[],options);
Index: /issm/trunk-jpl/src/m/plot/plotdoc.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plotdoc.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plotdoc.m	(revision 13009)
@@ -0,0 +1,174 @@
+function plotdoc()
+%PLOTDOC - plot documentation
+%
+%   Usage:
+%      plotdoc()
+
+disp(' ');
+disp('   Plot usage: plotm(model,varargin)');
+disp('   Options: ');
+disp('       ''figure'': figure number');
+disp('       ''data'' : what we want to plot');
+disp('                Available values for ''data'' are: ');
+disp('                  - any field of the model structure. ex: plot(md,''data'',''vel''), or plot(md,''data'',md.initialization.vel)');
+disp('                  - ''basal_drag'': plot the basal drag on the bed (in kPa)');
+disp('                  - ''basal_dragx'' or ''basal_dragy'' : plot a component of the basal drag on the bed (in kPa)');
+disp('                  - ''boundaries'': this will draw all the segment boundaries to the model, including rifts.');
+disp('                  - ''icefront'': this will show segments that are used to define the icefront of the model (Neumann boundary conditions).');
+disp('                  - ''BC'': this will draw all the boundary conditions (Dirichlet and Neumann).');
+disp('                  - ''deviatoricstress_tensor'': plot the components of the deviatoric stress tensor (tauxx,tauyy,tauzz,tauxy,tauxz,tauyz) if computed');
+disp('                  - ''deviatoricstress_principal'': plot the deviatoricstress tensor principal axis and principal values');
+disp('                  - ''deviatoricstress_principalaxis1'': arrow plot the first principal axis of the deviatoricstress tensor(replace 1 by 2 or 3 if needed)');
+disp('                  - ''driving_stress'': plot the driving stress (in kPa)');
+disp('                  - ''elements_type'': model used for each element');
+disp('                  - ''elementnumbering'': numbering of elements');
+disp('                  - ''vertexnumbering'': numbering of vertices');
+disp('                  - ''highlightelements'': to highlight elements to highlight the element list');
+disp('                  - ''highlightvertices'': to highlight vertices (use highlight option to enter the vertex list');
+disp('                  - ''mesh'': draw mesh using trisurf');
+disp('                  - ''referential'': diagnostic referential');
+disp('                  - ''riftvel'': velocities along rifts');
+disp('                  - ''riftrelvel'': relative velocities along rifts');
+disp('                  - ''riftpenetration'': penetration levels for a fault');
+disp('                  - ''riftfraction'': fill fractions for every node of the rifts');
+disp('                  - ''rifts'': plot mesh with an offset so that rifts are visible');
+disp('                  - ''strainrate_tensor'': plot the components of the strainrate tensor (exx,eyy,ezz,exy,exz,eyz) if computed');
+disp('                  - ''strainrate_principal'': plot the strainrate tensor principal axis and principal values)');
+disp('                  - ''strainrate_principalaxis1'': arrow plot the first principal axis of the strainrate tensor(replace 1 by 2 or 3 if needed)');
+disp('                  - ''stress_tensor'': plot the components of stress tensor (sxx,syy,szz,sxy,sxz,syz) if computed');
+disp('                  - ''stress_principal'': plot the stress tensor principal axis and principal values');
+disp('                  - ''stress_principalaxis1'': arrow plot the first principal axis of the stress tensor(replace 1 by 2 or 3 if needed)');
+disp('                  - ''transient_results'': this will display all the time steps of a transient run (use steps to specify the steps requested)');
+disp('                  - ''transient_vel'': this will display the velocity for the time steps requested in ''steps'' of a transient run');
+disp('                  - ''transient_vel'': vel can be by any field of the transient results (vx, vy, vz, vel, temperature, melting, pressure, bed, thickness, surface)');
+disp('                  - ''transient_field'': dynamic plot of results. specify ''steps'' option, as fell as ''field'' (defaults are all steps, for ''Vel'' field)');
+disp('                  - ''transient_movie'': this will display the time steps of a given field of a transient run');
+disp('                  - ''transient_movie_field'': field to be displayed when doing  transient_movie data display');
+disp('                  - ''transient_movie_output'': filename if output is desired for movie');
+disp('                  - ''transient_movie_time'': time for each image (default 2 seconds)');
+disp('                  - ''thermaltransient_results'': this will display all the time steps of a thermal transient run');
+disp('                  - ''qmuhistnorm'': histogram normal distribution. needs option qmudata');
+disp('                  - ''qmumean'': plot of mean distribution in sampling analysis with scaled response. needs option qmudata for descriptor');
+disp('                  - ''qmustddev'': plot of stddev distribution in sampling analysis with scaled response. needs option qmudata for descriptor');
+disp('                  - ''part_hist'': partitioning node and area histogram');
+disp('                  - ''quiver'': quiver plot');
+
+disp('       ''alloptions'': apply the options to all subplots if ''on''');
+disp('       ''axis'': same as standard matlab option (''equal'',''off'',''equal on'',...)');
+disp('       ''basin'': zoom on a given basin (''pineislandglacier'',''ronneiceshelf'', use isbasin to identify a basin');
+disp('                 ''hemisphere'': specify +1 or -1');
+disp('                 ''basindeltax'': in m');
+disp('                 ''showbasins'': write lables for every existing basin name around the center of the plot');
+disp('       ''caxis'': modify  colorbar range. (array of type [a b] where b>=a)');
+disp('       ''backgroundcolor'': plot background color. (default is ''w'')');
+disp('       ''figurebackgroundcolor'': figure background color. (default is ''none'')');
+disp('       ''coord'':  ''xy'' (default) or ''latlon''');
+disp('       ''colorlevels'':  N or {value1,valu2,value3,...} used if quiver, use different colors for the given number of colors or limits');
+disp('       ''colorbar'': add colorbar (string ''on'' or ''off'')');
+disp('       ''colorbartitle'': colorbar title (string)');
+disp('       ''colorbarYlabel'': colorbar Y label (string)');
+disp('       ''colorbarpos'': [x,y,dx,dy] where x,y,dx and dy are within [0 1]');
+disp('       ''colorbarcornerposition'': ''West'',''North'',etc ...');
+disp('       ''colorbartitlerotation'': -90, etc ...');
+disp('       ''colorbarfontsize'': specify colorbar fontsize');
+disp('       ''colorbarwidth'': multiplier (default 1) to the default width colorbar');
+disp('       ''colorbarheight'': multiplier (default 1) to the default height colorbar');
+disp('       ''colormap'': same as standard matlab option (''jet'',''hsv'',''cool'',''spring'',''gray'',''Ala'',''Rignot'',...)');
+disp('       ''contourlevels'': N or {value1,valu2,value3,...} add the contours of the specified values or N contours');
+disp('       ''contourticks'': ''on'' or ''off'' to display the ticks of the contours');
+disp('       ''contouronly'': ''on'' or ''off'' to display the contours on a white background');
+disp('       ''contourcolor'': ticks and contour color');
+disp('       ''density'': density of quivers (one arrow every N nodes, N integer)');
+disp('       ''inset'': add an inset (zoom) of the current figure if 1 (use ''insetx'', ''insety'' and ''insetpos'' to determine the inset position and content)');
+disp('       ''insetx'': [min(x) max(x)] where min(x) and max(x) are values determining the inset content');
+disp('       ''insety'': [min(y) max(y)] where min(y) and max(y) are values determining the inset content');
+disp('       ''insetpos'': [x,y,dx,dy] where x,y,dx and dy are within [0 1]');
+disp('       ''streamlines'': N (number of stream lines) or {[x1 y1],...} (coordinates of seed points) add streanlines on current figure');
+disp('       ''edgecolor'': same as standard matlab option EdgeColor (color name: ''black'' or RGB array: [0.5 0.2 0.8])');
+disp('       ''fontsize'': same as standard matlab option (10,14,...)');
+disp('       ''fontweight'': same as standard matlab option (normal: ''n'',bold: ''b'',light: ''l'',demi: ''d'')');
+disp('       ''fontcolor'': same as standard matlab option');
+disp('       ''highlight'': highlights certain nodes or elements when using ''nodenumbering'' or ''elementnumbering'' or ''highlightnodes '' or ''highlightelements'' option');
+disp('       ''resolution'': resolution used by section value (array of type [horizontal_resolution vertical_resolution])');
+disp('                       horizontal_resolution must be in meter, and vertical_resolution a number of layers');
+disp('       ''showsection'': show section used by ''sectionvalue'' (string ''on'' or a number of labels)');
+disp('       ''sectionvalue'': give the value of data on a profile given by an Argus file (string ''Argusfile_name.exp'')');
+disp('       ''profile'': give the value of data along a vertical profile ([xlocation ylocation])');
+disp('       ''smooth'': smooth element data (string ''yes'' or integer)');
+disp('       ''title'': same as standard matlab option');
+disp('       ''view'': same as standard matlab option (ex: 2, 3 or [90 180]');
+disp('       ''xlim'': same as standard matlab option (ex: [0 500])');
+disp('       ''ylim'': same as standard matlab option');
+disp('       ''zlim'': same as standard matlab option');
+disp('       ''xlabel'': same as standard matlab option (ex:''km'')');
+disp('       ''ylabel'': same as standard matlab option');
+disp('       ''xticklabel'': specifiy xticklabel');
+disp('       ''yticklabel'': specifiy yticklabel');
+disp('       ''overlay'': yes or no. This will overlay a radar amplitude image behind');
+disp('       ''overlay_image'': path to overlay image. provide overlay_xlim, overlay_ylim, overlay_xposting and overlay_yposting options also');
+disp('       ''contrast'': (default 1) coefficient to add contrast to the radar amplitude image used in overlays');
+disp('       ''highres'': resolution of overlayed radar amplitude image (default is 0, high resolution is 1).');
+disp('       ''hem'': specify hemisphere ''n'' or ''s'' (default is ''s'').');
+disp('       ''alpha'': transparency coefficient (the higher, the more transparent). Default is 1.5');
+disp('       ''scaling'': scaling factor used by quiver plots. Default is 0.4');
+disp('       ''autoscale'': set to ''off'' to have all the quivers with the same size. Default is ''on''');
+disp('       ''expdisp'': plot exp file on top of a data plot. provide exp file as an argument (use a cell of strings if more than one)');
+disp('       ''expstyle'': marker style for expdisp plot (use a cell of strings if more than one)');
+disp('       ''linewidth'': line width for expdisp plot');
+disp('       ''border'': size of display border (in pixels). active only for overlay plots');
+disp('       ''text'': print string, use a cell of strings if more than one');
+disp('       ''textposition'': [x y] position of text, use a cell of strings if more than one');
+disp('       ''textsize'':  same as standard ''FontSize'' matlab option applied to text, use a cell of strings if more than one');
+disp('       ''textweight'':  same as standard ''FontWeight'' matlab option applied to text, use a cell of strings if more than one');
+disp('       ''textcolor'':  same as standard ''color'' matlab option applied to text, use a cell of strings if more than one');
+disp('       ''textrotation'':  same as standard ''Rotation'' matlab option applied to text, use a cell of strings if more than one');
+disp('       ''mask'': list of flags of size numberofnodes or numberofelements. Only ''true'' values are plotted ');
+disp('       ''nan'': value assigned to NaNs (convenient when plotting BC)');
+disp('       ''partitionedges'': ''off'' by default. overlay plot of partition edges');
+disp('       ''log'': value of log');
+disp('       ''latlon'': ''on'' or {latstep lonstep [resolution [color]]} where latstep,longstep and resolution are in degrees, color is a [r g b] array');
+disp('       ''latlonnumbering'': ''on'' or {latgap longap colornumber latangle lonangle} where latgap and longap are pixel gaps for the numbers,'); 
+disp('       ''latlonclick'': ''on'' to click on latlon ticks positions');
+disp('                   colornumber is a [r g b] array and latangle and lonangle are angles to flip the numbers');
+disp('       ''northarrow'': add an arrow pointing north, ''on'' for default value or [x0 y0 length [ratio width fontsize]] where (x0,y0) are the coordinates of the base, ratio=headlength/length');
+disp('       ''offset'': mesh offset used by ''rifts'', default is 500');
+disp('       ''scaleruler'': add a scale ruler, ''on'' for default value or [x0 y0 length width numberofticks] where (x0,y0) are the coordinates of the lower left corner');
+disp('       ''showregion'': show domain in Antarctica on an inset, use ''insetpos'' properties');
+disp('       ''visible'': ''off'' to make figure unvisible, default is ''on''');
+disp('       ''wrapping'': repeat ''n'' times the colormap (''n'' must be an integer)');
+disp('       ''unit'': by default, in m, otherwise, ''km'' is available');
+disp('       ''legend_position'': by default, ''NorthEasth''');
+disp('       ''qmudata'': data for qmu  plots.');
+disp('                  {dresp1   ,dresp2  ,hmin,hmax,hnint} or {samp,desc,mu,sigma,hmin,hmax,hnint}');
+disp('                  where dresp1 is a structure array of responses (where we need samp and desc), ');
+disp('                  dresp2 is a structure array of responses (where we only need mu and sigma)');
+disp('                  hmin,hmax and hnint are the minimum, maximum and number of intervals of the histogram (optional)');
+disp('       ''figposition'': position of figure: ''fullscreen'', ''halfright'', ''halfleft'', ''portrait'', ''landscape'',... (hardcoded in applyoptions.m)');
+disp('       ''offsetaxispos'': offset of current axis position to get more space (ex: [-0.02 0  0.04 0])');
+disp('       ''axispos'': axis position to get more space');
+disp('       ''hmin'': (numeric, minimum for histogram)');
+disp('       ''hmax'': (numeric, maximum for histogram)');
+disp('       ''hnint'': (numeric, number of intervals for histogram)');
+disp('       ''ymin1'': (numeric, minimum of histogram y-axis)');
+disp('       ''ymax1'': (numeric, maximum of histogram y-axis)');
+disp('       ''ymin2'': (numeric, minimum of cdf y-axis)');
+disp('       ''ymax2'': (numeric, maximum of cdf y-axis)');
+disp('       ''cdfplt'': (char, ''off'' to turn off cdf line plots)');
+disp('       ''cdfleg'': (char, ''off'' to turn off cdf legends)');
+disp('       ''segmentnumbering'': (''off'' by default)');
+disp('       ''kmlgroundoverlay'': (''off'' by default)');
+disp('       ''kmlfilename'': (''tempfile.kml'' by default)');
+disp('       ''kmlroot'': (''./'' by default)');
+disp('       ''kmlimagename'': (''tempimage'' by default)');
+disp('       ''kmlimagetype'': (''png'' by default)');
+disp('       ''kmlresolution'': (1 by default)');
+disp('       ''kmlfolder'': (''Ground Overlay'' by default)');
+disp('       ''kmlfolderdescription'': ('''' by default)');
+disp('       ''kmlgroundoverlayname'': ('''' by default)');
+disp('       ''kmlgroundoverlaydescription'': ('''' by default)');
+
+disp('       any options (except ''data'') can be followed by ''#i'' where ''i'' is the subplot number, or ''#all'' if applied to all plots');
+disp('  ');
+disp('   Examples:');
+disp('       plotmodel(md,''data'',''vel'',''data'',''mesh'',''view#2'',3,''colorbar#all'',''on'',''axis#1'',''off equal'')');
+disp('       plotmodel(md,''data'',''highlightelements'',''highlight'',[1 4 10],''expdisp'',{''domain1.exp'' ''domain2.exp'' ''domain3.exp''})');
Index: /issm/trunk-jpl/src/m/plot/plotmodel.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/plotmodel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/plotmodel.m	(revision 13009)
@@ -0,0 +1,57 @@
+function plotmodel(md,varargin)
+%At command prompt, type plotdoc for help on documentation.
+
+%First process options
+options=plotoptions(varargin{:});
+
+%get number of subplots
+subplotwidth=ceil(sqrt(options.numberofplots));
+
+%if nlines and ncols specified, then bypass.
+if exist(options.list{1},'nlines'),
+	nlines=getfieldvalue(options.list{1},'nlines');
+else 
+	nlines=subplotwidth;
+end
+
+if exist(options.list{1},'ncols'),
+	ncols=getfieldvalue(options.list{1},'ncols');
+else 
+	ncols=subplotwidth;
+end
+
+%check that nlines and ncols were given at the same time!
+if ((exist(options.list{1},'ncols') & ~exist(options.list{1},'ncols')) | (~exist(options.list{1},'ncols') & exist(options.list{1},'ncols')))
+	error('plotmodel error message: nlines and ncols  need to be specified together, or not at all');
+end
+
+%Get figure number and number of plots
+figurenumber=options.figurenumber;
+numberofplots=options.numberofplots;
+
+%go through subplots
+if numberofplots,
+		
+	%Create figure 
+	if strcmpi(getfieldvalue(options.list{1},'visible','on'),'off'),
+		F=figure(figurenumber);clf;
+		set(F,'Visible','Off');
+	else
+		figure(figurenumber);clf;
+	end
+
+	%Use zbuffer renderer (snoother colors)
+	set(gcf,'Renderer','zbuffer');
+
+	%Go through all data plottable and close window if an error occurs
+	try,
+		for i=1:numberofplots,
+			plot_manager(getfieldvalue(options.list{i},'model',md),options.list{i},subplotwidth,nlines,ncols,i);
+		end
+	catch me,
+		%figure(figurenumber),close;
+		rethrow(me);
+	end
+else
+	error('plotmodel error message: no output data found. ');
+end
Index: /issm/trunk-jpl/src/m/plot/processdata.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/processdata.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/processdata.m	(revision 13009)
@@ -0,0 +1,203 @@
+function [data datatype]=processdata(md,data,options);
+%PROCESSDATA - process data to be plotted
+%
+%   datatype = 1 -> elements
+%   datatype = 2 -> nodes
+%   datatype = 3 -> node quivers
+%   datatype = 4 -> patch
+%
+%   Usage:
+%      [data datatype]=processdata(md,data,options);
+%
+%   See also: PLOTMODEL, PROCESSMESH
+
+%check format
+if (iscell(data) | isempty(data) | length(data)==0 | (length(data)==1 & ~isstruct(data) & isnan(data))),
+	error('plotmodel error message: data provided is empty');
+end
+
+%needed later on
+if isfield(md.mesh,'numberofvertices2d'), 
+	numberofvertices2d=md.mesh.numberofvertices2d; 
+	numberofelements2d=md.mesh.numberofelements2d; 
+else 
+	numberofvertices2d=NaN;
+	numberofelements2d=NaN;
+end
+
+%Process Patch
+if isstruct(data) 
+	if (isfield(data,'index') & isfield(data,'value')),
+		if data.interpolation(1)==P1Enum(),
+			data=data.value;
+			data=data';
+			data=data(:);
+			datatype=4;
+		elseif data.interpolation(1)==P0Enum(),
+			data=data.value;
+			datatype=5;
+		else
+			error(['interpolation ' data.interpolation(1) ' not supported yet']);
+		end
+	else
+		error('structure other than Patch not supported yet');
+	end
+else
+	%initialize datatype
+	datatype=0;
+end
+
+%get datatype
+datasize=size(data);
+
+%Process NaN if any (do not now before mask is applied)
+if exist(options,'nan')
+	data(find(isnan(data)))=getfieldvalue(options,'nan',0);
+end
+%non patch processing
+if datatype~=4 & datatype~=5,
+
+	%transpose data if necessary
+	if (size(data,2) > size(data,1)),
+		data=data';
+	end
+	datasize=size(data);
+
+	%convert to double if necessary
+	if ~isnumeric(data);
+		disp('processdata info message: data is not numeric (logical?). Converted to double');
+		data=double(data);
+	end
+
+	%check length
+	
+	if datasize(1)~=md.mesh.numberofvertices & datasize(1)~=md.mesh.numberofelements & datasize(1)~=md.mesh.numberofvertices*6 & (md.mesh.dimension==3 & ~(datasize(1)==numberofelements2d | datasize(1)==numberofvertices2d))
+		error('plotmodel error message: data not supported yet');
+	end
+	
+	%quiver?
+	if datasize(2)>1,
+		datatype=3;
+
+		%check number of columns, add zeros if necessary,
+		if (md.mesh.dimension==3)
+			if datasize(2)==2,
+				data=[data, zeros(datasize(1),1)];
+			elseif datasize(2)~=3,
+				error('plotmodel error message: data provided should have 2 or 3 columns for quiver plot, and 1 for regular plot');
+			end
+		%elseif ((md.mesh.dimension==2) & datasize(2)~=2),
+		%	error('plotmodel error message: data provided should have 2 columns for quiver plot, and 1 for regular plot');
+		end
+	end
+
+	%treat the case datasize(1)=6*nodes
+	if datasize(1)==6*md.mesh.numberofvertices
+		%keep the only norm of data
+		data1=data(1:6:md.mesh.numberofvertices*6,:);
+		data2=data(2:6:md.mesh.numberofvertices*6,:);
+		data=sqrt(data1.^2+data2.^2);
+		datasize(1)=md.mesh.numberofvertices;
+		%---> go to node data
+	end
+
+	%treat the case datasize(1)=nodes2d
+	if (md.mesh.dimension==3 & datasize(1)==numberofvertices2d),
+		data=project3d(md,'vector',data,'type','node');
+		datasize(1)=md.mesh.numberofvertices;
+		%---> go to node data
+	end
+
+	%treat the case datasize(1)=nodes2d
+	if (md.mesh.dimension==3 & datasize(1)==numberofelements2d),
+		data=project3d(md,'vector',data,'type','element');
+		datasize(1)=md.mesh.numberofelements;
+		%---> go to node data
+	end
+
+	%smoothing?
+	if exist(options,'smooth')
+		data=averaging(md,data,getfieldvalue(options,'smooth'));
+		datasize(1)=md.mesh.numberofvertices;
+		%---> go to node data
+	end
+end
+
+%element data
+if (datasize(1)==md.mesh.numberofelements & datasize(2)==1),
+
+	%Initialize datatype if non patch
+	if datatype~=4 & datatype~=5,
+		datatype=1;
+	end
+
+	%Mask?
+	if exist(options,'mask'),
+		flags=getfieldvalue(options,'mask');
+		pos=find(~flags);
+		if length(flags)==md.mesh.numberofvertices,
+			[pos2 dummy]=find(ismember(md.mesh.elements,pos));
+			data(pos2,:)=NaN;
+		elseif length(flags)==md.mesh.numberofelements
+			data(pos,:)=NaN;
+		else
+			disp('plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements');
+		end
+	end
+
+	%log?
+	if exist(options,'log'),
+		bounds=getfieldvalue(options,'caxis',[min(data(:)) max(data(:))]);
+		data(find(data<bounds(1)))=bounds(1);
+		if any(data<=0),
+			error('Log option cannot be applied on negative values. Use caxis option (Rignot''s settings: [1.5 max(data)])');
+		end
+		pos=find(~isnan(data));
+		data(pos)=log(data(pos))/log(getfieldvalue(options,'log'));
+	end
+end
+
+%node data
+if (datasize(1)==md.mesh.numberofvertices & datasize(2)==1),
+	datatype=2;
+
+	%Mask?
+	if exist(options,'mask'),
+		flags=getfieldvalue(options,'mask');
+		pos=find(~flags);
+		if length(flags)==md.mesh.numberofvertices,
+			data(pos,:)=NaN;
+		elseif length(flags)==md.mesh.numberofelements
+			data(md.mesh.elements(pos,:),:)=NaN;
+		else
+			disp('plotmodel warning: mask length not supported yet (supported length are md.mesh.numberofvertices and md.mesh.numberofelements');
+		end
+	end
+
+	%log?
+	if exist(options,'log'),
+		%if any(data<=0),
+		%	error('Log option cannot be applied on negative values. Use caxis option (Rignot''s settings: [1.5 max(data)])');
+		%end
+		data=log(data)/log(getfieldvalue(options,'log'));
+	end
+end
+
+%layer projection? 
+if getfieldvalue(options,'layer',0)>=1,
+	data=project2d(md,data,getfieldvalue(options,'layer')); %project onto 2d mesh
+end
+
+%control arrow density if quiverplot
+if datatype==3 & exist(options,'density')
+	databak=data;
+	data=NaN*ones(datasize);
+	density=getfieldvalue(options,'density');
+	data(1:density:end,:)=databak(1:density:end,:);
+	clear databak
+end
+
+%OK, if datatype=0 error out
+if datatype==0,
+	error(['data provided not recognized or not supported']);
+end
Index: /issm/trunk-jpl/src/m/plot/processmesh.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/processmesh.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/processmesh.m	(revision 13009)
@@ -0,0 +1,98 @@
+function [x y z elements is2d isplanet]=processmesh(md,data,options);
+%PROCESSMESH - process mesh to be plotted
+%
+%   Usage:
+%      [x y z elements is2d]=processmesh(md,data,options)
+%
+%   See also: PLOTMODEL, PROCESSDATA
+
+%some checks
+if md.mesh.numberofvertices==0,
+	error('plot error message: mesh is empty')
+end
+if md.mesh.numberofvertices==md.mesh.numberofelements
+	error(['plot error message: the number of elements is the same as the number of nodes...']);
+end
+
+if (isempty(data) | ~isstruct(data)),
+	%first load x,y, etc ... to speed up plot
+
+	if ~strcmpi(getfieldvalue(options,'coord','xy'),'latlon'),
+		x=md.mesh.x;
+		if isfield(md.mesh,'x2d'), x2d=md.mesh.x2d; end
+		y=md.mesh.y;
+		if isfield(md.mesh,'y2d'), y2d=md.mesh.y2d; end
+	else
+		x=md.mesh.long;
+		%x2d=md.mesh.x2d; this sounds like something that was forgotten
+		y=md.mesh.lat;
+		%y2d=md.mesh.y2d;
+	end
+
+	z_field=getfieldvalue(options,'z',md.mesh.z);
+	if ischar(z_field),
+		z=md.(z_field);
+	elseif isnumeric(z_field),
+		z=z_field;
+	else
+		z=md.mesh.z;
+	end
+
+
+	if isfield(md.mesh,'elements2d'), elements2d=md.mesh.elements2d; end
+	elements=md.mesh.elements;
+
+	%is it a 2d plot?
+	if (md.mesh.dimension==2);
+		is2d=1;
+	elseif (md.mesh.dimension==3),
+		if getfieldvalue(options,'layer',0)>=1,
+			is2d=1;
+		else
+			is2d=0;
+		end
+	else
+		error(['dim = ' num2str(md.mesh.dimension) ' not supported yet']);
+	end
+
+	%layer projection? 
+	if getfieldvalue(options,'layer',0)>=1,
+		if strcmpi(getfieldvalue(options,'coord','xy'),'latlon'),
+			error('processmesh error message: cannot work with 3D meshes for now');
+		end
+		%we modify the mesh temporarily to a 2d mesh from which the 3d mesh was extruded. 
+		x=x2d;
+		y=y2d;
+		z=zeros(size(x2d));
+		elements=elements2d;
+	end
+else
+	%Process Patch
+	if (md.mesh.dimension==2),
+		elements=transpose(reshape(1:3*md.mesh.numberofelements,3,md.mesh.numberofelements));
+		x=transpose(reshape(md.mesh.x(data.index)',1,3*md.mesh.numberofelements));
+		y=transpose(reshape(md.mesh.y(data.index)',1,3*md.mesh.numberofelements));
+		z=zeros(3*md.mesh.numberofelements,1);
+		is2d=1;
+	else
+		elements=transpose(reshape(1:6*md.mesh.numberofelements,6,md.mesh.numberofelements));
+		x=transpose(reshape(md.mesh.x(data.index)',1,6*md.mesh.numberofelements));
+		y=transpose(reshape(md.mesh.y(data.index)',1,6*md.mesh.numberofelements));
+		z=transpose(reshape(md.mesh.z(data.index)',1,6*md.mesh.numberofelements));
+		is2d=0;
+	end
+end
+
+%units
+if exist(options,'unit'),
+	unit=getfieldvalue(options,'unit');
+	x=x*unit;
+	y=y*unit;
+	z=z*unit;
+end
+
+if isa(md,'planet'),
+	isplanet=1;
+else
+	isplanet=0;
+end
Index: /issm/trunk-jpl/src/m/plot/quiver_colorbar.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/quiver_colorbar.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/quiver_colorbar.m	(revision 13009)
@@ -0,0 +1,41 @@
+function quiver_colorbar(quivers,options)
+%QUIVER_COLORBAR - colorbar for quiver plots
+%
+%   Usage:
+%      quiver_colorbar(quivers,options)
+
+if  strcmpi(getfieldvalue(options,'colorbar','on'),'on'),
+
+	%build ticks
+	hcb=colorbar('peer',gca,'location','EastOutside');
+	ticklabel=cell(1,length(quivers.levels));
+	for i=1:length(quivers.levels),
+		ticklabel{i}=num2str(round_ice(quivers.levels(i),3));
+	end
+	tickpos=1:quivers.numcolors+1;
+
+	%remove ticks if to many have been created
+	proportion=round(length(quivers.levels)/4);
+	if proportion>1,
+		ticklabel=ticklabel(1:proportion:end);
+		tickpos=tickpos(1:proportion:end);
+	end
+
+	%draw colorbar
+	set(hcb,'YTickLabel',ticklabel,'YTick',tickpos);
+	%position
+	if exist(options,'colorbarpos'),
+		set(hcb,'Position',getfieldvalue(options,'colorbarpos'));
+	end
+	%fontsize
+	fontsize=getfieldvalue(options,'fontsize',14);
+	set(hcb,'FontSize',fontsize);
+	
+	if exist(options,'colorbartitle'),
+		backup=gca;
+		axes(hcb);lab=title(getfieldvalue(options,'colorbartitle'));
+		set(lab,'Rotation',getfieldvalue(options,'colorbartitlerotation',0));
+		set(lab,'VerticalAlignment','bottom');
+		axes(backup);
+	end
+end
Index: /issm/trunk-jpl/src/m/plot/quiver_process.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/quiver_process.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/quiver_process.m	(revision 13009)
@@ -0,0 +1,70 @@
+function [quivers,palette]=quiver_process(x,y,u,v,options)
+%QUIVER_PROCESS - process data for color quiver plot
+%
+%   Usage:
+%      [quivers,palette]=quiver_process(x,y,u,v,options)
+
+%keep only non NaN elements
+pos=find(~isnan(x) & ~isnan(y) & ~isnan(u) & ~isnan(v));
+x=x(pos); y=y(pos);
+u=u(pos); v=v(pos);
+
+%get Norm Min and Max
+Norm=sqrt(u.^2+v.^2);
+Min=min(Norm);
+Max=max(Norm);
+
+%Scale data
+scalingfactor=getfieldvalue(options,'scaling',0.40);
+if strcmpi(getfieldvalue(options,'autoscale','on'),'off'),
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	u=scalingfactor*sqrt(delta)*u./Norm;
+	v=scalingfactor*sqrt(delta)*v./Norm;
+else
+	delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x);
+	u=scalingfactor*sqrt(delta)*u./max(Norm);
+	v=scalingfactor*sqrt(delta)*v./max(Norm);
+end
+
+%number of colors?
+colorlevels=getfieldvalue(options,'colorlevels',30);
+if isnumeric(colorlevels),
+	if isnan(colorlevels),
+		numcolors=30;
+	else
+		numcolors=colorlevels;
+	end
+	levels=round_ice(linspace(Min,Max,numcolors+1),2);
+else
+	levels=zeros(1,length(colorlevels)+2);
+	levels(1)=Min;
+	for i=1:length(colorlevels)
+		levels(i+1)=colorlevels{i};
+	end
+	levels(end)=Max;
+	levels=sort(unique(levels));
+	numcolors=length(levels)-1;
+end
+
+%create colorind for colors
+colorind=ones(length(u),1);
+for i=1:numcolors
+	pos=find((Norm>=levels(i)) & (Norm<=levels(i+1)) );
+	colorind(pos)=i;
+end
+colorind(find(Norm>levels(end)))=numcolors;
+
+%build output
+quivers=struct('x',x,'y',y,'u',u,'v',v,'levels',levels,'colorind',colorind,'numcolors',numcolors);
+
+%set the colormap 
+if numcolors==2;
+	%blue and red
+	palette=colormap([0 0 1;1 0 0]);
+elseif numcolors==3,
+	%blue yellow and red
+	palette=colormap([0 0 1;1 1 0;1 0 0]);
+else
+	%let jet choose
+	palette=colormap(jet(numcolors));
+end
Index: /issm/trunk-jpl/src/m/plot/radarpower.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/radarpower.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/radarpower.m	(revision 13009)
@@ -0,0 +1,118 @@
+function md=radarpower(md,varargin)
+%RADARPOWER - overlay a power radar image on an existing mesh
+%
+%   This routine will overlay a power radar image on an existing mesh.
+%   The power amplitude will be output to vel for now.
+%   In the future, think about a field to hold this value.
+%
+%   Usage:
+%      md=radarpower(md,options);
+%      md=radarpower(md)
+
+%If gdal does not work, uncomment the following line
+%setenv('LD_LIBRARY_PATH','/proj/ice/larour/issm/trunk/externalpackages/gdal/install/lib/');
+%Parse inputs
+if nargin==1,
+	options=pairoptions;
+else
+	options=varargin{:};
+	if ~isa(options,'pairoptions'),
+		options=pairoptions(varargin{:});
+	end
+end
+
+highres=getfieldvalue(options,'highres',0);
+xlim=getfieldvalue(options,'xlim',[min(md.mesh.x) max(md.mesh.x)]);
+ylim=getfieldvalue(options,'ylim',[min(md.mesh.y) max(md.mesh.y)]);
+posting=getfieldvalue(options,'posting',0); % 0 -> image posting default
+
+%find gdal coordinates
+x0=min(xlim); x1=max(xlim);
+y0=min(ylim); y1=max(ylim);
+
+%figure out if we should go look for Greenland or Antarctica geotiff, or if user provided one.
+if ~exist(options,'overlay_image'),
+	if strcmpi(md.mesh.hemisphere,'n'),
+		if ~exist([jplsvn() '/projects/ModelData/MOG/mog150_greenland_map.jpg']),
+			error(['radarpower error message: file ' jplsvn() '/projects/ModelData/MOG/mog150_greenland_map.jpg not found.']);
+		end
+		name = 'mog150_greenland_map';
+		%name = 'mog100_hp1_v10';
+		%name = 'mog500_hp1_v10';
+		jpgim=[jplsvn() '/projects/ModelData/MOG/' name '.jpg'];
+		geom=load([jplsvn() '/projects/ModelData/MOG/' name '.jpgw'],'ascii');
+
+		%geom:   xposting nbcols nbrows yposting xmin ymax
+		xmin=max(geom(5),x0);
+		xmax=min(geom(5)+geom(1)*geom(2),x1);
+		ymin=max(geom(6)-geom(3)*geom(4),y0);
+		ymax=min(geom(6),y1);
+
+		firstcol=max(1,floor((xmin-geom(5))/geom(1))); %x min
+		firstrow=max(1,floor((geom(6)-ymax)/geom(4))); %y max
+		numcols=floor((xmax-xmin)/geom(1)); % x posting
+		numrows=floor((ymax-ymin)/geom(4)); % y posting
+		pixelskip=max(1,ceil(posting/geom(1)));
+
+		%Read and crop file
+		disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+		im=imread(jpgim);
+		im=im(firstrow:firstrow+numrows-1,firstcol:firstcol+numcols-1);
+		md.radaroverlay.pwr=double(flipud(im(1:pixelskip:end,1:pixelskip:end)));
+		md.radaroverlay.x=(xmin:(xmax-xmin)/(size(md.radaroverlay.pwr,2)-1):xmax);
+		md.radaroverlay.y=(ymin:(ymax-ymin)/(size(md.radaroverlay.pwr,1)-1):ymax);
+
+	elseif strcmpi(md.mesh.hemisphere,'s'),
+		if highres,
+			if ~exist([jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_200m.tif']),
+				error(['radarpower error message: file ' jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_200m.tif not found.']);
+			end
+			geotiff_name=[jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_200m.tif'];
+		else
+			if ~exist([jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_1km.tif']),
+				error(['radarpower error message: file ' jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_1km.tif not found.']);
+			end
+			geotiff_name=[jplsvn() '/projects/ModelData/MosaicTiffRsat/amm125m_v2_1km.tif'];
+		end
+
+		%Name of image
+		inputname='./temp.tif';
+		eval(['!gdal_translate -quiet -projwin ' num2str(x0) ' ' num2str(y1) ' ' num2str(x1) ' ' num2str(y0) ' ' geotiff_name ' ' inputname ]);
+
+		%Read in temp.tif:
+		im=imread('temp.tif','TIFF');
+		pixelskip=max(1,ceil(posting/((x1-x0)/(size(im,2)))));
+		md.radaroverlay.pwr=double(flipud(im(1:pixelskip:end,1:pixelskip:end)));
+		md.radaroverlay.x=(x0:(x1-x0)/(size(md.radaroverlay.pwr,2)-1):x1);
+		md.radaroverlay.y=(y0:(y1-y0)/(size(md.radaroverlay.pwr,1)-1):y1);
+
+		%Erase image
+		system('rm -rf ./temp.tif');
+
+	else
+		error('field hemisphere should either be ''n'' or ''s''');
+	end
+else
+	%ok, user provided an image. check we also have overlay_xlim and overlay_ylim  options, to know what range of coordinates the image covers.
+	if (~exist(options,'overlay_xlim') | ~exist(options,'overlay_xlim')| ~exist(options,'overlay_xposting')| ~exist(options,'overlay_yposting')),
+		error('radarpower error message: please provide overlay_xlim, overlay_ylim, overlay_xposting and overlay_yposting options together with overlay_image option');
+	end
+	overlay_image=getfieldvalue(options,'overlay_image');
+	overlay_xlim=getfieldvalue(options,'overlay_xlim');
+	overlay_ylim=getfieldvalue(options,'overlay_ylim');
+	overlay_xposting=getfieldvalue(options,'overlay_xposting');
+	overlay_yposting=getfieldvalue(options,'overlay_yposting');
+
+	sizex=floor((x1-x0)/overlay_xposting);
+	sizey=floor((y1-y0)/overlay_yposting);
+	topleftx=floor((x0-overlay_xlim(1))/overlay_xposting); % x min
+	toplefty=floor((overlay_ylim(2)-y1)/overlay_yposting); % y max
+
+	%Read and crop file
+	disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+	im=imread(overlay_image);
+	im=im(toplefty:toplefty+sizey,topleftx:topleftx+sizex);
+	md.radaroverlay.pwr=double(flipud(im));
+	md.radaroverlay.x=(x0:(x1-x0)/(size(md.radaroverlay.pwr,2)-1):x1);
+	md.radaroverlay.y=(y0:(y1-y0)/(size(md.radaroverlay.pwr,1)-1):y1);
+end
Index: /issm/trunk-jpl/src/m/plot/scaleruler.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/scaleruler.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/scaleruler.m	(revision 13009)
@@ -0,0 +1,61 @@
+function scaleruler(options)
+%SCALERULER - overlay a scale ruler on current plot
+%
+%   Usage:
+%      scaleruler(options)
+
+%get options
+structure=getfieldvalue(options,'scaleruler');
+fontsize=getfieldvalue(options,'scaleruler_fontsize',16);
+
+%Go through structure and fill missing arguments
+if length(structure)~=5
+	error('plotmodel error message: bad number of input arguments for scaleruler: [x0 y0 length thickness numberofticks]');
+end
+
+%retrieve north arrow parameters
+x0=structure(1);
+y0=structure(2);
+lengthscale=structure(3);
+widthscale=structure(4);
+numberofticks=structure(5);
+
+%initialize some coordinates
+unitlength=lengthscale/(numberofticks -1);
+flag=-1;
+
+Bd=[x0 y0];
+Bu=[x0 y0+widthscale];
+Tick=0;
+
+%Text
+xt=Bu(1);
+yt=Bu(2)+widthscale;
+text(xt,yt,num2str(Tick),'FontSize',fontsize,'FontWeight','n','HorizontalAlignment','left','VerticalAlignment','baseline');
+
+%loope over the patches
+for i=1:numberofticks-1,
+	Au=Bu;
+	Ad=Bd;
+	Bu=[Au(1)+unitlength Ad(2)+widthscale];
+	Bd=[Ad(1)+unitlength Ad(2)];
+	Tick=Tick+unitlength;
+
+	%pathes
+	if flag==-1
+		p=patch([Ad(1) Bd(1) Bu(1) Au(1)],[Ad(2) Bd(2) Bu(2) Au(2)],'Black','FaceAlpha',0.5);
+	else
+		p=patch([Ad(1) Bd(1) Bu(1) Au(1)],[Ad(2) Bd(2) Bu(2) Au(2)],'White','FaceAlpha',0.3);
+	end
+
+	%flip flag
+	flag=-flag;
+
+	%Text
+	xt=Bu(1);
+	yt=Bu(2)+widthscale;
+	if i~=numberofticks-1,
+		text(xt,yt,num2str(round_ice(Tick/1000,3)),'FontSize',fontsize,'FontWeight','n','HorizontalAlignment','left','VerticalAlignment','baseline');
+	end
+end
+text(xt,yt,[num2str(round_ice(Tick/1000,3)) ' km'],'FontSize',fontsize,'FontWeight','n','HorizontalAlignment','left','VerticalAlignment','baseline');
Index: /issm/trunk-jpl/src/m/plot/showregion.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/showregion.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/showregion.m	(revision 13009)
@@ -0,0 +1,34 @@
+function showregion(md,insetpos)
+%SHOWREGION - show region on plot
+%
+%   Usage:
+%      showregion(md,insetpos);
+
+%get inset relative position (x,y,width,height)
+%insetpos=getfieldvalue(options,'insetpos',[0.02 0.70 0.18 0.18]);
+
+%get current plos position
+cplotpos=get(gca,'pos');
+%compute inset position
+PosInset=[cplotpos(1)+insetpos(1)*cplotpos(3),cplotpos(2)+insetpos(2)*cplotpos(4), insetpos(3)*cplotpos(3), insetpos(4)*cplotpos(4)];
+axes('pos',PosInset);
+axis equal off
+%box off
+if strcmpi(md.mesh.hemisphere,'n') | strcmpi(md.mesh.hemisphere,'north'),
+	A=expread([issmdir() 'projects/Exp/Greenland.exp']);
+elseif strcmpi(md.mesh.hemisphere,'s') | strcmpi(md.mesh.hemisphere,'south'),
+	A=expread([issmdir() '/projects/Exp/Antarctica.exp']);
+else
+	error('applyoptions error message: hemisphere not defined');
+end
+
+Ax=[min(A.x) max(A.x)];
+Ay=[min(A.y) max(A.y)];
+
+mdx=[min(md.mesh.x) max(md.mesh.x)];
+mdy=[min(md.mesh.y) max(md.mesh.y)];
+
+line(A.x,A.y,'color','b');
+patch([Ax(1)  Ax(2)  Ax(2)  Ax(1) Ax(1)],[Ay(1)  Ay(1)  Ay(2)  Ay(2) Ay(1)],[1 1 1],'EdgeColor',[0 0 0],'LineWidth',1,'FaceLighting','none')
+patch( [mdx(1) mdx(2) mdx(2) mdx(1)],[mdy(1) mdy(1) mdy(2) mdy(2)],ones(4,1),'EdgeColor',[0 0 0],'FaceColor','r','FaceAlpha',0.5)
+colorbar('off');
Index: /issm/trunk-jpl/src/m/plot/subplotmodel.m
===================================================================
--- /issm/trunk-jpl/src/m/plot/subplotmodel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/plot/subplotmodel.m	(revision 13009)
@@ -0,0 +1,35 @@
+function ha=subplotmodel(nlines,ncols,num,options);
+%SUBPLOTMODEL -  tight subplot that includes margins
+%
+%   Usage:
+%      h=subplotmodel(nlines,ncols,i,options)
+
+%Regular subplot
+if ~exist(options,'tightsubplot')
+	subplot(nlines,ncols,num);
+	return;
+end
+
+gap     = getfieldvalue(options,'gap',[.01 .01]);
+hmargin = getfieldvalue(options,'hmargin',[.01 .01]);
+vmargin = getfieldvalue(options,'vmargin',[.01 .01]);
+
+height = (1-sum(vmargin)-(nlines-1)*gap(1))/nlines; 
+width  = (1-sum(hmargin)-(ncols-1)*gap(2))/ncols;
+ymin   = 1-vmargin(2)-height; 
+
+for i = 1:nlines
+	xmin = hmargin(1);
+	for j = 1:ncols
+		if(((i-1)*ncols+j)==num)
+			ha = axes('Units','normalized', ...
+				'Position',[xmin ymin width height],'XTickLabel','','YTickLabel','','Visible','off');
+			return
+		end
+		xmin = xmin+width+gap(2);
+	end
+	ymin = ymin-height-gap(1);
+end
+
+%Activate new axes
+axes(ha);
Index: /issm/trunk-jpl/src/m/print/printmodel.m
===================================================================
--- /issm/trunk-jpl/src/m/print/printmodel.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/print/printmodel.m	(revision 13009)
@@ -0,0 +1,100 @@
+function printmodel(filename,format,varargin)
+%PRINTMODEL - save an image of current figure
+%
+%   filename: output name of image file (no extension)
+%   format: image format (ex: 'tiff','jpg','pdf') 
+%
+%   List of options to printfmodel: 
+%
+%   figure: number of figure to print (default: current figure)
+%   resolution: use higher resolution to anti-alias (default 2)
+%   margin: add margin around final image  
+%   marginsize: size of margin around final image (default 5)
+%   frame: add frame around final image
+%   framesize: size of frame around final image (default 5)
+%   framecolor: color of frame around final image (default 'black')
+%   trim: trim empty space around image (default 'off')
+%   hardcopy: 'off' to impose MATLAB to use the same colors (default 'off')
+%   
+%   Usage:
+%      printmodel(filename,format,varargin);
+%
+%   Examples:
+%      printmodel('image','tiff')
+%      printmodel('image','eps','margin','on','frame','on','hardcopy','on')
+
+
+%get options: 
+options=pairoptions(varargin{:});
+
+%set defaults
+options=addfielddefault(options,'figure','gcf');
+options=addfielddefault(options,'format','tiff');
+options=addfielddefault(options,'resolution',1);
+options=addfielddefault(options,'margin','on');
+options=addfielddefault(options,'marginsize',25);
+options=addfielddefault(options,'frame','on');
+options=addfielddefault(options,'framesize',3);
+options=addfielddefault(options,'framecolor','black');
+options=addfielddefault(options,'trim','on');
+options=addfielddefault(options,'hardcopy','off');
+
+%get fig: 
+fig=getfieldvalue(options,'figure');
+if ischar(fig),
+	fig=gcf;
+else
+	figure(fig);
+	fig=gcf;
+end
+
+%In auto mode, MATLAB prints the figure the same size as it appears on the computer screen, centered on the page
+set(fig, 'PaperPositionMode', 'auto');
+
+%InvertHardcopy off imposes MATLAB to use the same colors
+set(fig, 'InvertHardcopy', getfieldvalue(options,'hardcopy'));
+
+
+%we could have several formats, as a cell array of strings.
+formats=format;
+if ~iscell(formats),
+	formats={formats};
+end
+
+%loop on formats:
+for i=1:length(formats),
+	format=formats{i};
+
+	%Use higher resolution to anti-alias and use zbuffer to have smooth colors
+	print(fig, '-zbuffer','-dtiff',['-r' num2str(get(0,'ScreenPixelsPerInch')*getfieldvalue(options,'resolution'))],filename);
+
+	%some trimming involved? 
+	if ~strcmpi(format,'pdf'),
+		if strcmpi(getfieldvalue(options,'trim'),'on'),
+			system(['convert -trim ' filename '.tif ' filename '.tif']);
+		end
+	end
+
+	%margin?
+	if ~strcmpi(format,'pdf'),
+		if strcmpi(getfieldvalue(options,'margin'),'on'),
+			marginsize=getfieldvalue(options,'marginsize');
+			system(['convert -border ' num2str(marginsize) 'x' num2str(marginsize) ' -bordercolor "white" ' filename '.tif ' filename '.tif']);
+		end
+	end
+
+	%frame?
+	if ~strcmpi(format,'pdf'),
+		if strcmpi(getfieldvalue(options,'frame'),'on'),
+			framesize=getfieldvalue(options,'framesize');
+			framecolor=getfieldvalue(options,'framecolor');
+			system(['convert -border ' num2str(framesize) 'x' num2str(framesize) ' -bordercolor "' framecolor '" ' filename '.tif ' filename '.tif']);
+		end
+	end
+
+	%convert image to correct format
+	if ~strcmpi(format,'tiff') & ~strcmpi(format,'tif'),
+		system(['convert ' filename '.tif ' filename '.' format]);
+		delete([ filename '.tif']);
+	end
+end
Index: /issm/trunk-jpl/src/m/regional/BasinConstrain.m
===================================================================
--- /issm/trunk-jpl/src/m/regional/BasinConstrain.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/regional/BasinConstrain.m	(revision 13009)
@@ -0,0 +1,63 @@
+function md=BasinConstrain(md,domain);
+%BASINCONSTRAIN - constrain basin
+%
+%   Constrain basin using a constraint domain outline, 
+%   to dirichlet boundary conditions.
+%   constraindomain is an Argus domain outline file enclosing 
+%   the geographical area of interest.
+%
+%   Usage: 
+%      md=BasinConstrain(md,constraindomain)
+%
+%   Example:
+%      md=BasinConstrain(md,'DomainOutline.exp');
+%      md=BasinConstrain(md,'~Iceshelves.exp');
+
+%now, flag nodes and elements outside the domain outline.
+if ischar(domain),
+	if isempty(domain),
+		elementondomain=zeros(md.mesh.numberofelements,1);
+		vertexondomain=zeros(md.mesh.numberofvertices,1);
+		invert=0;
+	elseif strcmpi(domain,'all')
+		elementondomain=ones(md.mesh.numberofelements,1);
+		vertexondomain=ones(md.mesh.numberofvertices,1);
+		invert=0;
+	else
+		%make sure that we actually don't want the elements outside the domain outline!
+		if strcmpi(domain(1),'~'),
+			domain=domain(2:end);
+			invert=1;
+		else
+			invert=0;
+		end
+		%ok, flag elements and nodes
+		[vertexondomain elementondomain]=ContourToMesh(md.mesh.elements(:,1:3),md.mesh.x,md.mesh.y,domain,'element and node',2);
+	end
+	if invert,
+		vertexondomain=~vertexondomain;
+		elementondomain=~elementondomain;
+	end
+else
+	error('BasinConstrain error message: domain type not supported yet');
+end
+
+%list of elements and nodes not on domain
+vertexnotondomain=find(~vertexondomain);
+elementnotondomain=find(~elementondomain);
+
+%all elements outside the constraint domain are equivalent to water. all nodes outside are spc'd.
+md.diagnostic.spcvx(vertexnotondomain)=md.inversion.vx_obs(vertexnotondomain);
+md.diagnostic.spcvy(vertexnotondomain)=md.inversion.vy_obs(vertexnotondomain);
+md.mask.elementonwater(elementnotondomain)=1;
+
+%now, make sure all elements on water have nodes that are spc'd, otherwise, we'll get a singular problem.
+pos=find(~md.mask.elementonwater);
+numpos=unique(md.mesh.elements(pos,:));
+nodes=setdiff(1:1:md.mesh.numberofvertices,numpos);
+md.diagnostic.spcvx(nodes)=md.inversion.vx_obs(nodes);
+md.diagnostic.spcvy(nodes)=md.inversion.vy_obs(nodes);
+
+%make sure icefronts that are completely spc'd are taken out:
+free_segments=find((~isnan(md.diagnostic.spcvx(md.diagnostic.icefront(:,1:2))) + ~isnan(md.diagnostic.spcvy(md.diagnostic.icefront(:,1:2))))~=2);
+md.diagnostic.icefront=md.diagnostic.icefront(free_segments,:);
Index: /issm/trunk-jpl/src/m/regional/BasinConstrainShelf.m
===================================================================
--- /issm/trunk-jpl/src/m/regional/BasinConstrainShelf.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/regional/BasinConstrainShelf.m	(revision 13009)
@@ -0,0 +1,74 @@
+function md=BasinConstrainShelf(md,domain);
+%BASINCONSTRAIN - constrain basin
+%
+%   Constrain basin using a constraint domain outline, 
+%   to dirichlet boundary conditions.
+%   constraindomain is an Argus domain outline file enclosing 
+%   the geographical area of interest.
+%
+%   Usage: 
+%      md=BasinConstrain(md,constraindomain)
+%
+%   Example:
+%      md=BasinConstrain(md,'DomainOutline.exp');
+%      md=BasinConstrain(md,'~Iceshelves.exp');
+
+%now, flag nodes and elements outside the domain outline.
+if ischar(domain),
+	if isempty(domain),
+		elementondomain=zeros(md.mesh.numberofelements,1);
+		vertexondomain=zeros(md.mesh.numberofvertices,1);
+		invert=0;
+	elseif strcmpi(domain,'all')
+		elementondomain=ones(md.mesh.numberofelements,1);
+		vertexondomain=ones(md.mesh.numberofvertices,1);
+		invert=0;
+	else
+		%make sure that we actually don't want the elements outside the domain outline!
+		if strcmpi(domain(1),'~'),
+			domain=domain(2:end);
+			invert=1;
+		else
+			invert=0;
+		end
+		%ok, flag elements and nodes
+		[vertexondomain elementondomain]=ContourToMesh(md.mesh.elements(:,1:3),md.mesh.x,md.mesh.y,domain,'element and node',2);
+	end
+	if invert,
+		vertexondomain=~vertexondomain;
+		elementondomain=~elementondomain;
+	end
+else
+	error('BasinConstrain error message: domain type not supported yet');
+end
+
+%list of elements and nodes not on domain
+vertexnotondomain=find(~vertexondomain);
+elementnotondomain=find(~elementondomain);
+
+%all elements outside the constraint domain are equivalent to water. all nodes outside are spc'd.
+md.diagnostic.spcvx(vertexnotondomain)=md.inversion.vx_obs(vertexnotondomain);
+md.diagnostic.spcvy(vertexnotondomain)=md.inversion.vy_obs(vertexnotondomain);
+md.mask.elementonwater(elementnotondomain)=1;
+
+%now, make sure all elements on water have nodes that are spc'd, otherwise, we'll get a singular problem.
+pos=find(~md.mask.elementonwater);
+numpos=unique(md.mesh.elements(pos,:));
+nodes=setdiff(1:1:md.mesh.numberofvertices,numpos);
+md.diagnostic.spcvx(nodes)=md.inversion.vx_obs(nodes);
+md.diagnostic.spcvy(nodes)=md.inversion.vy_obs(nodes);
+
+%make sure any node with NaN velocity is spc'd:
+%we spc to the smoothed value, so that control methods don't go berserk trying to figure out what reaction force to apply for the spc to stand.
+pos=find(isnan(md.inversion.vel_obs_raw));
+md.diagnostic.spcvx(pos)=md.inversion.vx_obs(pos); 
+md.diagnostic.spcvy(pos)=md.inversion.vy_obs(pos); 
+
+%iceshelves: any vertex on floating ice is spc'd
+pos=find(md.mask.vertexongroundedice);
+md.diagnostic.spcvx(pos)=md.inversion.vx_obs(pos); 
+md.diagnostic.spcvy(pos)=md.inversion.vy_obs(pos); 
+
+%make sure icefronts that are completely spc'd are taken out:
+free_segments=find((~isnan(md.diagnostic.spcvx(md.diagnostic.icefront(:,1:2))) + ~isnan(md.diagnostic.spcvy(md.diagnostic.icefront(:,1:2))) )~=2);
+md.diagnostic.icefront=md.diagnostic.icefront(free_segments,:);
Index: /issm/trunk-jpl/src/m/regional/regionaltransient2d.m
===================================================================
--- /issm/trunk-jpl/src/m/regional/regionaltransient2d.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/regional/regionaltransient2d.m	(revision 13009)
@@ -0,0 +1,158 @@
+function md2=regionaltransient2d(md1,area,hmin,hmax,err,stepres)
+%regionaltransient2d - extract a model according to an Argus contour or flag list and remesh
+%               at new resolution res
+%
+%   This routine extracts a submodel from a bigger model with respect to a given contour
+%   md must be followed by the corresponding exp domain file (argus type, .exp extension). 
+%   The model will be remeshed at high rsolution hmin and low resolution hmax.  The ice 
+%   boundary velocities will be spc'd to the transient velocities at saved transient steps
+%   at the resolution optionally provided for stepres.  A stepres of 2 means that you wish
+%   to skip every other saved transient step.  This is useful when extracting a long transient.
+%
+%   Usage:
+%      md2=regionaltransient2d(md1,area,hmin,hmax,err);
+%
+%   Examples:
+%      md2=regionaltransient2d(md,'Domain.exp',500,10000,[15 250]);
+%      md2=regionaltransient2d(md,'Domain.exp',3000,15000,[10 300],2);
+%
+%   See also: MODELEXTRACT, EXTRUDE, COLLAPSE
+
+%some checks
+if ((nargin~=5) & (nargin~=6)),
+	help regionaltransient2d 
+	error('regionaltransient2d error message: bad usage');
+end
+
+%get check option
+if (nargin==5),
+	stepres=1;
+end
+
+%take every fields from model
+mde=modelextract(md1,area);
+mde.private.bamg=[];
+mde.mesh.extractedvertices=nan;
+mde.mesh.extractedelements=nan;
+
+%remesh
+md2=bamg(mde,'hmin',hmin,'hmax',hmax,'field',[mde.inversion.vel_obs mde.geometry.surface],'splitcorner',1,'KeepVertices',0,'err',err);
+md2=setmask(md2,'','');
+
+%automatically modify fields
+
+	%loop over model fields
+	model_fields=fields(md1);
+	for i=1:length(model_fields),
+
+		%get field
+		field=md1.(model_fields{i});
+		fieldsize=size(field);
+
+		%copy field, interpolated to new mesh
+		if isobject(field), %recursive call
+			object_fields=fields(md1.(model_fields{i}));
+			fname=['(model_fields{i}).(object_fields{j})'];
+		else
+			object_fields=field;
+			fname=['(model_fields{i})'];
+		end
+		for j=1:length(object_fields),
+			%get field
+			field=eval(['md2.' fname]);
+			fieldsize=size(field);
+
+			%size = number of nodes * n
+			for n=1:fieldsize(2)
+				if fieldsize(1)==mde.mesh.numberofvertices
+					if(sum(field(:,n) ~= field(1,n)) == 0)
+						eval(['md2.' fname '(1:md2.mesh.numberofvertices,n)=field(1,n)*ones(md2.mesh.numberofvertices,1);']);
+					else
+						eval(['md2.' fname '(1:md2.mesh.numberofvertices,n)=InterpFromMeshToMesh2d(mde.mesh.elements,mde.mesh.x,mde.mesh.y,field(:,n),md2.mesh.x,md2.mesh.y);']);
+					end
+					eval(['md2.' fname '(:,n)=md2.' fname '(1:md2.mesh.numberofvertices,n);']);
+				elseif fieldsize(1)==mde.mesh.numberofvertices+1
+					if(sum(field(1:end-1,n) ~= field(1,n)) == 0)
+						eval(['md2.' fname '(1:md2.mesh.numberofvertices+1,n)=[field(1,n)*ones(md2.mesh.numberofvertices,1); field(end,n)];']);
+					else
+						eval(['md2.' fname '(1:md2.mesh.numberofvertices+1,n)=[InterpFromMeshToMesh2d(mde.mesh.elements,mde.mesh.x,mde.mesh.y,field(1:end-1,n),md2.mesh.x,md2.mesh.y); field(end,n)];']);
+					end
+					eval(['md2.' fname '(:,n)=md2.' fname '(1:md2.mesh.numberofvertices+1,n)']);
+					%size = number of elements * n
+				elseif fieldsize(1)==mde.mesh.numberofelements
+					if(sum(field(1:end-1,n) ~= field(1,n)) == 0)
+						eval(['md2.' fname '(1:md2.mesh.numberofelements,n)=field(1,n)*ones(md2.mesh.numberofelements,1);']);
+					else
+						eval(['md2.' fname '(1:md2.mesh.numberofelements,n)=InterpFromMeshToMesh2d(mde.mesh.elements,mde.mesh.x,mde.mesh.y,field(:,n),md2.mesh.x,md2.mesh.y);']);
+					end
+					eval(['md2.' fname '(:,n)=md2.' fname '(1:md2.mesh.numberofelements,n);']);
+				end
+			end
+		end
+	end
+
+	%Read transient velocities and thickness, looping through only the populated times
+	spcx=[];
+	spcy=[];
+	spct=[];
+	steps=[];
+	nsteps=length(md1.results.TransientSolution);
+	count=0;
+	numElements=arrayfun(@(x) numel(x.step), md1.results.TransientSolution);
+	for t=find(numElements==1)
+		if ~isempty(md1.results.TransientSolution(t).Vel) & mod(count,stepres)==0,
+			vx=PatchToVec(md1.results.TransientSolution(t).Vx);
+			vy=PatchToVec(md1.results.TransientSolution(t).Vy);
+			thickness=PatchToVec(md1.results.TransientSolution(t).Thickness);
+			spcx=[spcx InterpFromMeshToMesh2d(md1.mesh.elements,md1.mesh.x,md1.mesh.y,vx,md2.mesh.x,md2.mesh.y)];
+			spcy=[spcy InterpFromMeshToMesh2d(md1.mesh.elements,md1.mesh.x,md1.mesh.y,vy,md2.mesh.x,md2.mesh.y)];
+			spct=[spct InterpFromMeshToMesh2d(md1.mesh.elements,md1.mesh.x,md1.mesh.y,thickness,md2.mesh.x,md2.mesh.y)];
+			steps=[steps t*md1.timestepping.time_step];
+		end
+		count=count+1;
+	end
+
+	%As long as there are recorded time steps, spc the boundaries with velocities
+	if nsteps > 0
+		md2.diagnostic.spcvx=md2.diagnostic.spcvx*ones(1,size(spcx,2));
+		md2.diagnostic.spcvy=md2.diagnostic.spcvy*ones(1,size(spcy,2));
+		md2.diagnostic.spcvz=md2.diagnostic.spcvz*ones(1,size(spcx,2));
+		md2.prognostic.spcthickness=md2.prognostic.spcthickness*ones(1,size(spct,2));
+		md2.diagnostic.spcvx(find(md2.mesh.vertexonboundary),:)=spcx(find(md2.mesh.vertexonboundary),:);
+		md2.diagnostic.spcvy(find(md2.mesh.vertexonboundary),:)=spcy(find(md2.mesh.vertexonboundary),:);
+		md2.diagnostic.spcvz(find(md2.mesh.vertexonboundary),:)=0;
+		md2.prognostic.spcthickness(find(md2.mesh.vertexonboundary),:)=spct(find(md2.mesh.vertexonboundary),:);
+		md2.diagnostic.spcvx=[md2.diagnostic.spcvx; steps];
+		md2.diagnostic.spcvy=[md2.diagnostic.spcvy; steps];
+		md2.diagnostic.spcvz=[md2.diagnostic.spcvz; steps];
+		md2.prognostic.spcthickness=[md2.prognostic.spcthickness; steps];
+	end
+
+	%Diagnostic.  Don't spc the icefront vertices.
+	if ~isnan(md2.diagnostic.icefront)
+		md1s=modelextract(md1,area);
+		%md2.diagnostic.icefront=[md2.mesh.segments 2];
+		e2=md2.mesh.segments(:,end);
+		e1=md1s.mesh.segments(:,end);
+
+		pload = nan*ones(size(md1s.mesh.elements,1),1);
+		pload(md1s.diagnostic.icefront(:,end-1))=md1s.diagnostic.icefront(:,end);
+
+		x2=mean(md2.mesh.x(md2.mesh.elements(e2,:)),2);
+      y2=mean(md2.mesh.y(md2.mesh.elements(e2,:)),2);
+		x1=mean(md1s.mesh.x(md1s.mesh.elements),2);
+      y1=mean(md1s.mesh.y(md1s.mesh.elements),2);
+
+		pload2=griddata(x1,y1,pload,x2,y2,'nearest');
+		md2.diagnostic.icefront=[md2.mesh.segments(~isnan(pload2),:) pload2(~isnan(pload2))];
+		md2.diagnostic.spcvx(unique(md2.diagnostic.icefront(:,1:2)),:)=nan;
+		md2.diagnostic.spcvy(unique(md2.diagnostic.icefront(:,1:2)),:)=nan;
+		md2.diagnostic.spcvz(unique(md2.diagnostic.icefront(:,1:2)),:)=nan;
+		md2.prognostic.spcthickness(unique(md2.diagnostic.icefront(:,1:2)),:)=nan;
+	end
+
+	%Clear results fields
+	if isstruct(md1.results),
+		md2.results=[];
+	end
+
Index: /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.m	(revision 13009)
@@ -0,0 +1,65 @@
+function structure=MatlabProcessPatch(structure);
+%PROCESSPATCH - create a structure from a patch
+%
+%   Usage:
+%      Result=ProcessPatch(Result);
+
+%return if there is no field Patch
+if (~isfield(structure,'Patch')),
+	return;
+end
+
+%loop over steps
+for i=1:length(structure),
+
+	%Get Patch for current step
+	Patch=structure(i).Patch;
+	numvertices=structure(i).PatchVertices;
+
+	%check that Patch is not empty
+	if length(Patch)==0 continue; end
+
+	%Get number of fields;
+	fields=unique(Patch(:,1));
+	steps=unique(Patch(:,2));
+
+	%parse steps
+	for j=1:length(steps),
+
+		posstep=find(Patch(:,2)==steps(j));
+
+		%Take all the lines of the Patch for this timestep
+		temporarypatch=Patch(posstep,:);
+		time=temporarypatch(1,3);
+		step=temporarypatch(1,2);
+
+		%parse fields
+		for i=1:length(fields),
+
+			%get name
+			fieldname=EnumToString(fields(i));
+
+			%get line positions
+			pos=find(temporarypatch(:,1)==fields(i));
+
+			%Fill Result structure
+			structure(step).steps=step;
+			structure(step).time=time;
+			structure(step).(fieldname).element=temporarypatch(pos,4);
+			structure(step).(fieldname).interpolation=temporarypatch(pos,5);
+			structure(step).(fieldname).index=temporarypatch(pos,6:5+numvertices);
+			if structure(step).(fieldname).interpolation==P1Enum,
+				structure(step).(fieldname).value=temporarypatch(pos,6+numvertices:end);
+			end
+			if structure(step).(fieldname).interpolation==P0Enum,
+				structure(step).(fieldname).value=temporarypatch(pos,6+numvertices);
+			end
+
+		end
+	end
+end
+
+%remove fields
+structure=rmfield(structure,'Patch');
+structure=rmfield(structure,'PatchVertices');
+structure=rmfield(structure,'PatchNodes');
Index: /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/MatlabProcessPatch.py	(revision 13009)
@@ -0,0 +1,19 @@
+def MatlabProcessPatch(structure):
+	"""
+	PROCESSPATCH - create a structure from a patch
+ 
+	   Usage:
+	      Result=ProcessPatch(Result);
+	"""
+
+	#loop over steps
+	for structurei in structure.itervalues():
+
+		#return if there is no field Patch
+		if not 'Patch' in structurei:
+			continue
+
+		raise SystemError("MatlabProcessPatch not implemented in Python.")
+
+	return structure
+
Index: /issm/trunk-jpl/src/m/solve/WriteData.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/WriteData.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/WriteData.m	(revision 13009)
@@ -0,0 +1,260 @@
+function WriteData(fid,varargin)
+%WRITEDATA - write model field in binary file
+%
+%   Usage:
+%      WriteData(fid,varargin);
+
+%process options
+options=pairoptions(varargin{:});
+
+%Get data properties
+if exist(options,'object');
+	%This is a object field, construct enum and data
+	obj       = getfieldvalue(options,'object');
+	fieldname = getfieldvalue(options,'fieldname');
+	classname = class(obj);
+
+	enum      = BuildEnum([classname '_' fieldname]);
+	data      = obj.(fieldname);
+else
+	%No processing required
+	data = getfieldvalue(options,'data');
+	enum = getfieldvalue(options,'enum');
+end
+format  = getfieldvalue(options,'format');
+mattype = getfieldvalue(options,'mattype',0);    %only required for matrices
+
+%Process sparse matrices
+if issparse(data),
+	data=full(data);
+end
+
+%Step 1: write the enum to identify this record uniquely
+fwrite(fid,enum,'int'); 
+
+%Step 2: write the data itself.
+if     strcmpi(format,'Boolean'),% {{{
+	if(numel(data)~=1), error(['field ' EnumToString(enum) ' cannot be marshalled as it has more than one element!']); end
+
+	%first write length of record
+	fwrite(fid,4+4,'int');  %1 bool (disguised as an int)+code
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%now write integer
+	fwrite(fid,data,'int');  %send an int, not easy to send a bool
+	% }}}
+elseif strcmpi(format,'Integer'), % {{{
+	if(numel(data)~=1), error(['field ' EnumToString(enum) ' cannot be marshalled as it has more than one element!']); end
+
+	%first write length of record
+	fwrite(fid,4+4,'int');  %1 integer + code
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%now write integer
+	fwrite(fid,data,'int'); 
+	% }}}
+elseif strcmpi(format,'Double'), % {{{
+	if(numel(data)~=1), error(['field ' EnumToString(enum) ' cannot be marshalled as it has more than one element!']); end
+
+	%first write length of record
+	fwrite(fid,8+4,'int');  %1 double+code
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%now write double
+	fwrite(fid,data,'double'); 
+	% }}}
+elseif strcmpi(format,'String'), % {{{
+	%first write length of record
+	fwrite(fid,length(data)+4+4,'int');  %string + string size + code
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%now write string
+	fwrite(fid,length(data),'int'); 
+	fwrite(fid,data,'char'); 
+	% }}}
+elseif strcmpi(format,'BooleanMat'), % {{{
+
+	%Get size
+	s=size(data);
+	%if matrix = NaN, then do not write anything
+	if (s(1)==1 & s(2)==1 & isnan(data)),
+		s(1)=0; s(2)=0;
+	end
+
+	%first write length of record
+	fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int');  %2 integers (32 bits) + the double matrix + code + matrix type
+
+	%write data code and matrix type: 
+	fwrite(fid,FormatToCode(format),'int'); 
+	fwrite(fid,mattype,'int');
+
+	%now write matrix
+	fwrite(fid,s(1),'int'); 
+	fwrite(fid,s(2),'int'); 
+	if s(1)*s(2),
+		fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
+	end
+	% }}}
+elseif strcmpi(format,'IntMat'), % {{{
+
+	%Get size
+	s=size(data);
+	%if matrix = NaN, then do not write anything
+	if (s(1)==1 & s(2)==1 & isnan(data)),
+		s(1)=0; s(2)=0;
+	end
+
+	%first write length of record
+	fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int');  %2 integers (32 bits) + the double matrix + code + matrix type
+
+	%write data code and matrix type: 
+	fwrite(fid,FormatToCode(format),'int'); 
+	fwrite(fid,mattype,'int');
+
+	%now write matrix
+	fwrite(fid,s(1),'int'); 
+	fwrite(fid,s(2),'int'); 
+	if s(1)*s(2),
+		fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
+	end
+	% }}}
+elseif strcmpi(format,'DoubleMat'), % {{{
+
+	%Get size
+	s=size(data);
+	%if matrix = NaN, then do not write anything
+	if (s(1)==1 & s(2)==1 & isnan(data)),
+		s(1)=0; s(2)=0;
+	end
+
+	%first write length of record
+	fwrite(fid,4+4+8*s(1)*s(2)+4+4,'int');  %2 integers (32 bits) + the double matrix + code + matrix type
+
+	%write data code and matrix type: 
+	fwrite(fid,FormatToCode(format),'int'); 
+	fwrite(fid,mattype,'int');
+
+	%now write matrix
+	fwrite(fid,s(1),'int'); 
+	fwrite(fid,s(2),'int'); 
+	if s(1)*s(2),
+		fwrite(fid,data','double'); %get to the "c" convention, hence the transpose
+	end
+	% }}}
+elseif strcmpi(format,'MatArray'), % {{{
+
+	numrecords=numel(data);
+
+	%first get length of record
+	recordlength=4+4; %number of records + code
+	for i=1:numrecords,
+		matrix=data{i};
+		s=size(matrix);
+		recordlength=recordlength+4*2+... %row and col of matrix
+			s(1)*s(2)*8; %matrix of doubles
+	end
+
+	%write length of record
+	fwrite(fid,recordlength,'int'); 
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%write data, first number of records
+	fwrite(fid,numrecords,'int'); 
+
+	%write each matrix: 
+	for i=1:numrecords,
+		matrix=data{i};
+		s=size(matrix);
+		fwrite(fid,s(1),'int'); 
+		fwrite(fid,s(2),'int'); 
+		fwrite(fid,matrix','double');
+	end
+	% }}}
+elseif strcmpi(format,'StringArray'), % {{{
+
+	%first get length of string array: 
+	num=numel(data);
+	%now get length of record: 
+	recordlength=4+4; %for length of array + code
+	for i=1:num,
+		string=data{i};
+		recordlength=recordlength+4+length(string); %for each string
+	end
+
+	%write length of record
+	fwrite(fid,recordlength,'int'); 
+
+	%write data code: 
+	fwrite(fid,FormatToCode(format),'int'); 
+
+	%now write length of string array
+	fwrite(fid,num,'int'); 
+
+	%now write the strings
+	for i=1:num,
+		string=data{i};
+		fwrite(fid,length(string),'int'); 
+		fwrite(fid,string,'char'); 
+	end
+	% }}}
+else  % {{{
+	error(['WriteData error message: data type: ' num2str(format) ' not supported yet! (' EnumToString(enum) ')']);
+end % }}}
+end
+
+function enum=BuildEnum(string) % {{{
+%BUILDENUM - build enum out of string
+%
+%   Usage:
+%      enum=BuildEnum(string)
+
+	if findstr(string,'_'),
+		indices=findstr(string,'_');
+		for i=1:length(indices),
+			string(indices(i)+1)=upper(string(indices(i)+1));
+		end
+		string(indices)=[];
+	end
+
+	%take first letter of string and make it uppercase: 
+	string(1)=upper(string(1));
+
+	%Get Enum
+	enum=eval([string 'Enum();']); 
+end % }}}
+function code=FormatToCode(format) % {{{
+%This routine takes the format string, and hardcodes it into an integer, which 
+%is passed along the record, in order to identify the nature of the dataset being 
+%sent.
+	if     strcmpi(format,'Boolean'),
+		code=1;
+	elseif strcmpi(format,'Integer'), 
+		code=2;
+	elseif strcmpi(format,'Double'), 
+		code=3;
+	elseif strcmpi(format,'String'), 
+		code=4;
+	elseif strcmpi(format,'BooleanMat'),
+		code=5;
+	elseif strcmpi(format,'IntMat'),
+		code=6;
+	elseif strcmpi(format,'DoubleMat'),
+		code=7;
+	elseif strcmpi(format,'MatArray'), 
+		code=8;
+	elseif strcmpi(format,'StringArray'),
+		code=9;
+	else 
+		error('FormatToCode error message: data type not supported yet!');
+	end
+end% }}}
Index: /issm/trunk-jpl/src/m/solve/WriteData.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/WriteData.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/WriteData.py	(revision 13009)
@@ -0,0 +1,274 @@
+import numpy
+import math
+import struct
+from MatlabFuncs import *
+
+def WriteData(fid,*args):
+	"""
+	WRITEDATA - write model field in binary file
+ 
+	   Usage:
+	      WriteData(fid,varargin)
+	"""
+
+	#process options
+	options=pairoptions(*args)
+
+	#Get data properties
+	if options.exist('object'):
+		#This is an object field, construct enum and data
+		obj       = options.getfieldvalue('object')
+		fieldname = options.getfieldvalue('fieldname')
+		classname = type(obj)
+
+		enum      = BuildEnum(classname+'_'+fieldname)
+		data      = getattr(obj,fieldname)
+	else:
+		#No processing required
+		data = options.getfieldvalue('data')
+		enum = options.getfieldvalue('enum')
+	format  = options.getfieldvalue('format')
+	mattype = options.getfieldvalue('mattype',0)    #only required for matrices
+
+	#Process sparse matrices
+#	if issparse(data),
+#		data=full(data);
+#	end
+
+	#Step 1: write the enum to identify this record uniquely
+	fid.write(struct.pack('i',enum)) 
+
+	#Step 2: write the data itself.
+	if   strcmpi(format,'Boolean'):    # {{{
+		if len(data) !=1:
+			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum))
+
+		#first write length of record
+		fid.write(struct.pack('i',4+4))  #1 bool (disguised as an int)+code
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#now write integer
+		fid.write(struct.pack('i',data))  #send an int, not easy to send a bool
+		# }}}
+
+	elif strcmpi(format,'Integer'):    # {{{
+		if len(data) !=1:
+			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum))
+
+		#first write length of record
+		fid.write(struct.pack('i',4+4))  #1 integer + code
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#now write integer
+		fid.write(struct.pack('i',data)) 
+		# }}}
+
+	elif strcmpi(format,'Double'):    # {{{
+		if len(data) !=1:
+			raise ValueError('field %s cannot be marshalled as it has more than one element!' % EnumToString(enum))
+
+		#first write length of record
+		fid.write(struct.pack('i',8+4))  #1 double+code
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#now write double
+		fid.write(struct.pack('d',data)) 
+		# }}}
+
+	elif strcmpi(format,'String'):    # {{{
+		#first write length of record
+		fid.write(struct.pack('i',len(data)+4+4))  #string + string size + code
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#now write string
+		fid.write(struct.pack('i',len(data))) 
+		fid.write(struct.pack('%ds' % len(data),data)) 
+		# }}}
+
+	elif strcmpi(format,'BooleanMat'):    # {{{
+
+		#Get size
+		s=data.shape
+		#if matrix = NaN, then do not write anything
+		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+			s[0]=0
+			s[1]=0
+
+		#first write length of record
+		fid.write(struct.pack('i',4+4+8*s[0]*s[1]+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
+
+		#write data code and matrix type: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',mattype))
+
+		#now write matrix
+		fid.write(struct.pack('i',s[0])) 
+		fid.write(struct.pack('i',s[1])) 
+		for i in xrange(s[0]):
+			for j in xrange(s[1]):
+				fid.write(struct.pack('i',data[i][j]))    #get to the "c" convention, hence the transpose
+		# }}}
+
+	elif strcmpi(format,'IntMat'):    # {{{
+
+		#Get size
+		s=data.shape
+		#if matrix = NaN, then do not write anything
+		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+			s[0]=0
+			s[1]=0
+
+		#first write length of record
+		fid.write(struct.pack('i',4+4+8*s[0]*s[1]+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
+
+		#write data code and matrix type: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',mattype))
+
+		#now write matrix
+		fid.write(struct.pack('i',s[0])) 
+		fid.write(struct.pack('i',s[1])) 
+		for i in xrange(s[0]):
+			for j in xrange(s[1]):
+				fid.write(struct.pack('i',data[i][j]))    #get to the "c" convention, hence the transpose
+		# }}}
+
+	elif strcmpi(format,'DoubleMat'):    # {{{
+
+		#Get size
+		s=data.shape
+		#if matrix = NaN, then do not write anything
+		if s[0]==1 and s[1]==1 and math.isnan(data[0][0]):
+			s[0]=0
+			s[1]=0
+
+		#first write length of record
+		fid.write(struct.pack('i',4+4+8*s[0]*s[1]+4+4))    #2 integers (32 bits) + the double matrix + code + matrix type
+
+		#write data code and matrix type: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+		fid.write(struct.pack('i',mattype))
+
+		#now write matrix
+		fid.write(struct.pack('i',s[0])) 
+		fid.write(struct.pack('i',s[1])) 
+		for i in xrange(s[0]):
+			for j in xrange(s[1]):
+				fid.write(struct.pack('d',data[i][j]))    #get to the "c" convention, hence the transpose
+		# }}}
+
+	elif strcmpi(format,'MatArray'):    # {{{
+
+		#first get length of record
+		recordlength=4+4    #number of records + code
+		for matrix in data:
+			s=matrix.shape
+			recordlength+=4*2+s[0]*s[1]*8    #row and col of matrix + matrix of doubles
+
+		#write length of record
+		fid.write(struct.pack('i',recordlength)) 
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#write data, first number of records
+		fid.write(struct.pack('i',len(data))) 
+
+		#write each matrix: 
+		for matrix in data:
+			s=matrix.shape
+			fid.write(struct.pack('i',s[0])) 
+			fid.write(struct.pack('i',s[1])) 
+			for i in xrange(s[0]):
+				for j in xrange(s[1]):
+					fid.write(struct.pack('d',matrix[i][j]))
+		# }}}
+
+	elif strcmpi(format,'StringArray'):    # {{{
+
+		#first get length of record
+		recordlength=4+4    #for length of array + code
+		for string in data:
+			recordlength+=4+len(string)    #for each string
+
+		#write length of record
+		fid.write(struct.pack('i',recordlength)) 
+
+		#write data code: 
+		fid.write(struct.pack('i',FormatToCode(format))) 
+
+		#now write length of string array
+		fid.write(struct.pack('i',len(data))) 
+
+		#now write the strings
+		for string in data:
+			fid.write(struct.pack('i',len(string))) 
+			fid.write(struct.pack('%ds' % len(string),string)) 
+		# }}}
+
+	else:    # {{{
+		raise TypeError('WriteData error message: data type: %d not supported yet! (%s)' % (format,EnumToString(enum)))
+	# }}}
+
+def BuildEnum(string): # {{{
+	"""
+	BUILDENUM - build enum out of string
+ 
+    Usage:
+       enum=BuildEnum(string)
+	"""
+
+	if '_' in string:
+		substrs=string.split('_')
+		string=''
+		for str in substrs:
+			string+=str[0].upper()+str[1:]
+	else:
+		#take first letter of string and make it uppercase: 
+		string=str[0].upper()+str[1:]
+
+	#Get Enum
+	exec('enum='+string+'Enum()',globals())
+
+	return enum
+# }}}
+
+def FormatToCode(format): # {{{
+	"""
+	This routine takes the format string, and hardcodes it into an integer, which 
+	is passed along the record, in order to identify the nature of the dataset being 
+	sent.
+	"""
+
+	if   strcmpi(format,'Boolean'):
+		code=1
+	elif strcmpi(format,'Integer'):
+		code=2
+	elif strcmpi(format,'Double'):
+		code=3
+	elif strcmpi(format,'String'):
+		code=4
+	elif strcmpi(format,'BooleanMat'):
+		code=5
+	elif strcmpi(format,'IntMat'):
+		code=6
+	elif strcmpi(format,'DoubleMat'):
+		code=7
+	elif strcmpi(format,'MatArray'):
+		code=8
+	elif strcmpi(format,'StringArray'):
+		code=9
+	else:
+		raise InputError('FormatToCode error message: data type not supported yet!')
+
+	return code
+# }}}
+
Index: /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.m	(revision 13009)
@@ -0,0 +1,100 @@
+function ismodelselfconsistent(md),
+%ISMODELSELFCONSISTENT - check that model forms a closed form solvable problem.
+%
+%   Usage:
+%      ismodelselfconsistent(md),
+
+%initialize consistency as true
+md.private.isconsistent=true;
+
+%Get solution and associated analyses
+solution=md.private.solution;
+[analyses,numanalyses]=AnalysisConfiguration(solution);
+
+%Go through a model field, check that it is a class, and call checkconsistency
+fields=properties('model');
+for i=1:length(fields),
+	field=fields{i};
+
+	%Some properties do not need to be checked
+	if ismember(field,{'results' 'debug' 'radaroverlay'}),
+		continue;
+	end
+
+	%Check that current field is an object
+	if ~isobject(md.(field))
+		md=checkmessage(md,['field ''' char(field) ''' is not an object']);
+	end
+
+	%Check consistency of the object
+	if verLessThan('matlab', '7.6')
+		md=checkconsistency(md.(field),md,solution,analyses);
+	else
+		md=md.(field).checkconsistency(md,solution,analyses);
+	end
+end
+
+%error message if mode is not consistent
+if md.private.isconsistent==false,
+	error('Model not consistent, see messages above');
+end
+end
+
+function [analyses,numanalyses]=AnalysisConfiguration(solutiontype), % {{{
+%ANALYSISCONFIGURATION - return type of analyses, number of analyses 
+%
+%   Usage:
+%      [analyses, numanalyses]=AnalysisConfiguration(solutiontype);
+
+
+
+switch solutiontype,
+
+	case DiagnosticSolutionEnum,
+		numanalyses=5;
+		analyses=[DiagnosticHorizAnalysisEnum;DiagnosticVertAnalysisEnum;DiagnosticHutterAnalysisEnum;SurfaceSlopeAnalysisEnum;BedSlopeAnalysisEnum];
+
+	case SteadystateSolutionEnum,
+		numanalyses=7; 
+		analyses=[DiagnosticHorizAnalysisEnum;DiagnosticVertAnalysisEnum;DiagnosticHutterAnalysisEnum;SurfaceSlopeAnalysisEnum;BedSlopeAnalysisEnum;ThermalAnalysisEnum;MeltingAnalysisEnum];
+
+	case ThermalSolutionEnum,
+		numanalyses=2; 
+		analyses=[ThermalAnalysisEnum;MeltingAnalysisEnum];
+
+	case EnthalpySolutionEnum,
+		numanalyses=1; 
+		analyses=[EnthalpyAnalysisEnum];
+
+	case PrognosticSolutionEnum,
+		numanalyses=1; 
+		analyses=[PrognosticAnalysisEnum];
+
+	case BalancethicknessSolutionEnum,
+		numanalyses=1; 
+		analyses=[BalancethicknessAnalysisEnum];
+
+	case SurfaceSlopeSolutionEnum,
+		numanalyses=1; 
+		analyses=[SurfaceSlopeAnalysisEnum];
+
+	case BedSlopeSolutionEnum,
+		numanalyses=1; 
+		analyses=[BedSlopeAnalysisEnum];
+
+	case TransientSolutionEnum,
+		numanalyses=9; 
+		analyses=[DiagnosticHorizAnalysisEnum;DiagnosticVertAnalysisEnum;DiagnosticHutterAnalysisEnum;SurfaceSlopeAnalysisEnum;BedSlopeAnalysisEnum;ThermalAnalysisEnum;MeltingAnalysisEnum;EnthalpyAnalysisEnum;PrognosticAnalysisEnum];
+
+	case FlaimSolutionEnum,
+		numanalyses=1; 
+		analyses=[FlaimAnalysisEnum];
+
+	case HydrologySolutionEnum,
+		numanalyses=3; 
+		analyses=[BedSlopeAnalysisEnum;SurfaceSlopeAnalysisEnum;HydrologyAnalysisEnum];
+
+	otherwise
+		error('%s%s%s',' solution type: ',EnumToString(solutiontype),' not supported yet!');
+
+end % }}}
Index: /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/ismodelselfconsistent.py	(revision 13009)
@@ -0,0 +1,95 @@
+from AnalysisConfiguration import *
+from EnumDefinitions import *
+
+def AnalysisConfiguration(solutiontype): #{{{
+	"""
+	ANALYSISCONFIGURATION - return type of analyses, number of analyses 
+
+		Usage:
+			[analyses, numanalyses]=AnalysisConfiguration(solutiontype);
+	"""
+
+	if   solutiontype == DiagnosticSolutionEnum:
+		numanalyses=5
+		analyses=[DiagnosticHorizAnalysisEnum,DiagnosticVertAnalysisEnum,DiagnosticHutterAnalysisEnum,SurfaceSlopeAnalysisEnum,BedSlopeAnalysisEnum]
+
+	elif solutiontype == SteadystateSolutionEnum:
+		numanalyses=7 
+		analyses=[DiagnosticHorizAnalysisEnum,DiagnosticVertAnalysisEnum,DiagnosticHutterAnalysisEnum,SurfaceSlopeAnalysisEnum,BedSlopeAnalysisEnum,ThermalAnalysisEnum,MeltingAnalysisEnum]
+
+	elif solutiontype == ThermalSolutionEnum:
+		numanalyses=2 
+		analyses=[ThermalAnalysisEnum,MeltingAnalysisEnum]
+
+	elif solutiontype == EnthalpySolutionEnum:
+		numanalyses=1 
+		analyses=[EnthalpyAnalysisEnum]
+
+	elif solutiontype == PrognosticSolutionEnum:
+		numanalyses=1 
+		analyses=[PrognosticAnalysisEnum]
+
+	elif solutiontype == BalancethicknessSolutionEnum:
+		numanalyses=1 
+		analyses=[BalancethicknessAnalysisEnum]
+
+	elif solutiontype == SurfaceSlopeSolutionEnum:
+		numanalyses=1 
+		analyses=[SurfaceSlopeAnalysisEnum]
+
+	elif solutiontype == BedSlopeSolutionEnum:
+		numanalyses=1 
+		analyses=[BedSlopeAnalysisEnum]
+
+	elif solutiontype == TransientSolutionEnum:
+		numanalyses=9 
+		analyses=[DiagnosticHorizAnalysisEnum,DiagnosticVertAnalysisEnum,DiagnosticHutterAnalysisEnum,SurfaceSlopeAnalysisEnum,BedSlopeAnalysisEnum,ThermalAnalysisEnum,MeltingAnalysisEnum,EnthalpyAnalysisEnum,PrognosticAnalysisEnum]
+
+	elif solutiontype == FlaimSolutionEnum:
+		numanalyses=1 
+		analyses=[FlaimAnalysisEnum]
+
+	elif solutiontype == HydrologySolutionEnum:
+		numanalyses=3 
+		analyses=[BedSlopeAnalysisEnum,SurfaceSlopeAnalysisEnum,HydrologyAnalysisEnum]
+
+	else:
+		raise TypeError("solution type: '%s' not supported yet!" % EnumToString(solutiontype))
+
+	return analyses,numanalyses
+#}}}
+
+def ismodelselfconsistent(md):
+	"""
+	ISMODELSELFCONSISTENT - check that model forms a closed form solvable problem.
+
+	   Usage:
+	      ismodelselfconsistent(md),
+	"""
+
+	#initialize consistency as true
+	md.private.isconsistent=True
+
+	#Get solution and associated analyses
+	solution=md.private.solution
+	analyses,numanalyses=AnalysisConfiguration(solution)
+
+	#Go through a model fields, check that it is a class, and call checkconsistency
+	fields=vars(md)
+	for field in fields.iterkeys():
+
+		#Some properties do not need to be checked
+		if field in ['results','debug','radaroverlay']:
+			continue
+
+		#Check that current field is an object
+		if not hasattr(getattr(md,field),'checkconsistency'):
+			md.checkmessage("field '%s' is not an object." % field)
+
+		#Check consistency of the object
+		exec("md.%s.checkconsistency(md,solution,analyses)" % field)
+
+	#error message if mode is not consistent
+	if not md.private.isconsistent:
+		raise RuntimeError('Model not consistent, see messages above.')
+
Index: /issm/trunk-jpl/src/m/solve/loadmultipleresultsfromcluster.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadmultipleresultsfromcluster.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/loadmultipleresultsfromcluster.m	(revision 13009)
@@ -0,0 +1,34 @@
+function md_list=loadmultipleresultsfromcluster(md_list)
+%LOADMULTIPLERESULTSFROMCLUSTER - load multiple results of solution sequences from cluster
+%
+%   Usage:
+%      md_list=loadresultsfromcluster(md_list);
+
+nummodels=length(md_list);
+
+%Get cluster settings
+cluster=md_list{1}.cluster;
+name=md_list{1}.name;
+cluster_rc_location=which('cluster.rc');
+[codepath,executionpath,login]=ClusterParameters(cluster,cluster_rc_location);
+
+%Remote tar: 
+disp('tarring results');
+issmssh(cluster,['"cd ' executionpath ' && rm -rf file_list.txt ModelResults.tar.gz && find -iname ''*_*vs*.outbin'' > file_list.txt && tar zcvf ModelResults.tar.gz --files-from file_list.txt  && rm -rf file_list.txt "']);
+
+%copy results from cluster to present directory
+scpin(cluster, executionpath, {'ModelResults.tar.gz'});
+
+%untar:
+!tar -zxvf ModelResults.tar.gz
+
+%ok, go through list and load results from disk: 
+for i=1:nummodels,
+	%load  results for this model
+	md_list{i}=loadresultsfromdisk(md_list{i},[md_list{i}.name '.outbin']);
+
+	delete([name '.outbin']);
+end
+
+%erase files 
+delete('ModelResults.tar.gz');
Index: /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.m	(revision 13009)
@@ -0,0 +1,60 @@
+function md=loadresultsfromcluster(md,runtimename)
+%LOADRESULTSFROMCLUSTER - load results of solution sequence from cluster
+%
+%   Usage:
+%      md=loadresultsfromcluster(md,runtimename);
+
+%retrieve cluster, to be able to call its methods
+cluster=md.cluster;
+
+if nargin==2,
+	md.private.runtimename=runtimename;
+end
+
+%Download outputs from the cluster
+filelist={[md.miscellaneous.name '.outlog'],[md.miscellaneous.name '.errlog']};
+if md.qmu.isdakota,
+	filelist{end+1}=[md.miscellaneous.name '.qmu.err'];
+	filelist{end+1}=[md.miscellaneous.name '.qmu.out'];
+	if isfield(md.qmu.params,'tabular_graphics_data'),
+		if md.qmu.params.tabular_graphics_data==true,
+			filelist{end+1}='dakota_tabular.dat';
+		end
+	end
+else
+	filelist{end+1}=[md.miscellaneous.name '.outbin'];
+end
+Download(cluster,md.private.runtimename,filelist);
+
+%If we are here, no errors in the solution sequence, call loadresultsfromdisk.
+md=loadresultsfromdisk(md,[md.miscellaneous.name '.outbin']);
+
+%erase the log and output files
+if md.qmu.isdakota,
+	delete([['qmu' num2str(feature('GetPid')) '/'] md.miscellaneous.name '.outlog']);
+	delete([['qmu' num2str(feature('GetPid')) '/']  md.miscellaneous.name '.errlog']);
+else
+	delete([md.miscellaneous.name '.outlog']);
+	delete([md.miscellaneous.name '.errlog']);
+	delete([md.miscellaneous.name '.outbin']);
+	if ~ispc,
+		delete([md.private.runtimename '.tar.gz']);
+	end
+end
+
+%erase input file if run was carried out on same platform.
+hostname=oshostname();
+if strcmpi(hostname,cluster.name),
+	if md.qmu.isdakota,
+		delete([['qmu' num2str(feature('GetPid')) '/'] md.miscellaneous.name '.bin']);
+		delete([['qmu' num2str(feature('GetPid')) '/'] md.miscellaneous.name '.queue']);
+	else
+		delete([md.miscellaneous.name '.bin']);
+		delete([md.miscellaneous.name '.petsc']);
+		if ~ispc,
+			delete([md.miscellaneous.name '.queue']);
+		else
+			delete([md.miscellaneous.name '.bat']);
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py	(revision 13009)
@@ -0,0 +1,61 @@
+import os
+import platform
+import socket
+from MatlabFuncs import *
+
+def loadresultsfromcluster(md,runtimename=False):
+	"""
+	LOADRESULTSFROMCLUSTER - load results of solution sequence from cluster
+ 
+	   Usage:
+	      md=loadresultsfromcluster(md,runtimename);
+	"""
+
+	#retrieve cluster, to be able to call its methods
+	cluster=md.cluster
+
+	if runtimename:
+		md.private.runtimename=runtimename
+	end
+
+	#Download outputs from the cluster
+	filelist=[md.miscellaneous.name+'.outlog',md.miscellaneous.name+'.errlog']
+	if md.qmu.isdakota:
+		filelist.append(md.miscellaneous.name+'.qmu.err')
+		filelist.append(md.miscellaneous.name+'.qmu.out')
+		if 'tabular_graphics_data' in md.qmu.params:
+			if md.qmu.params['tabular_graphics_data']:
+				filelist.append('dakota_tabular.dat')
+		filelist.append(md.miscellaneous.name+'.outbin')
+	Download(cluster,md.private.runtimename,filelist)
+
+	#If we are here, no errors in the solution sequence, call loadresultsfromdisk.
+	md=loadresultsfromdisk(md,md.miscellaneous.name+'.outbin')
+
+	#erase the log and output files
+	if md.qmu.isdakota:
+		os.remove(os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name+'.outlog'))
+		os.remove(os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name+'.errlog'))
+	else:
+		os.remove(md.miscellaneous.name+'.outlog')
+		os.remove(md.miscellaneous.name+'.errlog')
+		os.remove(md.miscellaneous.name+'.outbin')
+		if not 'Windows' in platform.system():
+			os.remove(md.private.runtimename+'.tar.gz')
+
+	#erase input file if run was carried out on same platform.
+	hostname=socket.gethostname().lower().split('.')[0]
+	if strcmpi(hostname,cluster.name):
+		if md.qmu.isdakota:
+			os.remove(os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name+'.bin'))
+			os.remove(os.path.join('qmu'+str(os.getpid()),md.miscellaneous.name+'.queue'))
+		else:
+			os.remove(md.miscellaneous.name+'.bin')
+			os.remove(md.miscellaneous.name+'.petsc')
+			if not 'Windows' in platform.system():
+				os.remove(md.miscellaneous.name+'.queue')
+			else:
+				os.remove(md.miscellaneous.name+'.bat')
+
+	return md
+
Index: /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.m	(revision 13009)
@@ -0,0 +1,61 @@
+function md=loadresultsfromdisk(md,filename)
+%LOADRESULTSFROMDISK - load results of solution sequence from disk file "filename"            
+%
+%   Usage:
+%      md=loadresultsfromdisk(md,filename);
+
+%check number of inputs/outputs
+if ((nargin~=2) | (nargout~=1)),
+	help loadresultsfromdisk;
+	error('loadresultsfromdisk: error message.');
+end
+
+if ~md.qmu.isdakota,
+
+	%Check that file exists
+	if ~exist(filename,'file'),
+		error(['binary file ' filename ' not found.']);
+	end
+
+	%initialize md.results if not a structure yet
+	if ~isstruct(md.results),
+		md.results=struct();
+	end
+
+	%load results onto model
+	structure=parseresultsfromdisk(filename,~md.settings.io_gather);
+	if isempty(fieldnames(structure)),
+		error(['No result found in binary file ' filename '. Check for solution crash.']);
+	end
+	md.results.(structure(1).SolutionType)=structure;
+
+	%recover solution_type from results
+	md.private.solution=structure(1).SolutionType;
+
+	%read log files onto  fields
+	if exist([md.miscellaneous.name '.errlog'],'file'),
+		md.results.(structure(1).SolutionType)(1).errlog=char(textread([md.miscellaneous.name '.errlog'],'%s','delimiter','\n'));
+	else
+		md.results.(structure(1).SolutionType)(1).errlog='';
+	end
+
+	if exist([md.miscellaneous.name '.outlog'],'file'),
+		md.results.(structure(1).SolutionType)(1).outlog=char(textread([md.miscellaneous.name '.outlog'],'%s','delimiter','\n'));
+	else
+		md.results.(structure(1).SolutionType)(1).outlog='';
+	end
+
+	if ~isempty(md.results.(structure(1).SolutionType)(1).errlog),
+		disp(['loadresultsfromcluster info message: error during solution. Check your errlog and outlog model fields']);
+	end
+
+
+%post processes qmu results if necessary
+else
+
+	if isscalar(md.private.solution),
+		md.private.solution=EnumToString(md.private.solution);
+	end
+	md=postqmu(md);
+	cd ..
+end
Index: /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/loadresultsfromdisk.py	(revision 13009)
@@ -0,0 +1,60 @@
+import os
+
+def loadresultsfromdisk(md,filename):
+	"""
+	LOADRESULTSFROMDISK - load results of solution sequence from disk file "filename"            
+ 
+	   Usage:
+	      md=loadresultsfromdisk(md=False,filename=False);
+	"""
+
+	#check number of inputs/outputs
+	if not md or not filename:
+		raise ValueError("loadresultsfromdisk: error message.")
+
+	if not md.qmu.isdakota:
+
+		#Check that file exists
+		if not os.path.exists(filename):
+			raise ValueError("binary file '%s' not found." % filename)
+
+		#initialize md.results if not a structure yet
+		if not isinstance(md.results,dict):
+			md.results={}
+
+		#load results onto model
+		structure=parseresultsfromdisk(filename,~md.settings.io_gather)
+		if not len(structure):
+			raise RuntimeError("No result found in binary file '%s'. Check for solution crash." % filename)
+		end
+		md.results[structure[1]['SolutionType']]=structure;
+
+		#recover solution_type from results
+		md.private.solution=structure[1]['SolutionType']
+
+		#read log files onto fields
+		if os.path.exists(md.miscellaneous.name+'.errlog'):
+			with open(md.miscellaneous.name+'.errlog','r') as f:
+				md.results[structure[1]['SolutionType']]['errlog']=[line[:-1] for line in f]
+		else:
+			md.results[structure[1]['SolutionType']]['errlog']=[]
+
+		if os.path.exists(md.miscellaneous.name+'.outlog'):
+			with open(md.miscellaneous.name+'.outlog','r') as f:
+				md.results[structure[1]['SolutionType']]['outlog']=[line[:-1] for line in f]
+		else:
+			md.results[structure[1]['SolutionType']]['outlog']=[]
+
+		if len(md.results[structure[1]['SolutionType']]['errlog']):
+			print ("loadresultsfromcluster info message: error during solution. Check your errlog and outlog model fields.")
+
+	#post processes qmu results if necessary
+	else:
+
+		if not isinstance(md.private.solution,str):
+			md.private.solution=EnumToString(md.private.solution)
+		md=postqmu(md)
+		os.chdir('..')
+
+	return md
+
Index: /issm/trunk-jpl/src/m/solve/marshall.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/marshall.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/marshall.m	(revision 13009)
@@ -0,0 +1,49 @@
+function marshall(md)
+%MARSHALL - outputs a compatible binary file from @model md, for certain solution type.
+%
+%   The routine creates a compatible binary file from @model md
+%   This binary file will be used for parallel runs in JPL-package
+%
+%   Usage:
+%      marshall(md)
+
+disp(['marshalling file ' md.miscellaneous.name '.bin']);
+
+%open file for binary writing
+fid=fopen([ md.miscellaneous.name '.bin'],'wb');
+if fid==-1,
+	error(['marshall error message: could not open ' [md.miscellaneous.name '.bin'],' file for binary writing']);
+end
+
+%First, write MaximumNumberOfEnum to make sure that the Enums are synchronized
+WriteData(fid,'enum',MaximumNumberOfEnums(),'data',true,'format','Boolean');
+
+%Go through all model fields: check that it is a class and call checkconsistency
+fields=properties('model');
+for i=1:length(fields),
+	field=fields{i};
+
+	%Some properties do not need to be marshalled
+	if ismember(field,{'results' 'radaroverlay' 'solver' 'cluster'  'flaim' 'private'}),
+		continue;
+	end
+
+	%Check that current field is an object
+	if ~isobject(md.(field))
+		error(['field ''' char(field) ''' is not an object']);
+	end
+
+	%Marshall current object
+	%disp(['marshalling ' field '...']);
+	if verLessThan('matlab', '7.6')
+		marshall(md.(field),fid);
+	else
+		md.(field).marshall(fid);
+	end
+end
+
+%close file
+st=fclose(fid);
+if st==-1,
+	error(['marshall error message: could not close file ' [md.miscellaneous.name '.bin']]);
+end
Index: /issm/trunk-jpl/src/m/solve/marshall.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/marshall.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/marshall.py	(revision 13009)
@@ -0,0 +1,47 @@
+from WriteData import *
+
+def marshall(md):
+	"""
+	MARSHALL - outputs a compatible binary file from @model md, for certain solution type.
+
+	   The routine creates a compatible binary file from @model md
+	   This binary file will be used for parallel runs in JPL-package
+
+	   Usage:
+	      marshall(md)
+	"""
+
+	print "marshalling file '%s.bin'." % md.miscellaneous.name
+
+	#open file for binary writing
+	try:
+		fid=open(md.miscellaneous.name+'.bin','wb')
+	except IOError as e:
+		raise IOError("marshall error message: could not open '%s.bin' file for binary writing." % md.miscellaneous.name)
+
+	#First, write MaximumNumberOfEnum to make sure that the Enums are synchronized
+	WriteData(fid,'enum',MaximumNumberOfEnums(),'data',True,'format','Boolean')
+
+	#Go through all model fields: check that it is a class and call checkconsistency
+	fields=vars(md)
+
+	for field in fields.iterkeys():
+
+		#Some properties do not need to be marshalled
+		if field in ['results','radaroverlay','solver','cluster','flaim','private']:
+			continue
+
+		#Check that current field is an object
+		if not hasattr(getattr(md,field),'marshall'):
+			raise TypeError("field '%s' is not an object." % field)
+
+		#Marshall current object
+		#print "marshalling %s ..." % field
+		exec("md.%s.marshall(fid)" % field)
+
+	#close file
+	try:
+		f.close(fid)
+	except IOError as e:
+		raise IOError("marshall error message: could not close file '%s.bin'." % md.miscellaneous.name)
+
Index: /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.m	(revision 13009)
@@ -0,0 +1,212 @@
+function results=parseresultsfromdisk(filename,iosplit)
+%PARSERESULTSFROMDISK - ...
+%
+%   Usage:
+%      results=parseresultsfromdisk(filename,iosplit)
+
+if iosplit,
+	results=parseresultsfromdiskiosplit(filename);
+else
+	results=parseresultsfromdiskioserial(filename);
+end
+
+%process patch if necessary
+results=MatlabProcessPatch(results);
+
+function results=parseresultsfromdiskioserial(filename) % {{{
+%PARSERESULTSFROMDISK - ...
+%
+%   Usage:
+%      results=parseresultsfromdiskioserial(filename)
+
+
+%Open file
+fid=fopen(filename,'rb');
+if(fid==-1),
+	error(['loadresultsfromdisk error message: could not open ',filename,' for binary reading']);
+end
+results=struct();
+
+%Read fields until the end of the file.
+result=ReadData(fid);
+while ~isempty(result), 
+	%Get time and step
+	results(result.step).step=result.step;
+	results(result.step).time=result.time; 
+
+	%Add result
+	if (length(results)>=result.step & isfield(results,result.fieldname) & ~strcmp(result.fieldname,'SolutionType')),
+			results(result.step).(result.fieldname)=[ results(result.step).(result.fieldname); result.field];
+	else
+		results(result.step).(result.fieldname)=result.field;
+	end
+
+	%read next result
+	result=ReadData(fid);
+
+end
+
+fclose(fid);
+% }}}
+function results=parseresultsfromdiskiosplit(filename) % {{{
+%PARSERESULTSFROMDISKIOSPLIT - ...
+%
+%   Usage:
+%      results=parseresultsfromdiskiosplit(filename)
+
+
+%Open file
+fid=fopen(filename,'rb');
+if(fid==-1),
+	error(['loadresultsfromdisk error message: could not open ',filename,' for binary reading']);
+end
+results=struct();
+
+%if we have done split I/O, ie, we have results that are fragmented across patches, 
+%do a first pass, and figure out the structure of results
+result=ReadDataDimensions(fid);
+while ~isempty(result),
+
+	%Get time and step
+	results(result.step).step=result.step;
+	results(result.step).time=result.time; 
+
+	%Add result
+	if strcmpi(result.fieldname,'Patch'),
+		results(result.step).(result.fieldname)=[0 result.N];
+	else
+		results(result.step).(result.fieldname)=NaN;
+	end
+
+	%read next result
+	result=ReadDataDimensions(fid);
+end
+
+%do a second pass, and figure out the size of the patches
+fseek(fid,0,-1); %rewind
+result=ReadDataDimensions(fid);
+while ~isempty(result),
+
+	%Add result
+	if strcmpi(result.fieldname,'Patch'),
+		patchdimensions=results(result.step).(result.fieldname);
+		results(result.step).(result.fieldname)=[patchdimensions(1)+result.M result.N];
+	end
+
+	%read next result
+	result=ReadDataDimensions(fid);
+end
+
+%allocate patches
+for i=1:length(results),
+	results(i).Patch=zeros(results(i).Patch(1),results(i).Patch(2));
+	results(i).counter=1; %use to index into the patch
+end
+
+%third pass, this time to read the real information
+fseek(fid,0,-1); %rewind
+result=ReadData(fid);
+while ~isempty(result),
+
+	%Get time and step
+	results(result.step).step=result.step;
+	results(result.step).time=result.time; 
+
+	%Add result
+	if strcmpi(result.fieldname,'Patch'),
+		counter=results(result.step).counter;
+		counter2=counter+size(result.field,1)-1;
+		results(result.step).(result.fieldname)(counter:counter2,:)=result.field;
+
+		%increment counter: 
+		results(result.step).counter=counter2+1;
+	else
+		results(result.step).(result.fieldname)=result.field;
+	end
+
+	%read next result
+	result=ReadData(fid);
+
+end
+
+%close file
+fclose(fid);
+	% }}}
+function result=ReadData(fid) % {{{
+%READDATA - ...
+%
+%   Usage:
+%      field=ReadData(fid)
+
+%read field
+[length,count]=fread(fid,1,'int');
+
+if count==0,
+	result=struct([]);
+else
+	fieldname=fread(fid,length,'char');
+	fieldname=fieldname(1:end-1)';
+	fieldname=char(fieldname);
+	time=fread(fid,1,'double');
+	step=fread(fid,1,'int');
+
+	type=fread(fid,1,'int');
+	M=fread(fid,1,'int');
+	if type==1,
+		field=fread(fid,M,'double');
+	elseif type==2,
+		field=fread(fid,M,'char');
+		field=char(field(1:end-1)');
+	elseif type==3,
+		N=fread(fid,1,'int');
+		field=transpose(fread(fid,[N M],'double'));
+	else
+		error(['cannot read data of type ' num2str(type) ]);
+	end
+
+	result.fieldname=fieldname;
+	result.time=time;
+	result.step=step;
+	result.field=field;
+end
+% }}}
+function result=ReadDataDimensions(fid) % {{{
+%READDATADIMENSIONS - read data dimensions, step and time, but not the data itself.
+%
+%   Usage:
+%      field=ReadDataDimensions(fid)
+
+
+%read field
+[length,count]=fread(fid,1,'int');
+
+if count==0,
+	result=struct([]);
+else
+	fieldname=fread(fid,length,'char');
+	fieldname=fieldname(1:end-1)';
+	fieldname=char(fieldname);
+	time=fread(fid,1,'double');
+	step=fread(fid,1,'int');
+
+	type=fread(fid,1,'int');
+	M=fread(fid,1,'int');
+	N=1; %default
+	if type==1,
+		fseek(fid,M*8,0);
+	elseif type==2,
+		fseek(fid,M,0);
+	elseif type==3,
+		N=fread(fid,1,'int');
+		fseek(fid,N*M*8,0);
+	else
+		error(['cannot read data of type ' num2str(type) ]);
+	end
+
+	result.fieldname=fieldname;
+	result.time=time;
+	result.step=step;
+	result.M=M;
+	result.N=N;
+end
+% }}}
Index: /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/parseresultsfromdisk.py	(revision 13009)
@@ -0,0 +1,235 @@
+import struct
+import numpy
+from MatlabFuncs import *
+from MatlabProcessPatch import *
+
+def parseresultsfromdisk(filename,iosplit):
+	"""
+	PARSERESULTSFROMDISK - ...
+
+	   Usage:
+	      results=parseresultsfromdisk(filename,iosplit)
+	"""
+
+	if iosplit:
+		results=parseresultsfromdiskiosplit(filename)
+	else:
+		results=parseresultsfromdiskioserial(filename)
+
+	#process patch if necessary
+	results=MatlabProcessPatch(results)
+
+	return results
+
+def parseresultsfromdiskioserial(filename):    # {{{
+	"""
+	PARSERESULTSFROMDISK - ...
+	 
+	    Usage:
+	       results=parseresultsfromdiskioserial(filename)
+	"""
+
+	#Open file
+	try:
+		fid=open(filename,'rb')
+	except IOError as e:
+		raise IOError("loadresultsfromdisk error message: could not open '%s' for binary reading." % filename)
+
+	results={}
+
+	#Read fields until the end of the file.
+	result=ReadData(fid)
+	while result:
+		#Get time and step
+		if not result['step'] in results:
+			results[result['step']]={}
+			results[result['step']]['step']=result['step']
+			results[result['step']]['time']=result['time'] 
+	
+		#Add result
+		if result['step'] in results and \
+		   result['fieldname'] in results[result['step']] and \
+		   not strcmp(result['fieldname'],'SolutionType'):
+			results[result['step']][result['fieldname']]=numpy.concatenate((results[result['step']][result['fieldname']],result['field']),axis=0)
+		else:
+			results[result['step']][result['fieldname']]=result['field']
+
+		#read next result
+		result=ReadData(fid)
+
+	fid.close()
+
+	return results
+	# }}}
+
+def parseresultsfromdiskiosplit(filename):    # {{{
+	"""
+	PARSERESULTSFROMDISKIOSPLIT - ...
+	 
+	    Usage:
+	       results=parseresultsfromdiskiosplit(filename)
+	"""
+
+	#Open file
+	try:
+		fid=open(filename,'rb')
+	except IOError as e:
+		raise IOError("loadresultsfromdisk error message: could not open '%s' for binary reading." % filename)
+
+	results={}
+
+	#if we have done split I/O, ie, we have results that are fragmented across patches, 
+	#do a first pass, and figure out the structure of results
+	result=ReadDataDimensions(fid)
+	while result:
+
+		#Get time and step
+		if not result['step'] in results:
+			results[result['step']]={}
+			results[result['step']]['step']=result['step']
+			results[result['step']]['time']=result['time'] 
+
+		#Add result
+		if strcmpi(result['fieldname'],'Patch'):
+			results[result['step']][result['fieldname']]=[0,result['N']]
+		else:
+			results[result['step']][result['fieldname']]=float('NaN')
+
+		#read next result
+		result=ReadDataDimensions(fid)
+
+	#do a second pass, and figure out the size of the patches
+	fid.seek(0)    #rewind
+	result=ReadDataDimensions(fid)
+	while result:
+
+		#Add result
+		if strcmpi(result['fieldname'],'Patch'):
+			patchdimensions=results[result['step']][result['fieldname']]
+			results[result['step']][result['fieldname']]=[patchdimensions[0]+result['M'],result['N']]
+
+		#read next result
+		result=ReadDataDimensions(fid)
+
+	#allocate patches
+	for result in results.itervalues():
+		if 'Patch' in result:
+			result['Patch']=numpy.zeros(shape=(result['Patch'][0],result['Patch'][1]),dtype=float)
+			result['counter']=0    #use to index into the patch
+
+	#third pass, this time to read the real information
+	fid.seek(0)    #rewind
+	result=ReadData(fid)
+	while result:
+
+		#Get time and step
+		if not result['step'] in results:
+			results[result['step']]={}
+			results[result['step']]['step']=result['step']
+			results[result['step']]['time']=result['time'] 
+
+		#Add result
+		if strcmpi(result['fieldname'],'Patch'):
+			counter=results[result['step']]['counter']
+			counter2=counter+result['field'].shape[0]-1
+			results[result['step']][result['fieldname']][counter:counter2,:]=result['field']
+
+			#increment counter: 
+			results[result['step']]['counter']=counter2+1
+		else:
+			results[result['step']][result['fieldname']]=result['field']
+
+		#read next result
+		result=ReadData(fid)
+
+	#close file
+	fid.close()
+
+	return results
+	# }}}
+
+def ReadData(fid):    # {{{
+	"""
+	READDATA - ...
+	 
+	    Usage:
+	       field=ReadData(fid)
+	"""
+
+	#read field
+	try:
+		length=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+
+		fieldname=struct.unpack('%ds' % length,fid.read(length))[0][:-1]
+		time=struct.unpack('d',fid.read(struct.calcsize('d')))[0]
+		step=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+
+		type=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+		M=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+		if   type==1:
+			field=numpy.array(struct.unpack('%dd' % M,fid.read(M*struct.calcsize('d'))),dtype=float)
+		elif type==2:
+			field=struct.unpack('%ds' % M,fid.read(M))[0][:-1]
+		elif type==3:
+			N=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+#			field=transpose(fread(fid,[N M],'double'));
+			field=numpy.zeros(shape=(M,N),dtype=float)
+			for i in xrange(M):
+				field[i,:]=struct.unpack('%dd' % N,fid.read(N*struct.calcsize('d')))
+		else:
+			raise TypeError("cannot read data of type %d" % type)
+
+		result={}
+		result['fieldname']=fieldname
+		result['time']=time
+		result['step']=step
+		result['field']=field
+
+	except struct.error as e:
+		result={}
+
+	return result
+	# }}}
+
+def ReadDataDimensions(fid):    # {{{
+	"""
+	READDATADIMENSIONS - read data dimensions, step and time, but not the data itself.
+	 
+	    Usage:
+	       field=ReadDataDimensions(fid)
+	"""
+
+	#read field
+	try:
+		length=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+
+		fieldname=struct.unpack('%ds' % length,fid.read(length))[0][:-1]
+		time=struct.unpack('d',fid.read(struct.calcsize('d')))[0]
+		step=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+
+		type=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+		M=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+		N=1    #default
+		if   type==1:
+			fid.seek(M*8,1)
+		elif type==2:
+			fid.seek(M,1)
+		elif type==3:
+			N=struct.unpack('i',fid.read(struct.calcsize('i')))[0]
+			fid.seek(N*M*8,1)
+		else:
+			raise TypeError("cannot read data of type %d" % type)
+
+		result={}
+		result['fieldname']=fieldname
+		result['time']=time
+		result['step']=step
+		result['M']=M
+		result['N']=N
+
+	except struct.error as e:
+		result={}
+
+	return result
+	# }}}
+
Index: /issm/trunk-jpl/src/m/solve/process_solve_options.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/process_solve_options.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/process_solve_options.m	(revision 13009)
@@ -0,0 +1,39 @@
+function outoptions=process_solve_options(options)
+%DEFAULT_SOLVE_OPTIONS - set up default options for solve phase
+%
+%   Usage:
+%      options=process_solve_options(options)
+%
+%   See also: SOLVE
+
+%solution_type: check on this option, error out otherwise
+solution_type=getfieldvalue(options,'solution_type');
+if ~ismember(solution_type,[DiagnosticSolutionEnum,PrognosticSolutionEnum,ThermalSolutionEnum,...
+		SteadystateSolutionEnum,TransientSolutionEnum,EnthalpySolutionEnum,...
+		BalancethicknessSolutionEnum,BedSlopeSolutionEnum,SurfaceSlopeSolutionEnum,HydrologySolutionEnum,FlaimSolutionEnum]),
+	error(['process_solve_options error message: solution_type ' EnumToString(solution_type) ' not supported yet!']);
+end
+outoptions.solution_type=solution_type;
+
+outoptions.upload=getfieldvalue(options,'upload','off');
+outoptions.batch=getfieldvalue(options,'batch','no');
+outoptions.loadonly=getfieldvalue(options,'loadonly',false);
+outoptions.directory=getfieldvalue(options,'directory','');
+
+%  process qmu arguments
+outoptions.qmudir=getfieldvalue(options,'qmudir',['qmu' num2str(feature('GetPid'))]);  % qmudir =['qmu_' datestr(now,'yyyymmdd_HHMMSS')];
+outoptions.qmufile=getfieldvalue(options,'qmufile','qmu');% qmufile cannot be changed unless ????script.sh is also changed
+outoptions.overwrite=getfieldvalue(options,'overwrite','n');
+outoptions.keep=getfieldvalue(options,'keep','n');
+outoptions.ivar=getfieldvalue(options,'ivar',1);
+outoptions.iresp=getfieldvalue(options,'iresp',1);
+outoptions.imethod=getfieldvalue(options,'imethod',1);
+outoptions.iparams=getfieldvalue(options,'iparams',1);
+outoptions.runmpi=getfieldvalue(options,'runmpi',false);
+
+%  process flaim arguments
+outoptions.fmdir=getfieldvalue(options,'fmdir',['fm' num2str(feature('GetPid'))]);
+outoptions.overwrite=getfieldvalue(options,'overwrite','n');
+outoptions.keep=getfieldvalue(options,'keep','y');
+outoptions.latsgn=getfieldvalue(options,'latsgn',0);
+outoptions.cmap=getfieldvalue(options,'cmap',[]);
Index: /issm/trunk-jpl/src/m/solve/process_solve_options.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/process_solve_options.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/process_solve_options.py	(revision 13009)
@@ -0,0 +1,48 @@
+import os
+from EnumDefinitions import *
+
+def process_solve_options(options):
+	"""
+	DEFAULT_SOLVE_OPTIONS - set up default options for solve phase
+ 
+	   Usage:
+	      options=process_solve_options(options)
+ 
+	   See also: SOLVE
+	"""
+
+	outoptions={}
+
+	#solution_type: check on this option, error out otherwise
+	solution_type=options.getfieldvalue('solution_type')
+	if not solution_type in (DiagnosticSolutionEnum,PrognosticSolutionEnum,ThermalSolutionEnum,\
+			SteadystateSolutionEnum,TransientSolutionEnum,EnthalpySolutionEnum,\
+			BalancethicknessSolutionEnum,BedSlopeSolutionEnum,SurfaceSlopeSolutionEnum,HydrologySolutionEnum,FlaimSolutionEnum):
+		raise ValueError("process_solve_options error message: solution_type '%s' not supported yet!" % EnumToString(solution_type))
+	outoptions['solution_type']=solution_type
+
+	outoptions['upload']=options.getfieldvalue('upload','off')
+	outoptions['batch']=options.getfieldvalue('batch','no')
+	outoptions['loadonly']=options.getfieldvalue('loadonly',False)
+	outoptions['directory']=options.getfieldvalue('directory','')
+
+	#  process qmu arguments
+	outoptions['qmudir']=options.getfieldvalue('qmudir','qmu'+str(os.getpid()))
+	outoptions['qmufile']=options.getfieldvalue('qmufile','qmu')    # qmufile cannot be changed unless ????script.sh is also changed
+	outoptions['overwrite']=options.getfieldvalue('overwrite','n')
+	outoptions['keep']=options.getfieldvalue('keep','n')
+	outoptions['ivar']=options.getfieldvalue('ivar',1)
+	outoptions['iresp']=options.getfieldvalue('iresp',1)
+	outoptions['imethod']=options.getfieldvalue('imethod',1)
+	outoptions['iparams']=options.getfieldvalue('iparams',1)
+	outoptions['runmpi']=options.getfieldvalue('runmpi',False)
+
+	#  process flaim arguments
+	outoptions['fmdir']=options.getfieldvalue('fmdir','fm'+str(os.getpid()))
+	outoptions['overwrite']=options.getfieldvalue('overwrite','n')
+	outoptions['keep']=options.getfieldvalue('keep','y')
+	outoptions['latsgn']=options.getfieldvalue('latsgn',0)
+	outoptions['cmap']=options.getfieldvalue('cmap',[])
+
+	return outoptions
+
Index: /issm/trunk-jpl/src/m/solve/solve.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/solve.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/solve.m	(revision 13009)
@@ -0,0 +1,121 @@
+function md=solve(md,solutionenum,varargin)
+%SOLVE - apply solution sequence for this model
+%
+%   Usage:
+%      md=solve(md,solutionenum,varargin)
+%      where varargin is a lit of paired arguments of string OR enums
+%
+%   solution types available comprise:
+%		 - DiagnosticSolutionEnum
+%		 - PrognosticSolutionEnum
+%		 - ThermalSolutionEnum
+%		 - SteadystateSolutionEnum
+%		 - TransientSolutionEnum...
+%		 - BalancethicknessSolutionEnum
+%		 - BedSlopeSolutionEnum
+%		 - SurfaceSlopeSolutionEnum
+%		 - HydrologySolutionEnum
+%		 - FlaimSolutionEnum
+%
+%  extra options:
+%      - loadonly : does not solve. only load results
+%
+%   Examples:
+%      md=solve(md,DiagnosticSolutionEnum);
+
+%recover and process solve options
+options=pairoptions(varargin{:},'solution_type',solutionenum);
+options=process_solve_options(options);
+
+%recover some fields
+md.private.solution=options.solution_type;
+cluster=md.cluster;
+
+%check model consistency
+disp('checking model consistency');
+if (solutionenum == FlaimSolutionEnum)
+	md.private.isconsistent=true;
+	md=checkconsistency(md.mesh,md,solutionenum);
+	md=checkconsistency(md.flaim,md,solutionenum);
+	if md.private.isconsistent==false,
+		error('Model not consistent, see messages above');
+	end
+else
+	ismodelselfconsistent(md),
+end
+
+%First, build a runtime name that is unique
+c=clock;
+md.private.runtimename=sprintf('%s-%02i-%02i-%04i-%02i-%02i-%02i-%i',md.miscellaneous.name,c(2),c(3),c(1),c(4),c(5),floor(c(6)),feature('GetPid'));
+
+%if running qmu analysis, some preprocessing of dakota files using models
+%fields needs to be carried out. 
+if md.qmu.isdakota,
+	md=preqmu(md,options);
+end
+
+%flaim analysis
+if (options.solution_type == FlaimSolutionEnum)
+	md=flaim_sol(md,options);
+	md.private.solution=EnumToString(options.solution_type);
+	return;
+end
+
+%Do we load results only?
+if options.loadonly,  
+	md=loadresultsfromcluster(md);
+	return;
+end
+
+%we need to make sure we have PETSC support, otherwise, we run with only one cpu: 
+if ~ispetsc,
+	disp('PETSC support not included, running on 1 cpu only!');
+	cluster.np=1;
+end
+
+
+%Wite all input files
+marshall(md);                                          % bin file
+PetscFile(md.solver,[md.miscellaneous.name '.petsc']); % petsc file
+BuildQueueScript(cluster,md.private.runtimename,md.miscellaneous.name,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof); % queue file
+
+
+%Stop here if batch mode
+if strcmpi(options.batch,'yes')
+	disp('batch mode requested: not launching job interactively');
+	disp('launch solution sequence on remote cluster by hand');
+	return;
+end
+
+%Launch job
+modelname = md.miscellaneous.name;
+filelist  = {[modelname '.bin '] [modelname '.petsc '] [modelname '.queue ']};
+if md.qmu.isdakota,
+	filelist{end+1} = [modelname '.qmu.in'];
+end
+LaunchQueueJob(cluster,md.miscellaneous.name,md.private.runtimename,filelist);
+
+%did we even try to run? if so, wait on lock
+if strcmpi(options.upload,'on'),
+	disp('solve done uploading test decks');
+	return;
+end
+
+%wait on lock
+if md.settings.waitonlock>0,
+	%we wait for the done file
+	islock=waitonlock(md);
+	if islock==0, %no results to be loaded
+		disp('The results must be loaded manually with md=loadresultsfromcluster(md).');
+	else          %load results
+		disp('loading results from cluster');
+		md=loadresultsfromcluster(md);
+	end
+end
+
+%post processes qmu results if necessary
+if md.qmu.isdakota,
+	if ~strncmpi(options.keep,'y',1)
+		system(['rm -rf qmu' num2str(feature('GetPid'))]);
+	end
+end
Index: /issm/trunk-jpl/src/m/solve/solve.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/solve.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/solve.py	(revision 13009)
@@ -0,0 +1,119 @@
+import datetime
+import os
+import shutil
+from pairoptions import *
+from process_solve_options import *
+from EnumDefinitions import *
+from ismodelselfconsistent import *
+
+def solve(md,solutionenum,*args):
+	"""
+	SOLVE - apply solution sequence for this model
+ 
+	   Usage:
+	      md=solve(md,solutionenum,varargin)
+	      where varargin is a list of paired arguments of string OR enums
+ 
+	   solution types available comprise:
+	      - DiagnosticSolutionEnum
+	      - PrognosticSolutionEnum
+	      - ThermalSolutionEnum
+	      - SteadystateSolutionEnum
+	      - TransientSolutionEnum...
+	      - BalancethicknessSolutionEnum
+	      - BedSlopeSolutionEnum
+	      - SurfaceSlopeSolutionEnum
+	      - HydrologySolutionEnum
+	      - FlaimSolutionEnum
+ 
+	   extra options:
+	      - loadonly : does not solve. only load results
+ 
+	   Examples:
+	      md=solve(md,DiagnosticSolutionEnum);
+	"""
+
+	#recover and process solve options
+	options=pairoptions('solution_type',solutionenum,*args)
+	options=process_solve_options(options)
+
+	#recover some fields
+	md.private.solution=options['solution_type']
+	cluster=md.cluster
+
+	#check model consistency
+	print "checking model consistency"
+	if solutionenum == FlaimSolutionEnum:
+		md.private.isconsistent=True
+		md.mesh.checkconsistency(md,solutionenum)
+		md.flaim.checkconsistency(md,solutionenum)
+		if not md.private.isconsistent:
+			raise RuntimeError("Model not consistent, see messages above.")
+	else:
+		ismodelselfconsistent(md)
+
+	#First, build a runtime name that is unique
+	c=datetime.datetime.now()
+	md.private.runtimename="%s-%02i-%02i-%04i-%02i-%02i-%02i-%i" % (md.miscellaneous.name,c.month,c.day,c.year,c.hour,c.minute,c.second,os.getpid())
+
+	#if running qmu analysis, some preprocessing of dakota files using models
+	#fields needs to be carried out. 
+	if md.qmu.isdakota:
+		md=preqmu(md,options)
+
+	#flaim analysis
+	if options['solution_type'] == FlaimSolutionEnum:
+		md=flaim_sol(md,options)
+		md.private.solution=EnumToString(options['solution_type'])
+		return md
+
+	#Do we load results only?
+	if options['loadonly']:  
+		md=loadresultsfromcluster(md)
+		return md
+
+	#Wite all input files
+	marshall(md)                                           # bin file
+	md.solver.PetscFile(md.miscellaneous.name+'.petsc')    # petsc file
+	cluster.BuildQueueScript(md.miscellaneous.name,md.private.runtimename,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof)    # queue file
+
+	#we need to make sure we have PETSC support, otherwise, we run with only one cpu: 
+	if not ispetsc:
+		print "PETSC support not included, running on 1 cpu only!"
+		cluster.np=1
+
+	#Stop here if batch mode
+	if strcmpi(options['batch'],'yes'):
+		print 'batch mode requested: not launching job interactively'
+		print 'launch solution sequence on remote cluster by hand'
+		return md
+
+	#Launch job
+	modelname = md.miscellaneous.name
+	filelist  = [modelname+'.bin ',modelname+'.petsc ',modelname+'.queue ']
+	if md.qmu.isdakota:
+		filelist.append(modelname+'.qmu.in')
+	cluster.LaunchQueueJob(md.miscellaneous.name,md.private.runtimename,filelist)
+
+	#did we even try to run? if so, wait on lock
+	if strcmpi(options['upload'],'on'):
+		print 'solve done uploading test decks'
+		return md
+
+	#wait on lock
+	if md.settings.waitonlock>0:
+		#we wait for the done file
+		islock=waitonlock(md)
+		if islock==0:    #no results to be loaded
+			print 'The results must be loaded manually with md=loadresultsfromcluster(md).'
+		else:            #load results
+			print 'loading results from cluster'
+			md=loadresultsfromcluster(md)
+
+	#post processes qmu results if necessary
+	if md.qmu.isdakota:
+		if not strncmpi(options['keep'],'y',1):
+			shutil.rmtree('qmu'+str(os.getpid()))
+
+	return md
+
Index: /issm/trunk-jpl/src/m/solve/waitonlock.m
===================================================================
--- /issm/trunk-jpl/src/m/solve/waitonlock.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/waitonlock.m	(revision 13009)
@@ -0,0 +1,58 @@
+function flag=waitonlock(md,executionpath,login,port)
+%WAITONLOCK - wait for a file
+%
+%   This routine will return when a file named 'filename' is written to disk.
+%   If the time limit given in input is exceeded, return 0
+%
+%   Usage:
+%      flag=waitonlock(md,executionpath)
+
+%Get filename (lock file) and options
+executionpath=md.cluster.executionpath;
+cluster=md.cluster.name;
+login=md.cluster.login;
+port=md.cluster.port;
+timelimit=md.settings.waitonlock;
+filename=[executionpath '/' md.private.runtimename '/' md.miscellaneous.name '.lock'];
+
+%waitonlock will work if the lock is on the same machine only: 
+if ~strcmpi(oshostname(),cluster),
+
+	disp('solution launched on remote cluster. log in to detect job completion.');
+	choice=input('Is the job successfully completed? (y/n)','s');
+	if ~strcmp(choice,'y'), 
+		disp('Results not loaded... exiting'); 
+		flag=0;
+	else
+		flag=1;
+	end
+
+%job is running on the same machine
+else
+
+	if ismember('interactive',properties(md.cluster)) & md.cluster.interactive
+		%We are in interactive mode, no need to check for job completion
+		flag=1;
+		return;
+	end
+	%initialize time and file presence test flag
+	time=0; ispresent=0;
+	disp(['waiting for ' filename ' hold on... (Ctrl+C to exit)'])
+
+	%loop till file .lock exist or time is up
+	while (ispresent==0 & time<timelimit)
+		ispresent=exist(filename,'file');
+		pause(1);
+		time=time+1/60;
+	end
+
+	%build output
+	if (time>timelimit),
+		disp('Time limit exceeded. Increase md.settings.waitonlock');
+		disp('The results must be loaded manually with md=loadresultsfromcluster(md).');
+		error(['waitonlock error message: time limit exceeded']);
+		flag=0;
+	else
+		flag=1;
+	end
+end
Index: /issm/trunk-jpl/src/m/solve/waitonlock.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 13009)
@@ -0,0 +1,64 @@
+import os
+import socket
+import time
+from MatlabFuncs import *
+
+def waitonlock(md,executionpath,login,port):
+	"""
+	WAITONLOCK - wait for a file
+ 
+	   This routine will return when a file named 'filename' is written to disk.
+	   If the time limit given in input is exceeded, return 0
+ 
+	   Usage:
+	      flag=waitonlock(md,executionpath)
+	"""
+
+	#Get filename (lock file) and options
+	executionpath=md.cluster.executionpath
+	cluster=md.cluster.name
+	login=md.cluster.login
+	port=md.cluster.port
+	timelimit=md.settings.waitonlock
+	filename=os.path.join(executionpath,md.private.runtimename,md.miscellaneous.name+'.lock')
+
+	#waitonlock will work if the lock is on the same machine only: 
+	if not strcmpi(socket.gethostname().lower().split('.')[0],cluster):
+
+		print 'solution launched on remote cluster. log in to detect job completion.'
+		choice=raw_input('Is the job successfully completed? (y/n) ')
+		if not strcmp(choice,'y'): 
+			print 'Results not loaded... exiting' 
+			flag=0
+		else:
+			flag=1
+
+	#job is running on the same machine
+	else:
+
+		if 'interactive' in vars(md.cluster) and md.cluster.interactive:
+			#We are in interactive mode, no need to check for job completion
+			flag=1
+			return flag
+		#initialize time and file presence test flag
+		etime=0
+		ispresent=0
+		print "waiting for '%s' hold on... (Ctrl+C to exit)" % filename
+
+		#loop till file .lock exist or time is up
+		while ispresent==0 and etime<timelimit:
+			ispresent=os.path.exist(filename)
+			time.sleep(1)
+			etime+=1/60
+
+		#build output
+		if etime>timelimit:
+			print 'Time limit exceeded. Increase md.settings.waitonlock'
+			print 'The results must be loaded manually with md=loadresultsfromcluster(md).'
+			raise RuntimeError('waitonlock error message: time limit exceeded.')
+			flag=0
+		else:
+			flag=1
+
+	return flag
+
Index: /issm/trunk-jpl/src/m/solvers/asmoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/asmoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/asmoptions.m	(revision 13009)
@@ -0,0 +1,18 @@
+function asm=asmoptions(varargin)
+%ASMOPTIONS - return Additive Shwartz Method petsc options
+%
+%   Usage:
+%      options=asmoptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+asm=struct();
+
+%default asm options
+asm.mat_type=getfieldvalue(options,'mat_type','aij');
+asm.ksp_type=getfieldvalue(options,'ksp_type','gmres');
+asm.pc_type=getfieldvalue(options,'pc_type','asm');
+asm.sub_pc_type=getfieldvalue(options,'sub_pc_type','lu');
+asm.pc_asm_overlap=getfieldvalue(options,'pc_asm_overlap',3);
+asm.ksp_max_it=getfieldvalue(options,'ksp_max_it',100);
+asm.ksp_rtol=getfieldvalue(options,'ksp_rtol',1e-30);
Index: /issm/trunk-jpl/src/m/solvers/asmoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/asmoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/asmoptions.py	(revision 13009)
@@ -0,0 +1,31 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def asmoptions(*args):
+	#ASMOPTIONS - return ASM petsc options
+	#
+	#   Usage:
+	#      options=asmoptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+	
+	options=[['mat_type','aij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','lu'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-30]];
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
Index: /issm/trunk-jpl/src/m/solvers/iluasmoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/iluasmoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/iluasmoptions.m	(revision 13009)
@@ -0,0 +1,18 @@
+function iluasm=iluasmoptions(varargin)
+%ILUASMOPTIONS - 
+%
+%   Usage:
+%      options=iluasmoptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+iluasm=struct();
+
+%default iluasm options
+iluasm.mat_type=getfieldvalue(options,'mat_type','aij');
+iluasm.ksp_type=getfieldvalue(options,'ksp_type','gmres');
+iluasm.pc_type=getfieldvalue(options,'pc_type','asm');
+iluasm.sub_pc_type=getfieldvalue(options,'sub_pc_type','ilu');
+iluasm.pc_asm_overlap=getfieldvalue(options,'pc_asm_overlap',5);
+iluasm.ksp_max_it=getfieldvalue(options,'ksp_max_it',100);
+iluasm.ksp_rtol=getfieldvalue(options,'ksp_rtol',1e-15);
Index: /issm/trunk-jpl/src/m/solvers/iluasmoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/iluasmoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/iluasmoptions.py	(revision 13009)
@@ -0,0 +1,25 @@
+from pairoptions import *
+
+def iluasmoptions(*args):
+	"""
+	ILUASMOPTIONS - 
+
+	   Usage:
+	      options=iluasmoptions;
+	"""
+			 
+	#retrieve options provided in varargin
+	options=pairoptions(*args)
+	iluasm={}
+
+	#default iluasm options
+	iluasm['mat_type']=options.getfieldvalue('mat_type','aij')
+	iluasm['ksp_type']=options.getfieldvalue('ksp_type','gmres')
+	iluasm['pc_type']=options.getfieldvalue('pc_type','asm')
+	iluasm['sub_pc_type']=options.getfieldvalue('sub_pc_type','ilu')
+	iluasm['pc_asm_overlap']=options.getfieldvalue('pc_asm_overlap',5)
+	iluasm['ksp_max_it']=options.getfieldvalue('ksp_max_it',100)
+	iluasm['ksp_rtol']=options.getfieldvalue('ksp_rtol',1e-15)
+
+	return iluasm
+
Index: /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.m	(revision 13009)
@@ -0,0 +1,18 @@
+function jacobiasm=jacobiasmoptions(varargin)
+%ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options
+%
+%   Usage:
+%      options=jacobiasmoptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+jacobiasm=struct();
+
+%default jacobiasm options
+jacobiasm.mat_type=getfieldvalue(options,'mat_type','aij');
+jacobiasm.ksp_type=getfieldvalue(options,'ksp_type','gmres');
+jacobiasm.pc_type=getfieldvalue(options,'pc_type','asm');
+jacobiasm.sub_pc_type=getfieldvalue(options,'sub_pc_type','jacobi');
+jacobiasm.pc_asm_overlap=getfieldvalue(options,'pc_asm_overlap',3);
+jacobiasm.ksp_max_it=getfieldvalue(options,'ksp_max_it',100);
+jacobiasm.ksp_rtol=getfieldvalue(options,'ksp_rtol',1e-15);
Index: /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/jacobiasmoptions.py	(revision 13009)
@@ -0,0 +1,31 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def jacobiasmoptions(*args):
+	#ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options
+	#
+	#   Usage:
+	#      options=jacobiasmoptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+	
+	options=[['mat_type','aij'],['ksp_type','gmres'],['pc_type','asm'],['sub_pc_type','jacobi'],['pc_asm_overlap',3],['ksp_max_it',100],['ksp_rtol',1e-15]];
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
Index: /issm/trunk-jpl/src/m/solvers/jacobicgoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/jacobicgoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/jacobicgoptions.m	(revision 13009)
@@ -0,0 +1,15 @@
+function jacobicg=jacobiacgoptions(varargin)
+%ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options
+%
+%   Usage:
+%      options=jacobiasmoptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+jacobicg=struct();
+
+%default jacobiasm options
+jacobicg.mat_type=getfieldvalue(options,'mat_type','aij');
+jacobicg.ksp_type=getfieldvalue(options,'ksp_type','cg');
+jacobicg.ksp_max_it=getfieldvalue(options,'ksp_max_it',100);
+jacobicg.ksp_rtol=getfieldvalue(options,'ksp_rtol',1e-15);
Index: /issm/trunk-jpl/src/m/solvers/jacobicgoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/jacobicgoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/jacobicgoptions.py	(revision 13009)
@@ -0,0 +1,31 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def jacobicgoptions(*args):
+	#ASMOPTIONS - return Additive Shwartz Method with Jacobi preconditioner petsc options
+	#
+	#   Usage:
+	#      options=jacobicgoptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+	
+	options=[['mat_type','aij'],['ksp_type','cg'],['ksp_max_it',100],['ksp_rtol',1e-15]];
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
Index: /issm/trunk-jpl/src/m/solvers/matlaboptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/matlaboptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/matlaboptions.m	(revision 13009)
@@ -0,0 +1,12 @@
+function maltab=matlaboptions(varargin)
+%MATLABOPTIONS - return Matlab petsc options
+%
+%   Usage:
+%      options=matlaboptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+maltab=struct();
+
+%default matlab options
+maltab.ksp_type='matlab';
Index: /issm/trunk-jpl/src/m/solvers/matlaboptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/matlaboptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/matlaboptions.py	(revision 13009)
@@ -0,0 +1,31 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def matlaboptions(*args):
+	#MATLABOPTIONS - return Matlab petsc options
+	#
+	#   Usage:
+	#      options=matlaboptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+	
+	options=[['ksp_type','matlab']];
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
Index: /issm/trunk-jpl/src/m/solvers/mumpsoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/mumpsoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/mumpsoptions.m	(revision 13009)
@@ -0,0 +1,27 @@
+function mumps=mumpsoptions(varargin)
+%MUMPSOPTIONS - return MUMPS direct solver  petsc options
+%
+%   Usage:
+%      options=mumpsoptions;
+
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+mumps=struct();
+
+%default mumps options
+PETSC_VERSION=petscversion();
+if PETSC_VERSION==2,
+	mumps.mat_type=getfieldvalue(options,'mat_type','aijmumps');
+	mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly');
+	mumps.pc_type=getfieldvalue(options,'pc_type','lu');
+	mumps.mat_mumps_icntl_14=getfieldvalue(options,'mat_mumps_icntl_14',120);
+	mumps.pc_factor_shift_positive_definite=getfieldvalue(options,'pc_factor_shift_positive_definite','true');
+end
+if PETSC_VERSION==3,
+	mumps.mat_type=getfieldvalue(options,'mat_type','mpiaij');
+	mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly');
+	mumps.pc_type=getfieldvalue(options,'pc_type','lu');
+	mumps.pc_factor_mat_solver_package=getfieldvalue(options,'pc_factor_mat_solver_package','mumps');
+	mumps.mat_mumps_icntl_14=getfieldvalue(options,'mat_mumps_icntl_14',120);
+	mumps.pc_factor_shift_positive_definite=getfieldvalue(options,'pc_factor_shift_positive_definite','true');
+end
Index: /issm/trunk-jpl/src/m/solvers/mumpsoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/mumpsoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/mumpsoptions.py	(revision 13009)
@@ -0,0 +1,33 @@
+from pairoptions import *
+from petscversion import *
+
+def mumpsoptions(*args):
+	"""
+	MUMPSOPTIONS - return MUMPS direct solver  petsc options
+
+	   Usage:
+	      options=mumpsoptions;
+	"""
+
+	#retrieve options provided in varargin
+	options=pairoptions(*args)
+	mumps={}
+
+	#default mumps options
+	PETSC_VERSION=petscversion()
+	if PETSC_VERSION==2:
+		mumps['mat_type']=options.getfieldvalue('mat_type','aijmumps')
+		mumps['ksp_type']=options.getfieldvalue('ksp_type','preonly')
+		mumps['pc_type']=options.getfieldvalue('pc_type','lu')
+		mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120)
+		mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true')
+	if PETSC_VERSION==3:
+		mumps['mat_type']=options.getfieldvalue('mat_type','mpiaij')
+		mumps['ksp_type']=options.getfieldvalue('ksp_type','preonly')
+		mumps['pc_type']=options.getfieldvalue('pc_type','lu')
+		mumps['pc_factor_mat_solver_package']=options.getfieldvalue('pc_factor_mat_solver_package','mumps')
+		mumps['mat_mumps_icntl_14']=options.getfieldvalue('mat_mumps_icntl_14',120)
+		mumps['pc_factor_shift_positive_definite']=options.getfieldvalue('pc_factor_shift_positive_definite','true')
+
+	return mumps
+
Index: /issm/trunk-jpl/src/m/solvers/soroptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/soroptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/soroptions.m	(revision 13009)
@@ -0,0 +1,16 @@
+function sor=soroptions(varargin)
+%SOROPTIONS - return Relaxation Solver petsc options
+%
+%   Usage:
+%      options=soroptions;
+			 
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+sor=struct();
+
+%default sor options
+sor.mat_type=getfieldvalue(options,'mat_type','aij');
+sor.ksp_type=getfieldvalue(options,'ksp_type','cg');
+sor.pc_type=getfieldvalue(options,'pc_type','sor');
+sor.pc_sor_omega=getfieldvalue(options,'pc_sor_omega',1.1);
+sor.pc_sor_its=getfieldvalue(options,'pc_sor_its',2);
Index: /issm/trunk-jpl/src/m/solvers/soroptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/soroptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/soroptions.py	(revision 13009)
@@ -0,0 +1,31 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def soroptions(*args):
+	#SOROPTIONS - return Relaxation Solver petsc options
+	#
+	#   Usage:
+	#      options=soroptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+	
+	options=[['mat_type','aij'],['ksp_type','cg'],['pc_type','sor'],['pc_sor_omega',1.1],['pc_sor_its',2]];
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
Index: /issm/trunk-jpl/src/m/solvers/stokesoptions.m
===================================================================
--- /issm/trunk-jpl/src/m/solvers/stokesoptions.m	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/stokesoptions.m	(revision 13009)
@@ -0,0 +1,28 @@
+function stokes=stokesoptions(varargin)
+%STOKESOPTIONS - return STOKES multi-physics solver petsc options
+%
+%   Usage:
+%      options=stokesoptions;
+
+%retrieve options provided in varargin
+options=pairoptions(varargin{:});
+stokes=struct();
+
+%default stokes options
+PETSC_VERSION=petscversion();
+if PETSC_VERSION==2,
+	error('stokesoptions error message: multi-physics options not supported in Petsc 2');
+end
+if PETSC_VERSION==3,
+	stokes.mat_type=getfieldvalue(options,'mat_type','mpiaij');
+	stokes.ksp_max_it=getfieldvalue(options,'ksp_max_it',1000);
+	stokes.ksp_type=getfieldvalue(options,'ksp_type','gmres');
+	stokes.pc_type=getfieldvalue(options,'pc_type','fieldsplit');
+	stokes.pc_field_split_type=getfieldvalue(options,'pc_field_split_type','schur');
+	stokes.fieldsplit_0_pc_type=getfieldvalue(options,'fieldsplit_0_pc_type','hypre');
+	stokes.fieldsplit_0_ksp_type=getfieldvalue(options,'fieldsplit_0_ksp_type','gmres');
+	stokes.fieldsplit_0_pc_hypre_type=getfieldvalue(options,'fieldsplit_0_pc_hypre_type','boomerang');
+	stokes.fieldsplit_1_pc_type=getfieldvalue(options,'fieldsplit_1_pc_type','jacobi');
+	stokes.fieldsplit_1_ksp_type=getfieldvalue(options,'fieldsplit_1_ksp_type','preonly');
+	stokes.issm_option_solver=getfieldvalue(options,'issm_option_solver','stokes');
+end
Index: /issm/trunk-jpl/src/m/solvers/stokesoptions.py
===================================================================
--- /issm/trunk-jpl/src/m/solvers/stokesoptions.py	(revision 13009)
+++ /issm/trunk-jpl/src/m/solvers/stokesoptions.py	(revision 13009)
@@ -0,0 +1,40 @@
+#module imports {{{
+from pairoptions import *
+from petscversion  import *
+#}}}
+def stokesoptions(*args):
+	#STOKESOPTIONS - return STOKES multi-physics solver petsc options
+	#
+	#   Usage:
+	#      options=stokesoptions;
+	
+	#retrieve options provided in varargin
+	arguments=pairoptions(*args) 
+
+
+	#default stokes options
+	PETSC_VERSION=petscversion()
+
+	if PETSC_VERSION==2:
+		raise RuntimeError('stokesoptions error message: multi-physics options not supported in Petsc 2')
+	if PETSC_VERSION==3:
+		options=[['mat_type','mpiaij'],['ksp_max_it',1000],['ksp_type','gmres'],['pc_type','fieldsplit'],['pc_field_split_type','schur'],\
+	['fieldsplit_0_pc_type','hypre'],['fieldsplit_0_ksp_type','gmres'],['fieldsplit_0_pc_hypre_type','boomerang'],\
+	['fieldsplit_1_pc_type','jacobi'],['fieldsplit_1_ksp_type','preonly'],['issm_option_solver','stokes']]
+
+	#now, go through our arguments, and write over default options.
+	for i in range(len(arguments.list)):
+		arg1=arguments.list[i][0]
+		arg2=arguments.list[i][1]
+		found=0;
+		for j in range(len(options)):
+			joption=options[j][0]
+			if joption==arg1:
+				joption[1]=arg2;
+				options[j]=joption;
+				found=1;
+				break
+		if not found:
+			#this option did not exist, add it: 
+			options.append([arg1,arg2])
+	return options
