Index: /issm/trunk-jpl/src/m/Array/allempty.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/allempty.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/allempty.m	(revision 12996)
@@ -0,0 +1,22 @@
+%
+%  function to return an empty cell array if all array elements are empty
+%
+%  function [cout]=allempty(cin)
+%
+function [cout]=allempty(cin)
+
+if ~nargin
+    help allempty
+    return
+end
+
+for j=1:numel(cin)
+    if ~isempty(cin{j})
+        cout=cin;
+        return
+    end
+end
+cout={};
+
+end
+
Index: /issm/trunk-jpl/src/m/Array/allequal.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/allequal.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/allequal.m	(revision 12996)
@@ -0,0 +1,70 @@
+%
+%  function to return an empty array if all array elements are
+%  equal to the given value, which may also be empty but not nan.
+%
+%  (note that by definition, nan is not equal to nan.  this could
+%  be changed by using isequalwithequalnans.)
+%
+%  function [aout]=allequal(ain,aval)
+%
+function [aout]=allequal(ain,aval)
+
+if ~nargin
+    help allequal
+    return
+end
+
+aout=ain;
+
+if     islogical(ain) && islogical(aval)
+    for i=1:numel(ain)
+        if ~isequal(ain(i),aval)
+            return
+        end
+    end
+    aout=logical([]);
+
+elseif isnumeric(ain) && isnumeric(aval)
+    for i=1:numel(ain)
+        if ~isequal(ain(i),aval)
+            return
+        end
+    end
+    aout=[];
+
+elseif ischar(ain) && ischar(aval)
+    for i=1:size(ain,1)
+        if ~strcmp(ain(i,:),aval)
+            return
+        end
+    end
+    aout='';
+
+elseif iscell(ain)
+    if     islogical(aval)
+        for i=1:numel(ain)
+            if ~islogical(ain{i}) || ~isequal(ain{i},aval)
+                return
+            end
+        end
+        aout={};
+
+    elseif isnumeric(aval)
+        for i=1:numel(ain)
+            if ~isnumeric(ain{i}) || ~isequal(ain{i},aval)
+                return
+            end
+        end
+        aout={};
+
+    elseif ischar(aval)
+        for i=1:size(ain,1)
+            if ~ischar(ain{i}) || ~strcmp(ain{i},aval)
+                return
+            end
+        end
+        aout={};
+    end
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/allnan.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/allnan.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/allnan.m	(revision 12996)
@@ -0,0 +1,22 @@
+%
+%  function to return an empty double array if all array elements are NaN
+%
+%  function [dout]=allnan(din)
+%
+function [dout]=allnan(din)
+
+if ~nargin
+    help allnan
+    return
+end
+
+for i=1:numel(din)
+    if ~isnan(din(i))
+        dout=din;
+        return
+    end
+end
+dout=[];
+
+end
+
Index: /issm/trunk-jpl/src/m/Array/any2str.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/any2str.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/any2str.m	(revision 12996)
@@ -0,0 +1,22 @@
+%
+%  function to convert anything to a string
+%
+%  function [svec]=any2str(a,alim)
+%
+function [svec]=any2str(a,alim)
+
+if ~exist('alim','var') || (numel(a) <= alim)
+    if iscell(a)
+        svec=string_cell(a);
+    else
+        if (numel(a) > 1) && ~ischar(a)
+            svec=string_vec(a);
+        else
+            svec=item2str(a);
+        end
+    end
+else
+	svec=[string_size(a) ' ''' class(a) ''''];
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/array_numel.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/array_numel.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/array_numel.m	(revision 12996)
@@ -0,0 +1,35 @@
+%
+%  function to find a number of elements from a list of arrays.
+%  
+%  [asize]=array_numel(varargin)
+%
+%  see array_size to check the number and shape of elements, if
+%  multiple indices will be used.
+%
+function [anum]=array_numel(varargin)
+
+anum=1;
+
+for iarg=1:nargin
+    if ischar(varargin{iarg})
+        inum=numel(cellstr(varargin{iarg}));
+    else
+        inum=numel(varargin{iarg});
+    end
+    
+    if ~isequal(inum,1)
+        if isequal(anum,1)
+            anum=inum;
+        else
+            if ~isequal(inum,anum)
+                if ~isempty(inputname(iarg))
+                    error('Array ''%s'' has inconsistent number of elements.',inputname(iarg));
+                else
+                    error('Array %d has inconsistent number of elements.',iarg);
+                end
+            end
+        end
+    end
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/array_size.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/array_size.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/array_size.m	(revision 12996)
@@ -0,0 +1,35 @@
+%
+%  function to find an array size from a list of arrays.
+%  
+%  [asize]=array_size(varargin)
+%
+%  see array_numel to check only the number of elements, if
+%  single indices will be used.
+%
+function [asize]=array_size(varargin)
+
+asize=[1 1];
+
+for iarg=1:nargin
+    if ischar(varargin{iarg})
+        isize=size(cellstr(varargin{iarg}));
+    else
+        isize=size(varargin{iarg});
+    end
+    
+    if ~isequal(isize,[1 1])
+        if isequal(asize,[1 1])
+            asize=isize;
+        else
+            if ~isequal(isize,asize)
+                if ~isempty(inputname(iarg))
+                    error('Array ''%s'' has inconsistent size.',inputname(iarg));
+                else
+                    error('Array %d has inconsistent size.',iarg);
+                end
+            end
+        end
+    end
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/find_string.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/find_string.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/find_string.m	(revision 12996)
@@ -0,0 +1,18 @@
+%
+%  function to find a string in a cell array
+%  (could probably be replaced by matlab strmatch)
+%  
+%  [ifound]=find_string(cells,str)
+%
+function [ifound]=find_string(cells,str)
+
+ifound=false;
+
+for i=1:numel(cells)
+    if ischar(cells{i}) && strcmp(cells{i},str)
+        ifound=i;
+        return
+    end
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/item2str.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/item2str.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/item2str.m	(revision 12996)
@@ -0,0 +1,31 @@
+%
+%  function to convert an item to a string
+%
+%  function [svec]=item2str(a)
+%
+function [svec]=item2str(a)
+
+if     islogical(a)
+    if a
+        svec='true';
+    else
+        svec='false';
+    end
+elseif ischar(a)
+    svec=['''' a ''''];
+elseif isnumeric(a)
+    svec=num2str(a);
+else
+    if ~isempty(inputname(1))
+        warning('item2str:item_unrecog',...
+            'Item ''%s'' is of unrecognized type ''%s''.',...
+            inputname(1),class(a));
+    else
+        warning('item2str:item_unrecog',...
+            'Item %d is of unrecognized type ''%s''.',...
+            1,class(a));
+    end
+    return
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/rotateticklabel.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/rotateticklabel.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/rotateticklabel.m	(revision 12996)
@@ -0,0 +1,69 @@
+function th=rotateticklabel(h,rot,demo)
+%ROTATETICKLABEL rotates tick labels
+%   TH=ROTATETICKLABEL(H,ROT) is the calling form where H is a handle to
+%   the axis that contains the XTickLabels that are to be rotated. ROT is
+%   an optional parameter that specifies the angle of rotation. The default
+%   angle is 90. TH is a handle to the text objects created. For long
+%   strings such as those produced by datetick, you may have to adjust the
+%   position of the axes so the labels don't get cut off.
+%
+%   Of course, GCA can be substituted for H if desired.
+%
+%   TH=ROTATETICKLABEL([],[],'demo') shows a demo figure.
+%
+%   Known deficiencies: if tick labels are raised to a power, the power
+%   will be lost after rotation.
+%
+%   See also datetick.
+
+%   Written Oct 14, 2005 by Andy Bliss
+%   Copyright 2005 by Andy Bliss
+
+%DEMO:
+if nargin==3
+    x=[now-.7 now-.3 now];
+    y=[20 35 15];
+    figure
+    plot(x,y,'.-')
+    datetick('x',0,'keepticks')
+    h=gca;
+    set(h,'position',[0.13 0.35 0.775 0.55])
+    rot=90;
+end
+
+%set the default rotation if user doesn't specify
+if nargin==1
+    rot=90;
+end
+%make sure the rotation is in the range 0:360 (brute force method)
+while rot>360
+    rot=rot-360;
+end
+while rot<0
+    rot=rot+360;
+end
+%get current tick labels
+a=get(h,'XTickLabel');
+%erase current tick labels from figure
+set(h,'XTickLabel',[]);
+%get tick label positions
+b=get(h,'XTick');
+c=get(h,'YTick');
+%make new tick labels
+%  must consider yscale (jes, 9/14/10)
+switch lower(get(h,'YScale'))
+    case 'linear'
+        if rot<180
+            th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','right','rotation',rot,'Interpreter','none');
+        else
+            th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','left','rotation',rot,'Interpreter','none');
+        end
+    case 'log'
+        if rot<180
+            th=text(b,repmat(10^(log10(c(1))-.1*(log10(c(2))-log10(c(1)))),length(b),1),a,'HorizontalAlignment','right','rotation',rot,'Interpreter','none');
+        else
+            th=text(b,repmat(10^(log10(c(1))-.1*(log10(c(2))-log10(c(1)))),length(b),1),a,'HorizontalAlignment','left','rotation',rot,'Interpreter','none');
+        end
+    otherwise
+        set(h,'XTickLabel',a);
+end
Index: /issm/trunk-jpl/src/m/Array/str2int.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/str2int.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/str2int.m	(revision 12996)
@@ -0,0 +1,46 @@
+%
+%  function to find and read the first or last positive integer
+%  in a character string.
+%
+%  function [aint]=str2int(astr,cfl)
+%
+function [aint]=str2int(astr,cfl);
+
+aint=[];
+
+if     ~exist('cfl','var') || strncmpi(cfl,'f',1)
+    i=1;
+
+    while (i <= length(astr))
+        if (astr(i) >= '0' && astr(i) <= '9')
+            aint=sscanf(astr(i:length(astr)),'%d',[1,1]);
+            return
+        else
+            i=i+1;
+        end
+	end
+
+elseif strncmpi(cfl,'l',1)
+    i=length(astr);
+    ifound=false;
+
+    while (i >= 1)
+        if     (astr(i) >= '0' && astr(i) <= '9')
+            ifound=true;
+            i=i-1;
+        elseif ~ifound
+            i=i-1;
+        else
+            aint=sscanf(astr(i+1:length(astr)),'%d',[1,1]);
+            return
+        end
+	end
+
+    if ifound
+        aint=sscanf(astr,'%d',[1,1]);
+        return
+    end
+end
+
+end
+
Index: /issm/trunk-jpl/src/m/Array/string_cell.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/string_cell.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/string_cell.m	(revision 12996)
@@ -0,0 +1,26 @@
+%
+%  function to return the string of a cell array
+%
+%  function [svec]=string_cell(a)
+%
+function [svec]=string_cell(a)
+
+if ~nargin
+    help string_cell
+    return
+end
+
+if (numel(a) == 0)
+    svec='{}';
+    return
+end
+
+%  assemble string for output
+
+svec ='{';
+for i=1:numel(a)-1;
+    svec=[svec item2str(a{i}) ' '];
+end
+svec=[svec item2str(a{end}) '}'];
+
+end
Index: /issm/trunk-jpl/src/m/Array/string_dim.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/string_dim.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/string_dim.m	(revision 12996)
@@ -0,0 +1,72 @@
+%
+%  function to return the string dimension of an array element
+%
+%  function [sdim]=string_dim(a,idim,varargin)
+%
+function [sdim]=string_dim(a,idim,varargin)
+
+if ~nargin
+    help string_dim
+    return
+end
+
+%  check for scalar
+
+if (numel(a) == 1) && (idim == 1)
+    sdim='';
+    return
+end
+
+%  check for overflow
+
+if (idim > numel(a))
+    if ~isempty(inputname(1))
+        error('Index %d exceeds number of elements in array ''%s''.',...
+            idim,inputname(1));
+    else
+        error('Index %d exceeds number of elements in array %d.',...
+            idim,1);
+    end
+end
+
+%  check for column or row vector (Matlab uses a minimum of two
+%  dimensions, so this won't match Matlab standard output)
+
+for iarg=1:nargin-2
+    if strcmpi(varargin{iarg},'vector')
+        if (ndims(a) == 2) && ((size(a,1) == 1) || (size(a,2) == 1))
+            sdim =['(' num2str(idim) ')'];
+            return
+        end
+    end
+end
+
+%  do the general case
+
+asize=size(a);
+index=zeros(size(asize));
+aprod=prod(asize);
+idim =idim-1;
+
+%  calculate indices base 0 and convert to base 1
+
+%  note that ind2sub might be useful, except that it requires a list
+%  of scalars rather than a vector for output.
+
+for i=length(asize):-1:1
+    aprod=aprod/asize(i);
+    index(i)=floor(idim/aprod);
+    idim=idim-index(i)*aprod;
+end
+index=index+1;
+
+%  assemble string for output
+
+sdim ='(';
+for i=1:length(asize)-1;
+    sdim =[sdim num2str(index(i)) ','];
+end
+sdim =[sdim num2str(index(end)) ')'];
+
+end
+
Index: /issm/trunk-jpl/src/m/Array/string_size.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/string_size.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/string_size.m	(revision 12996)
@@ -0,0 +1,38 @@
+%
+%  function to return the string size of an array
+%
+%  function [ssize]=string_size(a,varargin)
+%
+function [ssize]=string_size(a,varargin)
+
+if ~nargin
+    help string_size
+    return
+end
+
+%  check for column or row vector (Matlab uses a minimum of two
+%  dimensions, so this won't match Matlab standard output)
+
+for iarg=1:nargin-1
+    if strcmpi(varargin{iarg},'vector')
+        if (ndims(a) == 2) && ((size(a,1) == 1) || (size(a,2) == 1))
+            ssize =['(' num2str(numel(a)) ')'];
+            return
+        end
+    end
+end
+
+%  do the general case
+
+asize=size(a);
+
+%  assemble string for output
+
+ssize ='(';
+for i=1:length(asize)-1;
+    ssize =[ssize num2str(asize(i)) 'x'];
+end
+ssize =[ssize num2str(asize(end)) ')'];
+
+end
+
Index: /issm/trunk-jpl/src/m/Array/string_vec.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/string_vec.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/string_vec.m	(revision 12996)
@@ -0,0 +1,26 @@
+%
+%  function to return the string of an vector
+%
+%  function [svec]=string_vec(a)
+%
+function [svec]=string_vec(a)
+
+if ~nargin
+    help string_vec
+    return
+end
+
+if (numel(a) == 0)
+    svec='[]';
+    return
+end
+
+%  assemble string for output
+
+svec ='[';
+for i=1:numel(a)-1;
+    svec=[svec item2str(a(i)) ' '];
+end
+svec=[svec item2str(a(end)) ']'];
+
+end
Index: /issm/trunk-jpl/src/m/Array/struc_class.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/struc_class.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/struc_class.m	(revision 12996)
@@ -0,0 +1,30 @@
+%
+%  function to find the structural fields of a specified class
+%  
+%  [sclasso]=struc_class(sclass,cstr)
+%
+function [sclasso]=struc_class(sclass,cstr)
+
+%  collect only the objects of the appropriate class
+
+if     isa(sclass,cstr)
+    if ~isempty(inputname(1))
+        sclasso.(inputname(1))=sclass;
+    else
+        sclasso.(cstr)        =sclass;
+    end
+
+elseif isstruct(sclass)
+    fnames=fieldnames(sclass);
+    for i=1:numel(fnames)
+        if isa(sclass.(fnames{i}),cstr)
+            sclasso.(fnames{i})=sclass.(fnames{i});
+        end
+    end
+end
+
+if ~exist('sclasso','var')
+    sclasso=struct([]);
+end
+
+end
Index: /issm/trunk-jpl/src/m/Array/struc_desc.m
===================================================================
--- /issm/trunk-jpl/src/m/Array/struc_desc.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Array/struc_desc.m	(revision 12996)
@@ -0,0 +1,61 @@
+%
+%  function to find the structures with the specified descriptors
+%  
+%  [sarrayo]=struc_desc(sarray,varargin)
+%
+function [sarrayo]=struc_desc(sarray,varargin)
+
+if ~isfield(sarray,'descriptor')
+    if ~isempty(inputname(1))
+        error('Field ''descriptor'' not found in array ''%s''.',inputname(1));
+    else
+        error('Field ''descriptor'' not found in array %d.',1);
+    end
+end
+
+sarrayo=struct([]);
+
+for iarg=1:nargin-1
+    if     iscell(varargin{iarg})
+        desc=        varargin{iarg};
+    elseif ischar(varargin{iarg})
+        desc=cellstr(varargin{iarg});
+    end
+    
+    for i=1:length(desc)
+        sarrayoi=struc_desci(sarray,desc{i});
+        if ~isempty(sarrayoi)
+            if isempty(sarrayo)
+                sarrayo       =sarrayoi;
+            else
+                sarrayo(end+1)=sarrayoi;
+            end
+        end
+    end
+end
+
+%  if nothing found, return whole array
+
+if isempty(sarrayo)
+    sarrayo=sarray;
+end
+
+end
+
+%
+%  function to find the structure with the specified descriptor
+%  
+function [sarrayo]=struc_desci(sarray,str)
+
+sarrayo=struct([]);
+
+for i=1:numel(sarray)
+    if strcmp(sarray(i).descriptor,str)
+        sarrayo=sarray(i);
+        return
+    end
+end
+
+warning(['String ''' str ''' not found in array ''' inputname(1) '''.']);
+
+end
Index: /issm/trunk-jpl/src/m/BC/SetIceSheetBC.m
===================================================================
--- /issm/trunk-jpl/src/m/BC/SetIceSheetBC.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/BC/SetIceSheetBC.m	(revision 12996)
@@ -0,0 +1,64 @@
+function md=SetIceSheetBC(md)
+%SETICESHEETBC - Create the boundary conditions for diagnostic and thermal models for an IceSheet with no Ice Front
+%
+%   Usage:
+%      md=SetIceSheetBC(md)
+%
+%   See also: SETICESHELFBC, SETMARINEICESHEETBC
+
+%node on Dirichlet
+pos=find(md.mesh.vertexonboundary);
+md.diagnostic.spcvx=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvy=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvz=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvx(pos)=0;
+md.diagnostic.spcvy(pos)=0;
+md.diagnostic.spcvz(pos)=0;
+md.diagnostic.referential=NaN*ones(md.mesh.numberofvertices,6);
+
+%Dirichlet Values
+if (length(md.inversion.vx_obs)==md.mesh.numberofvertices & length(md.inversion.vy_obs)==md.mesh.numberofvertices)
+	disp('      boundary conditions for diagnostic model: spc set as observed velocities');
+	md.diagnostic.spcvx(pos)=md.inversion.vx_obs(pos);
+	md.diagnostic.spcvy(pos)=md.inversion.vy_obs(pos);
+else
+	disp('      boundary conditions for diagnostic model: spc set as zero');
+end
+
+%segment on neumann (Ice Front) -> none
+if (md.mesh.dimension==2)
+	md.diagnostic.icefront=zeros(0,4);
+else
+	md.diagnostic.icefront=zeros(0,6);
+end
+
+%Create zeros basal melting rate and surface mass balance if not specified
+if (isnan(md.surfaceforcings.precipitation) & (md.surfaceforcings.ispdd==1) & (md.surfaceforcings.ispdd==0)),
+	md.surfaceforcings.precipitation=zeros(md.mesh.numberofvertices,1);
+	disp('      no surfaceforcings.precipitation specified: values set as zero');
+end
+if isnan(md.surfaceforcings.mass_balance) & (md.surfaceforcings.ispdd==0),
+	md.surfaceforcings.mass_balance=zeros(md.mesh.numberofvertices,1);
+	disp('      no surfaceforcings.mass_balance specified: values set as zero');
+end
+if isnan(md.basalforcings.melting_rate),
+	md.basalforcings.melting_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no basalforcings.melting_rate specified: values set as zero');
+end
+if isnan(md.balancethickness.thickening_rate),
+	md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no balancethickness.thickening_rate specified: values set as zero');
+end
+
+md.prognostic.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+
+if (length(md.initialization.temperature)==md.mesh.numberofvertices),
+	md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1);
+	pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface
+	if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices),
+		md.basalforcings.geothermalflux=50*10^-3*ones(md.mesh.numberofvertices,1); %50 mW/m^2
+	end
+else
+	disp('      no thermal boundary conditions created: no observed temperature found');
+end
Index: /issm/trunk-jpl/src/m/BC/SetIceShelfBC.m
===================================================================
--- /issm/trunk-jpl/src/m/BC/SetIceShelfBC.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/BC/SetIceShelfBC.m	(revision 12996)
@@ -0,0 +1,95 @@
+function md=SetIceShelfBC(md,varargin)
+%SETICESHELFBC - Create the boundary conditions for diagnostic and thermal models for a  Ice Shelf with Ice Front
+%
+%   Neumann BC are used on the ice front (an ANRGUS contour around the ice front
+%   must be given in input)
+%   Dirichlet BC are used elsewhere for diagnostic
+%
+%   Usage:
+%      md=SetIceShelfBC(md,varargin)
+%
+%   Example:
+%      md=SetIceShelfBC(md);
+%      md=SetIceShelfBC(md,'Front.exp');
+%
+%   See also: SETICESHEETBC, SETMARINEICESHEETBC
+
+%node on Dirichlet (boundary and ~icefront)
+if nargin==2,
+	icefrontfile=varargin{1};
+	if ~exist(icefrontfile), error(['SetIceShelfBC error message: ice front file ' icefrontfile ' not found']); end
+	nodeinsideicefront=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2);
+	nodeonicefront=double(md.mesh.vertexonboundary & nodeinsideicefront);
+elseif nargin==1,
+	nodeonicefront=zeros(md.mesh.numberofvertices,1);
+else
+	help SetIceShelfBC
+	error('bad usage');
+end
+pos=find(md.mesh.vertexonboundary & ~nodeonicefront);
+md.diagnostic.spcvx=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvy=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvz=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvx(pos)=0;
+md.diagnostic.spcvy(pos)=0;
+md.diagnostic.spcvz(pos)=0;
+md.diagnostic.referential=NaN*ones(md.mesh.numberofvertices,6);
+
+%Dirichlet Values
+if (length(md.inversion.vx_obs)==md.mesh.numberofvertices & length(md.inversion.vy_obs)==md.mesh.numberofvertices)
+	disp('      boundary conditions for diagnostic model: spc set as observed velocities');
+	md.diagnostic.spcvx(pos)=md.inversion.vx_obs(pos);
+	md.diagnostic.spcvy(pos)=md.inversion.vy_obs(pos);
+else
+	disp('      boundary conditions for diagnostic model: spc set as zero');
+end
+
+%segment on Ice Front
+%segment on Neumann (Ice Front)
+pos=find(nodeonicefront(md.mesh.segments(:,1)) | nodeonicefront(md.mesh.segments(:,2)));
+if (md.mesh.dimension==2)
+	pressureload=md.mesh.segments(pos,:);
+elseif md.mesh.dimension==3
+	pressureload_layer1=[md.mesh.segments(pos,1:2)  md.mesh.segments(pos,2)+md.mesh.numberofvertices2d  md.mesh.segments(pos,1)+md.mesh.numberofvertices2d  md.mesh.segments(pos,3)];
+	pressureload=[];
+	for i=1:md.mesh.numberoflayers-1,
+		pressureload=[pressureload ;pressureload_layer1(:,1:4)+(i-1)*md.mesh.numberofvertices2d pressureload_layer1(:,5)+(i-1)*md.mesh.numberofelements2d ];
+	end
+end
+
+%Add water or air enum depending on the element
+pressureload=[pressureload 1*md.mask.elementonfloatingice(pressureload(:,end))];
+
+%plug onto model
+md.diagnostic.icefront=pressureload;
+
+%Create zeros basalforcings and surfaceforcings
+if (isnan(md.surfaceforcings.precipitation) & (md.surfaceforcings.ispdd==1) & (md.surfaceforcings.ispdd==0)),
+	md.surfaceforcings.precipitation=zeros(md.mesh.numberofvertices,1);
+	disp('      no surfaceforcings.precipitation specified: values set as zero');
+end
+if isnan(md.surfaceforcings.mass_balance) & (md.surfaceforcings.ispdd==0),
+	        md.surfaceforcings.mass_balance=zeros(md.mesh.numberofvertices,1);
+		disp('      no surfaceforcings.mass_balance specified: values set as zero');
+end
+if isnan(md.basalforcings.melting_rate),
+	md.basalforcings.melting_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no basalforcings.melting_rate specified: values set as zero');
+end
+if isnan(md.balancethickness.thickening_rate),
+	md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no balancethickness.thickening_rate specified: values set as zero');
+end
+
+md.prognostic.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+
+if (length(md.initialization.temperature)==md.mesh.numberofvertices),
+	md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1);
+	pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface
+	if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices),
+		md.basalforcings.geothermalflux=zeros(md.mesh.numberofvertices,1);
+	end
+else
+	disp('      no thermal boundary conditions created: no observed temperature found');
+end
Index: /issm/trunk-jpl/src/m/BC/SetIceShelfBC.py
===================================================================
--- /issm/trunk-jpl/src/m/BC/SetIceShelfBC.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/BC/SetIceShelfBC.py	(revision 12996)
@@ -0,0 +1,98 @@
+import os
+import numpy
+
+def SetIceShelfBC(md,icefrontfile=''):
+	"""
+	SETICESHELFBC - Create the boundary conditions for diagnostic and thermal models for a  Ice Shelf with Ice Front
+
+	   Neumann BC are used on the ice front (an ANRGUS contour around the ice front
+	   must be given in input)
+	   Dirichlet BC are used elsewhere for diagnostic
+
+	   Usage:
+	      md=SetIceShelfBC(md,varargin)
+
+	   Example:
+	      md=SetIceShelfBC(md);
+	      md=SetIceShelfBC(md,'Front.exp');
+
+	   See also: SETICESHEETBC, SETMARINEICESHEETBC
+	"""
+
+	#node on Dirichlet (boundary and ~icefront)
+	if icefrontfile:
+		if not os.path.exists(icefrontfile):
+			raise IOError("SetIceShelfBC error message: ice front file '%s' not found." % icefrontfile)
+		nodeinsideicefront=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2)
+		nodeonicefront=double(md.mesh.vertexonboundary and nodeinsideicefront)
+	else:
+		nodeonicefront=numpy.zeros(md.mesh.numberofvertices)
+
+#	pos=find(md.mesh.vertexonboundary & ~nodeonicefront);
+	pos=[i for i,(vob,noif) in enumerate(zip(md.mesh.vertexonboundary,nodeonicefront)) if vob and not noif]
+	md.diagnostic.spcvx=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+	md.diagnostic.spcvy=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+	md.diagnostic.spcvz=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+	md.diagnostic.spcvx[pos]=0
+	md.diagnostic.spcvy[pos]=0
+	md.diagnostic.spcvz[pos]=0
+	md.diagnostic.referential=float('NaN')*numpy.ones((md.mesh.numberofvertices,6))
+
+	#Dirichlet Values
+	if numpy.size(md.inversion.vx_obs)==md.mesh.numberofvertices and numpy.size(md.inversion.vy_obs)==md.mesh.numberofvertices:
+		print '      boundary conditions for diagnostic model: spc set as observed velocities'
+		md.diagnostic.spcvx[pos]=md.inversion.vx_obs[pos]
+		md.diagnostic.spcvy[pos]=md.inversion.vy_obs[pos]
+	else:
+		print '      boundary conditions for diagnostic model: spc set as zero'
+
+	#segment on Ice Front
+	#segment on Neumann (Ice Front)
+#	pos=find(nodeonicefront(md.mesh.segments(:,1)) | nodeonicefront(md.mesh.segments(:,2)));
+	pos=[i for i,(noif1,noif2) in enumerate(zip(nodeonicefront[md.mesh.segments[:,0].astype('int')-1],nodeonicefront[md.mesh.segments[:,1].astype('int')-1])) if noif1 or noif2]
+	if   md.mesh.dimension==2:
+		pressureload=md.mesh.segments[pos,:]
+	elif md.mesh.dimension==3:
+#		pressureload_layer1=[md.mesh.segments(pos,1:2)  md.mesh.segments(pos,2)+md.mesh.numberofvertices2d  md.mesh.segments(pos,1)+md.mesh.numberofvertices2d  md.mesh.segments(pos,3)];
+		pressureload_layer1=numpy.concatenate((md.mesh.segments[pos,0:2],md.mesh.segments[pos,1]+md.mesh.numberofvertices2d,md.mesh.segments[pos,0]+md.mesh.numberofvertices2d,md.mesh.segments[pos,2]),axis=1)
+		pressureload=numpy.zeros((0,5))
+		for i in xrange(1,md.mesh.numberoflayers):
+#			pressureload=[pressureload ;pressureload_layer1(:,1:4)+(i-1)*md.mesh.numberofvertices2d pressureload_layer1(:,5)+(i-1)*md.mesh.numberofelements2d ];
+			pressureload=numpy.concatenate((pressureload,numpy.concatenate((pressureload_layer1[:,0:3]+(i-1)*md.mesh.numberofvertices2d,pressureload_layer1[:,4]+(i-1)*md.mesh.numberofelements2d),axis=1)),axis=0)
+
+	#Add water or air enum depending on the element
+#	pressureload=[pressureload 1*md.mask.elementonfloatingice(pressureload(:,end))];
+	pressureload=numpy.concatenate((pressureload,1*md.mask.elementonfloatingice[pressureload[:,-1].astype('int')-1].reshape((-1,1))),axis=1)
+
+	#plug onto model
+	md.diagnostic.icefront=pressureload
+
+	#Create zeros basalforcings and surfaceforcings
+	if numpy.isnan(md.surfaceforcings.precipitation).all():
+		md.surfaceforcings.precipitation=numpy.zeros(md.mesh.numberofvertices)
+		print '      no surfaceforcings.precipitation specified: values set as zero'
+	if numpy.isnan(md.surfaceforcings.mass_balance).all():
+		md.surfaceforcings.mass_balance=numpy.zeros(md.mesh.numberofvertices)
+		print '      no surfaceforcings.mass_balance specified: values set as zero'
+	if numpy.isnan(md.basalforcings.melting_rate).all():
+		md.basalforcings.melting_rate=numpy.zeros(md.mesh.numberofvertices)
+		print '      no basalforcings.melting_rate specified: values set as zero'
+	if numpy.isnan(md.balancethickness.thickening_rate).all():
+		md.balancethickness.thickening_rate=numpy.zeros(md.mesh.numberofvertices)
+		print '      no balancethickness.thickening_rate specified: values set as zero'
+
+	md.prognostic.spcthickness=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+	md.balancethickness.spcthickness=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+
+	if numpy.size(md.initialization.temperature)==md.mesh.numberofvertices:
+		md.thermal.spctemperature=float('NaN')*numpy.ones(md.mesh.numberofvertices)
+#		pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface
+		pos=[i for i,vos in enumerate(md.mesh.vertexonsurface) if vos]
+		md.thermal.spctemperature[pos]=md.initialization.temperature[pos]    # impose observed temperature on surface
+		if not numpy.size(md.basalforcings.geothermalflux)==md.mesh.numberofvertices:
+			md.basalforcings.geothermalflux=numpy.zeros(md.mesh.numberofvertices)
+	else:
+		print '      no thermal boundary conditions created: no observed temperature found'
+
+	return md
+
Index: /issm/trunk-jpl/src/m/BC/SetMarineIceSheetBC.m
===================================================================
--- /issm/trunk-jpl/src/m/BC/SetMarineIceSheetBC.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/BC/SetMarineIceSheetBC.m	(revision 12996)
@@ -0,0 +1,107 @@
+function md=SetMarineIceSheetBC(md,varargin)
+%SETICEMARINESHEETBC - Create the boundary conditions for diagnostic and thermal models for a  Marine Ice Sheet with Ice Front
+%
+%   Neumann BC are used on the ice front (an ARGUS contour around the ice front
+%   can be given in input, or it will be deduced as onfloatingice & onboundary)
+%   Dirichlet BC are used elsewhere for diagnostic
+%
+%   Usage:
+%      md=SetMarineIceSheetBC(md,icefrontfile)
+%      md=SetMarineIceSheetBC(md)
+%
+%   Example:
+%      md=SetMarineIceSheetBC(md,'Front.exp')
+%      md=SetMarineIceSheetBC(md)
+%
+%   See also: SETICESHELFBC, SETMARINEICESHEETBC
+
+%node on Dirichlet (boundary and ~icefront)
+if nargin==2,
+	%User provided Front.exp, use it
+	icefrontfile=varargin{1};
+	if ~exist(icefrontfile)
+		error(['SetMarineIceSheetBC error message: ice front file ' icefrontfile ' not found']);
+	end
+	nodeinsideicefront=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2);
+	vertexonicefront=double(md.mesh.vertexonboundary & nodeinsideicefront);
+else
+	%Guess where the ice front is
+	vertexonfloatingice=zeros(md.mesh.numberofvertices,1);
+	vertexonfloatingice(md.mesh.elements(find(md.mask.elementonfloatingice),:))=1;
+	vertexonicefront=double(md.mesh.vertexonboundary & vertexonfloatingice);
+end
+pos=find(md.mesh.vertexonboundary & ~vertexonicefront);
+if isempty(pos),
+	warning('SetMarineIceSheetBC warning: ice front all around the glacier, no dirichlet found. Dirichlet must be added manually')
+end
+md.diagnostic.spcvx=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvy=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvz=NaN*ones(md.mesh.numberofvertices,1);
+md.diagnostic.spcvx(pos)=0;
+md.diagnostic.spcvy(pos)=0;
+md.diagnostic.spcvz(pos)=0;
+md.diagnostic.referential=NaN*ones(md.mesh.numberofvertices,6);
+
+%Dirichlet Values
+if (length(md.inversion.vx_obs)==md.mesh.numberofvertices & length(md.inversion.vy_obs)==md.mesh.numberofvertices)
+	disp('      boundary conditions for diagnostic model: spc set as observed velocities');
+	md.diagnostic.spcvx(pos)=md.inversion.vx_obs(pos);
+	md.diagnostic.spcvy(pos)=md.inversion.vy_obs(pos);
+else
+	disp('      boundary conditions for diagnostic model: spc set as zero');
+end
+
+md.hydrology.spcwatercolumn=zeros(md.mesh.numberofvertices,2);
+pos=find(md.mesh.vertexonboundary); 
+md.hydrology.spcwatercolumn(pos,1)=1;
+
+%segment on Neumann (Ice Front)
+pos=find(vertexonicefront(md.mesh.segments(:,1)) | vertexonicefront(md.mesh.segments(:,2)));
+if (md.mesh.dimension==2)
+	pressureload=md.mesh.segments(pos,:);
+elseif md.mesh.dimension==3
+	pressureload_layer1=[md.mesh.segments(pos,1:2)  md.mesh.segments(pos,2)+md.mesh.numberofvertices2d  md.mesh.segments(pos,1)+md.mesh.numberofvertices2d  md.mesh.segments(pos,3)];
+	pressureload=[];
+	for i=1:md.mesh.numberoflayers-1,
+		pressureload=[pressureload ;pressureload_layer1(:,1:4)+(i-1)*md.mesh.numberofvertices2d pressureload_layer1(:,5)+(i-1)*md.mesh.numberofelements2d ];
+	end
+end
+
+%Add water or air enum depending on the element
+pressureload=[pressureload 1*md.mask.elementonfloatingice(pressureload(:,end))+ 0*md.mask.elementongroundedice(pressureload(:,end))];
+
+%plug onto model
+md.diagnostic.icefront=pressureload;
+
+
+%Create zeros basalforcings and surfaceforcings
+if (isnan(md.surfaceforcings.precipitation)& (md.surfaceforcings.ispdd==1) & (md.surfaceforcings.ispdd==0)),
+	md.surfaceforcings.precipitation=zeros(md.mesh.numberofvertices,1);
+	disp('      no surfaceforcings.precipitation specified: values set as zero');
+end
+if isnan(md.surfaceforcings.mass_balance) & (md.surfaceforcings.ispdd==0),
+	md.surfaceforcings.mass_balance=zeros(md.mesh.numberofvertices,1);
+	disp('      no surfaceforcings.mass_balance specified: values set as zero');
+end
+if isnan(md.basalforcings.melting_rate),
+	md.basalforcings.melting_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no basalforcings.melting_rate specified: values set as zero');
+end
+if isnan(md.balancethickness.thickening_rate),
+	md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1);
+	disp('      no balancethickness.thickening_rate specified: values set as zero');
+end
+
+md.prognostic.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1);
+
+if (length(md.initialization.temperature)==md.mesh.numberofvertices),
+	md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1);
+	pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface
+	if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices),
+		md.basalforcings.geothermalflux=zeros(md.mesh.numberofvertices,1);
+		md.basalforcings.geothermalflux(find(md.mask.vertexongroundedice))=50*10^-3; %50mW/m2
+	end
+else
+	disp('      no thermal boundary conditions created: no observed temperature found');
+end
Index: /issm/trunk-jpl/src/m/Basins/basinzoom.m
===================================================================
--- /issm/trunk-jpl/src/m/Basins/basinzoom.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Basins/basinzoom.m	(revision 12996)
@@ -0,0 +1,94 @@
+function varargout=basinzoom(varargin)
+%ANTZOOM - zoom on a basin in Antarctica or Greenland.
+%
+%   This function zooms on an existing figure describing Antarctica or Greenland 
+%   The zooming depends on the region name provided as input. 
+%
+%   Usage:
+%      varargout=basinzoom(options)
+
+%recover some options, and set defaults
+
+%is varargin an options database already?
+if nargin==0,
+	options=pairoptions(varargin{:});
+elseif (isa(varargin{1},'plotoptions') | isa(varargin{1},'pairoptions')),
+	%do nothing to the varargin: 
+	options=varargin{1};
+else
+	%process varargin for options: 
+	options=pairoptions(varargin{:});
+end
+
+unitmultiplier=getfieldvalue(options,'unit',NaN);
+basin=getfieldvalue(options,'basin');
+
+if exist(options,'basindelta'),
+
+	basindeltax=getfieldvalue(options,'basindelta',300); 
+	basindeltay=getfieldvalue(options,'basindelta',300); 
+else
+	basindeltax=getfieldvalue(options,'basindeltax',300); 
+	basindeltay=getfieldvalue(options,'basindeltay',300);
+end
+
+%multiply by 1000 to get kms
+basindeltax=basindeltax*1000;
+basindeltay=basindeltay*1000;
+
+%Ok, find basin we are talking about: 
+load([jplsvn() '/projects/ModelData/Names/Names.mat']);
+		
+%Go through names: 
+found=0;
+for i=1:size(names,1),
+	if strcmpi(names{i,1},basin),
+		%ok, we've got the region. Get lat and long: 
+		long=names{i,2};
+		lat=names{i,3};
+		hemisphere=names{i,4};
+		found=1;
+		break;
+	end
+end
+
+if ~found,
+	error(['basinzoom error message: cannot find basin ' basin '. Use isbasin to determine a basin name.']);
+end
+
+if hemisphere==+1,
+	central_meridian=getfieldvalue(options,'central_meridian',45);
+	standard_parallel=getfieldvalue(options,'standard_parallel',70);
+else
+	central_meridian=getfieldvalue(options,'central_meridian',0);
+	standard_parallel=getfieldvalue(options,'standard_parallel',71);
+end
+
+%Transform lat long into x,y: 
+[xc,yc]=ll2xy(lat,long,hemisphere,central_meridian,standard_parallel);
+
+%compute x0,x1 and y0,y1 using basindeltax and basindeltay
+x0=xc-basindeltax/2;
+x1=xc+basindeltax/2;
+y0=yc-basindeltay/2;
+y1=yc+basindeltay/2;
+
+if ~isnan(unitmultiplier)
+	x0=x0*unitmultiplier;
+	x1=x1*unitmultiplier;
+	y0=y0*unitmultiplier;
+	y1=y1*unitmultiplier;
+end
+
+%if output arguments are present, return the limits, 
+%otherwise, set them on the current graphic. 
+if nargout==2,
+	found=1;
+	varargout{1}=[x0 x1];
+	varargout{2}=[y0 y1];
+else
+	xlim([x0 x1]);
+	ylim([y0 y1]);
+	found=1;
+	daspect([1;1;1]);
+end
Index: /issm/trunk-jpl/src/m/Basins/isbasin.m
===================================================================
--- /issm/trunk-jpl/src/m/Basins/isbasin.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Basins/isbasin.m	(revision 12996)
@@ -0,0 +1,19 @@
+function isbasin(name)
+%ISBASIN: figure out if a basin name exists.
+%
+%
+%        Usage:  index=isbasin('jks');
+%
+%
+
+
+%First, load basin names:
+load([jplsvn '/projects/ModelData/Names/Names.mat']);
+
+
+%go through names: 
+for i=1:length(names),
+	if ~isempty(strfind(names{i,1},name)),
+		disp(['''' names{i,1} ''' Long:' num2str(names{i,2}) ' Lat:' num2str(names{i,3}) ]);
+	end
+end
Index: /issm/trunk-jpl/src/m/Basins/plotbasins.m
===================================================================
--- /issm/trunk-jpl/src/m/Basins/plotbasins.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Basins/plotbasins.m	(revision 12996)
@@ -0,0 +1,18 @@
+%display all the domain outlines in a directory
+
+basins=listfiles;
+
+hold on
+for i=1:length(basins), 
+	%check whether this is a .exp file
+	basin=basins{i};
+	if strcmpi(basin(end-3:end),'.exp'),
+
+		contour=expread(basin,0);
+		x=contour(1).x;
+		y=contour(1).y;
+		x0=mean(x); y0=mean(y);
+		text(x0,y0,basin(1:end-4),'Fontsize',14);
+		expdisp(basin);
+	end
+end
Index: /issm/trunk-jpl/src/m/Basins/showbasins.m
===================================================================
--- /issm/trunk-jpl/src/m/Basins/showbasins.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Basins/showbasins.m	(revision 12996)
@@ -0,0 +1,69 @@
+function showbasins(varargin)
+%SHOWBASINS - return basins that are within the xlim and ylim
+%
+%   Usage:
+%      names=showbasins(options);
+%   Options: 
+%      'unit' default 1
+%      'hemisphere': default +1;
+%      'central_meridian: 45 for Greenland and 0 for Antarctica
+%      'standard_parallel: 70 for Greenland and 71 for Antarctica
+%
+
+%is varargin an options database already?
+if nargin==0,
+	options=pairoptions(varargin{:});
+elseif (isa(varargin{1},'plotoptions') | isa(varargin{1},'pairoptions')),
+	%do nothing to the varargin: 
+	options=varargin{1};
+else
+	%process varargin for options: 
+	options=pairoptions(varargin{:});
+end
+
+
+%recover some options, and set defaults
+unitmultiplier=getfieldvalue(options,'unit',1);
+fontsize=getfieldvalue(options,'fontsize',12);
+hemisphere=getfieldvalue(options,'hemisphere');
+
+if strcmpi(hemisphere,'s'),
+	hemisphere=-1;
+elseif strcmpi(hemisphere,'n'),
+	hemisphere=+1;
+else
+	error('showbasins error message: hemispehre should be either ''n'' or ''s''');
+	end
+
+if hemisphere==+1,
+	central_meridian=getfieldvalue(options,'central_meridian',45);
+	standard_parallel=getfieldvalue(options,'standard_parallel',70);
+else
+	central_meridian=getfieldvalue(options,'central_meridian',0);
+	standard_parallel=getfieldvalue(options,'standard_parallel',71);
+end
+
+%Ok, find basin we are talking about: 
+load([jplsvn '/projects/ModelData/Names/Names.mat']);
+
+%Get xlim and ylim, and convert into lat,long: 
+xlimits=xlim; x0=xlimits(1); x1=xlimits(2);
+ylimits=ylim; y0=ylimits(1); y1=ylimits(2);
+
+%Convert names lat and long into x,y:
+lat=cell2mat(names(:,3));
+long=cell2mat(names(:,2));
+
+%Now, convert lat,long into x,y:
+[x,y]=ll2xy(lat,long,hemisphere,central_meridian,standard_parallel);
+
+%Find  x,y within xlimits and ylimits: 
+locations=find(x>x0 & x<x1 & y>y0 & y<y1);
+
+%Go through locations, and display the names: 
+for i=1:size(locations,1),
+	hold on,
+	plot(x(locations(i)),y(locations(i)),'r.');
+	t=text(x(locations(i)),y(locations(i)),names{locations(i),1}); 
+	set(t,'FontSize',fontsize);
+end
Index: /issm/trunk-jpl/src/m/Cluster/QueueRequirements.m
===================================================================
--- /issm/trunk-jpl/src/m/Cluster/QueueRequirements.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Cluster/QueueRequirements.m	(revision 12996)
@@ -0,0 +1,35 @@
+function QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,queue,np,time)
+%QUEUEREQUIREMENTS - queue requirements in time, number of cpus, by name of queue.
+%
+%   Usage: 
+%      QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,np,time)
+
+%Ok, go through requirements for current queue:
+index=ismemberi(queue,available_queues);
+if  ~index,
+	%ok, either we a generic cluster, with 'none' queue, or we could not find the queue reqruirements
+	if strcmpi(available_queues{1},'none'),
+		%reset index to 1, so we can fish the requirements
+		index=1;
+	else
+		string=available_queues{1};
+		for i=2:length(available_queues),
+			string=[string ' ' available_queues{i}];
+		end
+		error(['QueueRequirements error message: availables queues are ' string]);
+	end
+end
+
+%check on time requirements
+rtime=queue_requirements_time(index);
+if time<=0,
+	error('QueueRequirements: time should be a positive number');
+end
+if time>rtime,
+	error(['QueueRequirements: time should be < ' num2str(rtime) ' for queue: ' queue]);
+end
+
+%check on np requirements
+if np<=0,
+	error('QueueRequirements: np should be a positive number');
+end
Index: /issm/trunk-jpl/src/m/Cluster/parallelrange.m
===================================================================
--- /issm/trunk-jpl/src/m/Cluster/parallelrange.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Cluster/parallelrange.m	(revision 12996)
@@ -0,0 +1,23 @@
+function [i1,i2]=parallelrange(rank,numprocs,globalsize)
+%PARALLELRANGE - from a rank, and a number of processors, figure out a range, for parallel tasks.
+%
+%   Usage: 
+%      [i1,i1]=parallelrange(rank,numprocs,globalsize)
+
+num_local_rows=zeros(numprocs,1);
+
+for i=1:numprocs,
+	%we use floor. we under distribute rows. The rows left  are then redistributed, therefore resulting in a more even distribution.
+	num_local_rows(i)=floor(globalsize/numprocs);
+end
+
+
+%There may be some rows left. Distribute evenly.
+row_rest=globalsize - numprocs*floor(globalsize/numprocs);
+
+for i=1:row_rest,
+	num_local_rows(i)=num_local_rows(i)+1;
+end
+
+i1=sum(num_local_rows(1:rank-1))+1;
+i2=i1+num_local_rows(rank)-1;
Index: /issm/trunk-jpl/src/m/Cluster/parallelrange.py
===================================================================
--- /issm/trunk-jpl/src/m/Cluster/parallelrange.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/Cluster/parallelrange.py	(revision 12996)
@@ -0,0 +1,25 @@
+#! /usr/bin/env python
+def parallelrange(rank,numprocs,globalsize):
+	"""
+	PARALLELRANGE - from a rank, and a number of processors, figure out a range, for parallel tasks.
+ 
+	   Usage: 
+	      i1,i2=parallelrange(rank,numprocs,globalsize)
+	"""
+
+	#We use floor. we under distribute rows. The rows left are then redistributed, therefore resulting in a more even distribution.
+	num_local_rows=[int(globalsize/numprocs) for i in xrange(numprocs)]
+
+	#There may be some rows left. Distribute evenly.
+	row_rest=globalsize - numprocs*int(globalsize/numprocs)
+
+	for i in xrange(row_rest):
+		num_local_rows[i]=num_local_rows[i]+1
+
+	i1=0
+	for i in xrange(rank-1):
+		i1+=num_local_rows[i]
+	i2=i1+num_local_rows[rank-1]-1
+
+	return i1,i2
+
Index: /issm/trunk-jpl/src/m/DataProcessing/CreateDataBoundaries.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/CreateDataBoundaries.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/CreateDataBoundaries.m	(revision 12996)
@@ -0,0 +1,43 @@
+function	[Xedge,Yedge,EdgeValues]=CreateDataBoundaries(x_m,y_m,x_matrix,y_matrix,datamatrix);
+%CREATEDATABOUNDARIES - Create values on the edge of the matrix
+%
+%   This function create vectors with coordinates and values to constrain a matrix 
+%   on its edge from a given matrix tiwh data everywhere.
+%   x_m and y_m belongs to the matrix to be constrained
+%   x_matrix, y_matrix belongs to the matrix to be constrained with
+%   datamatrix is the matrix with values for the constraint
+%
+%   Usage:
+%      [Xedge,Yedge,EdgeValues]=CreateDataBoundaries(x_m,y_m,x_matrix,y_matrix,datamatrix);
+% 
+%   See also: TRACKSTOMATRIX, CREATEDATAMATRIX
+
+%Check the consistency of the data matrix
+if(length(x_matrix)~=(size(datamatrix,2)+1) | length(y_matrix)~=(size(datamatrix,1)+1)),
+	error('CreateDataBoundaries error message: size of matrix and vectors to constrained not consistent')
+end
+
+nxglobal=length(x_m);
+nyglobal=length(y_m);
+
+%Create the edgevalues and coordinates
+xedge1=x_m(1)*ones(nyglobal,1);
+xedge2=x_m(2:end-1);
+xedge3=x_m(end)*ones(nyglobal,1);
+xedge4=x_m(2:end-1);
+xedge5=x_m(2)*ones(nyglobal-2,1);
+xedge6=x_m(3:end-2);
+xedge7=x_m(end-1)*ones(nyglobal-2,1);
+xedge8=x_m(3:end-2);
+yedge1=y_m;
+yedge2=y_m(1)*ones(nxglobal-2,1);
+yedge3=y_m;
+yedge4=y_m(end)*ones(nxglobal-2,1);
+yedge5=y_m(2:end-1);
+yedge6=y_m(2)*ones(nxglobal-4,1);
+yedge7=y_m(2:end-1);
+yedge8=y_m(end-1)*ones(nxglobal-4,1);
+
+Xedge=[xedge1;xedge2;xedge3;xedge4;xedge5;xedge6;xedge7;xedge8];
+Yedge=[yedge1;yedge2;yedge3;yedge4;yedge5;yedge6;yedge7;yedge8];
+EdgeValues=DataInterp(x_matrix,y_matrix,datamatrix,Xedge,Yedge);
Index: /issm/trunk-jpl/src/m/DataProcessing/CreateDataMatrix.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/CreateDataMatrix.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/CreateDataMatrix.m	(revision 12996)
@@ -0,0 +1,94 @@
+function [Mvalue Mx My]=CreateDataMatrix(x_m,y_m,track_coord,track_values),
+%CREATEDATAMATRIX - Create a map with average values of map 
+%
+%   This routine creates a map with average values of tracks.
+%   x_m1 and y_m1 are two vectors containing the coordinates of the matrix
+%   trac_coord is an exp file containing the coordinates of the tracks (x and y)
+%   trav_values is a vector with the values along the track coordinates
+%
+%   Usage:
+%      [Mvalue Mx My]=CreateDataMatrix(x_m,y_m,track_coord,track_values),
+%
+%   Example:
+%      [Mvalue Mx My]=CreateDataMatrix(x_m,y_m,'trackcoord.exp',thickness_track)
+%
+%   See also: CREATEDATABOUNDARIES, TRACKSTOMATRIX
+
+%Read the points of the tracks
+stru=expread(track_coord,1);
+nods=stru.nods;
+xtracks=stru.x';
+ytracks=stru.y';
+
+%First check that the parameters are ok:
+if (size(track_values,1)~=nods)  || (size(xtracks,2)~=nods) || (size(ytracks,2)~=nods),
+	error('CreateDataMatrix error message : track coordinates and track values must have the same size');
+end
+
+%Compute number of rows and columns
+numrow=size(y_m,1)-1;
+numcol=size(x_m,1)-1;
+
+%Remove useless points of the track
+points=find(track_values==0);
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+points=find(isnan(track_values));
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+points=find(track_values<0);
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+
+points=find(xtracks<x_m(1) | xtracks>x_m(end) | ytracks<y_m(1) | ytracks>y_m(end));
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+
+%initialize some matrices
+numpoints=zeros(numrow,numcol);
+value=zeros(numrow,numcol);
+coordx=zeros(numrow,numcol);
+coordy=zeros(numrow,numcol);
+
+%Loop over the points of the track
+nel=size(track_values,1);
+fprintf('%s','      track processing progress:   0.00 %');
+for i=1:nel;
+	if mod(i,1000)==0,
+		fprintf('\b\b\b\b\b\b\b')
+		fprintf('%5.2f%s',i/nel*100,' %');
+	end
+
+	x=xtracks(i);
+	y=ytracks(i);
+
+	%get indices for the matrix
+	indexx=max(find(x_m<x));
+	indexy=max(find(y_m<y));
+
+	%get weighing coefficient
+	val=track_values(i);
+
+	%update numoverlap and weights
+	numpoints(indexy,indexx)=numpoints(indexy,indexx)+1;
+	value(indexy,indexx)=value(indexy,indexx)+val;
+	coordx(indexy,indexx)=coordx(indexy,indexx)+x;
+	coordy(indexy,indexx)=coordy(indexy,indexx)+y;
+
+end
+if nel>1000,
+	fprintf('\b\b\b\b\b\b\b\b')
+	fprintf('%4.2f%s\n',100,' %');
+end
+
+%Change the values of numoverlap to 1 if 0 since we are going to devide by this matrix
+numpoints(find(~numpoints))=1;
+
+%Create the center of mass for coordiantes and values.
+Mvalue=value./numpoints;
+Mx=coordx./numpoints;
+My=coordy./numpoints;
Index: /issm/trunk-jpl/src/m/DataProcessing/MisfitDeinterlace.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/MisfitDeinterlace.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/MisfitDeinterlace.m	(revision 12996)
@@ -0,0 +1,21 @@
+function Jstruct=MisfitDeinterlace(misfit,type)
+%MISFITDEINTERLACE - deinterlace misfits that are mixed together, using type.
+%
+%   Usage:
+%      Jstruct=MisfitDeinterlace(misfit,type)
+%
+%   Example:
+%      Jstruct=MisfitDeinterlace(md.results.diagnostic.J,md.fit)
+%
+%
+Jstruct=struct();
+
+count=1;
+for i=0:max(type),
+	pos=find(type==i);
+	if length(pos),
+		Jstruct(count).type=i;
+		Jstruct(count).J=misfit(pos);
+		count=count+1;
+	end
+end
Index: /issm/trunk-jpl/src/m/DataProcessing/TracksToMatrix.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/TracksToMatrix.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/TracksToMatrix.m	(revision 12996)
@@ -0,0 +1,84 @@
+function [x_f y_f MatData]=TracksToMatrix(xmin,ymin,nx,ny,posting,track_coord,track_values,theta,varargin),
+%TRACKSTOMATRIX - Create a map from tracks
+%
+%   This routine creates a map from tracks using a Kriging algorithm given by the package DACE.
+%   - xmin and ymin are two scalars that are the extreme values of the data matrix one wants to create
+%   - posting is a scalar giving the posting of the matrix to be created in meters
+%   - trac_coord is an Argus file containing the coordinates of the tracks (x and y)
+%   - trav_values is a vector with the values along the track coordinates
+%   - theta is a parameter of the correlation function stricly positive
+%   varagin can contain a matrix of data to constrain the matrix to be created
+%   it shoud contain indices x and y and the matrix
+%
+%   Usage:
+%      [x_ y_f MatData]=TracksToMatrix(xmin,ymin,nx,ny,posting,track_coord,track_values,theta),
+%
+%   Example:
+%      [x_f y_f Thickness]=TracksToMatrix(-10^6,10^6,200,180,1000,'trackcoord.exp',thickness_values,theta),
+%      [x_f y_f Thickness]=TracksToMatrix(-10^6,10^6,200,180,1000,'trackcoord.exp',thickness_values,theta,x_m,y_m,globalthickness),
+%
+%   See also: CREATEDATABOUNDARIES, CREATEDATAMATRIX
+
+%some checks
+if nargin~=8 & nargin~=11,
+	error(' TracksToMatrix error message: wrong number of arguments')
+end
+
+%Add path to dace
+addpath([issmdir() '/externalpackages/dace/install'])
+
+%First create the x_m and y_m fot the matrix
+x_f=[xmin:posting:xmin+posting*nx]';
+y_f=[ymin:posting:ymin+posting*ny]';
+
+%Now create a bigger map we will then truncate
+x_m=[xmin-posting*nx/2:posting:xmin+posting*nx*3/2]';
+y_m=[ymin-posting*ny/2:posting:ymin+posting*ny*3/2]';
+
+%Create DataMatrix with local averaging of tracks
+[Mvalue Mx My]=CreateDataMatrix(x_m,y_m,track_coord,track_values);
+
+%Create vector for these coordinates and values
+Svalue=sparse(Mvalue);
+Sx=sparse(Mx);
+Sy=sparse(My);
+[i,j,Values]=find(Svalue);
+[i,j,X]=find(Sx);
+[i,j,Y]=find(Sy);
+Coord=[X,Y];
+
+%Create boundaries for the track if specified
+if nargin==11,
+	disp('      constain the border of matrix with global matrix');
+	%Find out the elements to counstrain the border
+	x_matrix=varargin{1};
+	y_matrix=varargin{2};
+	datamatrix=varargin{3};
+
+	%Create values on the border of the smaller map
+	[Xedge,Yedge,EdgeValues]=CreateDataBoundaries(x_m,y_m,x_matrix,y_matrix,datamatrix);
+
+	%Create values on the border of the larger map
+	[Xedge2,Yedge2,EdgeValues2]=CreateDataBoundaries(x_f,y_f,x_matrix,y_matrix,datamatrix);
+
+	%Add these values to the track values
+	Values=[Values;EdgeValues;EdgeValues2];
+	Coord=[X,Y;Xedge,Yedge;Xedge2,Yedge2];
+end
+
+%Create model for data
+disp('      create the statiscal model of the data');
+[dmodel,perf]=dacefit(Coord,Values,@regpoly1,@corrgauss,theta);
+
+%Create design site(points where we are looking for the data)
+Points=nodesamp([x_f(1)+posting/2,y_f(1)+posting/2;x_f(end)-posting/2,y_f(end)-posting/2],[length(x_f)-1;length(y_f)-1]);
+
+%Compute data on these points
+disp('      predict the values');
+VecData=predictor(Points,dmodel);
+
+%Reshape to get a matrix
+MatData=reshape(VecData,ny,nx);
+
+%remove DACE path
+rmpath([issmdir() '/externalpackages/dace/install']);
Index: /issm/trunk-jpl/src/m/DataProcessing/addtrack.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/addtrack.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/addtrack.m	(revision 12996)
@@ -0,0 +1,156 @@
+function [x_m2 y_m2 values2]=addtrack(x_m1,y_m1,values1,track_coord,track_values,distance,exponent,varargin),
+%ADDTRACK - modify a map to take values of a track
+%
+%   This routine modifies a map to improve it with values of tracks.
+%   This output map has more values than the input one so that the values
+%   of the tracks are relevant.
+%   x_m1 and y_m1 are two vectors containing the coordinates of the matrix
+%   the distance between two points must be the same everywhere
+%   values1 is a matrix of size (y_m1-1)*(x_m1-1)
+%   trac_coord is an exp file containing the coordinates of the tracks (x and y)
+%   trav_values is a vector with the values along the track coordinates
+%   distance indicates the distance from the tracks where points have to be modified
+%   exposant allows to chance the influence of the track and the map
+%   it must be positive and usually is superior to 1.
+%
+%   Usage:
+%      [x_m2 y_m2 values1 values2]=addtrack(x_m1,y_m1,values1,track_coord,track_values,distance,exposant[,subdivision])
+%
+%   Example:
+%      [xnew ynew valuesnew]=addtrack(x_m,y_m,thickness,'trackcoord.exp',thickness_track,1000,2)
+%      [xnew ynew valuesnew]=addtrack(x_m,y_m,thickness,'trackcoord.exp',thickness_track,1000,2,3)
+
+%Create a new picture precise enough to be modified by the tracks
+%Read the points of the tracks
+stru=expread(track_coord,1);
+nods=stru.nods;
+xtracks=stru.x';
+ytracks=stru.y';
+
+%First check that the parameters are ok:
+if (size(track_values,1)~=nods)  || (size(xtracks,2)~=nods) || (size(ytracks,2)~=nods),
+	error('addtrack error message : track coordinates and track values must have the same size');
+elseif distance<0,
+	error('addtrack error message : the distance must be a positive value');
+elseif exponent<0,
+	error('addtrack error message : the exponent must be a positive value');
+elseif (size(x_m1,1)~=(size(values1,2)+1)) || (size(y_m1,1)~=(size(values1,1)+1)),
+	error('addtrack error message : problem in the map, check the size of x_m1, y_m1 and values1');
+end
+
+%stru.nods=4;
+%xtracks=[50 50 55 62]; % 2 3 4 5 6 7 8 9 1 ]';
+%ytracks=[40 40.5 41 41]; % 5 5 5 5 5 5 5 5 8 ]';
+%x_m1=[1:10:101]';
+%y_m1=[1:10:101]';
+%track_values=2*ones(4,1);
+%values1=ones(10,10);
+
+%Find the average distance between two points of the tracks
+av_x=sum(abs(diff(xtracks)))/(stru.nods-1);
+av_y=sum(abs(diff(ytracks)))/(stru.nods-1);
+dist_av=sqrt(av_x^2+av_y^2);
+
+%Calculate the multiplicate factor for the new values:
+if nargin==7,
+	mult=round((x_m1(2)-x_m1(1))/(1*dist_av));
+else
+	mult=varargin{1};
+end
+
+%Plug the values in the new multiplied matrix
+values=zeros(mult*size(values1,1),mult*size(values1,2));
+
+for i=1:mult,
+	for j=1:mult,
+		values(i:mult:end,j:mult:end)=values1;
+	end
+end
+
+%Create the new x and y addapted to the matrix
+x_m2=linspace(x_m1(1),x_m1(end),mult*(size(x_m1,1)-1)+1)';
+y_m2=linspace(y_m1(1),y_m1(end),mult*(size(y_m1,1)-1)+1)';
+
+%Create a new set of x and y correponding to the medium value on the matrix
+x_med=(x_m2(1:end-1)+x_m2(2:end))/2;
+y_med=(y_m2(1:end-1)+y_m2(2:end))/2;
+
+numrow=size(y_med,1);
+numcol=size(x_med,1);
+
+%Create new x and y to have the hole matrix
+x_mat=repmat(x_med',numrow,1);
+y_mat=repmat(y_med,1,numcol);
+
+%Remove useless points of the track
+points=find(track_values==0);
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+points=find(isnan(track_values));
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+
+%Remove points outside of the map
+points=find(xtracks<x_med(1) | xtracks>x_med(end) | ytracks<y_med(1) | ytracks>y_med(end));
+track_values(points)=[];
+xtracks(points)=[];
+ytracks(points)=[];
+
+%initialize some matrices
+numoverlap=zeros(numrow,numcol);
+weights=zeros(numrow,numcol);
+weightsvalues=zeros(numrow,numcol);
+
+%Loop over the points of the track
+nel=size(track_values,1);
+fprintf('%s','      track processing progress:   0.00 %');
+for i=1:nel;
+	if mod(i,1000)==0,
+		fprintf('\b\b\b\b\b\b\b')
+		fprintf('%5.2f%s',i/nel*100,' %');
+	end
+
+	x=xtracks(i);
+	y=ytracks(i);
+
+	%get indices that are modified
+	indexx1=max(find(x_med<x-distance));
+	if isempty( indexx1), indexx1=1; end
+	indexx2=min(find(x_med>x+distance));
+	if isempty( indexx2), indexx2=numrow; end
+	indexy1=max(find(y_med<y-distance));
+	if isempty( indexy1), indexy1=1; end
+	indexy2=min(find(y_med>y+distance));
+	if isempty( indexy2), indexy2=numcol; end
+
+
+	%get weighing coefficient
+	val=track_values(i);
+	distances=sqrt((x-x_mat(indexy1:indexy2,indexx1:indexx2)).^2+(y-y_mat(indexy1:indexy2,indexx1:indexx2)).^2);
+	coeff=min(1,(distances/distance)).^(1/exponent);
+
+	%update numoverlap and weights
+	numoverlap(indexy1:indexy2,indexx1:indexx2)=numoverlap(indexy1:indexy2,indexx1:indexx2)+1;
+	weights(indexy1:indexy2,indexx1:indexx2)=weights(indexy1:indexy2,indexx1:indexx2)+coeff;
+	weightsvalues(indexy1:indexy2,indexx1:indexx2)=weightsvalues(indexy1:indexy2,indexx1:indexx2)+(1-coeff)*val;
+
+end
+if nel>1000,
+	fprintf('\b\b\b\b\b\b\b\b')
+	fprintf('%4.2f%s\n',100,' %');
+end
+
+
+%Change the values of numoverlap to 1 if 0 since we are going to devide by this matrix
+numoverlap(find(~numoverlap))=1;
+
+%Same thing for weights since values far from the tracks don't change
+weights(find(~weights))=1;
+
+%Create the final matrix depending on the previous matrix
+values=(values.*weights+weightsvalues)./numoverlap;
+
+%Plug the values of the track in the new matrix
+values2=values;
Index: /issm/trunk-jpl/src/m/DataProcessing/data_processing_tool.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/data_processing_tool.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/data_processing_tool.m	(revision 12996)
@@ -0,0 +1,467 @@
+function varargout = data_processing_tool(varargin)
+%DATA_PROCESSING_TOOL - GUI to process binary data
+%
+%   this routine is a GUI that helps the user to open
+%   a binary file (Little Endian, Big Endian, Float 32,
+%   double,...) and save a Matlab file (.mat) with the
+%   processed data and the coordinates
+%
+%   Usage:
+%      data_processing_tool
+
+	gui_Singleton = 1;
+	gui_State = struct('gui_Name',       mfilename, ...
+		'gui_Singleton',  gui_Singleton, ...
+		'gui_OpeningFcn', @data_processing_tool_OpeningFcn, ...
+		'gui_OutputFcn',  @data_processing_tool_OutputFcn, ...
+		'gui_LayoutFcn',  [] , ...
+		'gui_Callback',   []);
+	if nargin && ischar(varargin{1})
+		gui_State.gui_Callback = str2func(varargin{1});
+	end
+
+	if nargout
+		[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
+	else
+		gui_mainfcn(gui_State, varargin{:});
+	end
+end
+
+function data_processing_tool_OpeningFcn(hObject, eventdata, handles, varargin)
+	handles.output = hObject;
+
+	%enable toolbar (useful for caxis...)
+	set(hObject,'toolbar','figure');
+
+	% Update handles structure
+	guidata(hObject, handles);
+
+	%this variable used to prevent users from breaking the GUI
+	%the variable is set to 1 once the data has been processed
+	handles.processDataCompleted=0;
+
+	%initialize other variables
+	handles.Msize=NaN;
+	handles.Nsize=NaN;
+	handles.numvectors=NaN;
+	handles.endian=NaN;
+	handles.datatype=NaN;
+	handles.dx=NaN;
+	handles.dy=NaN;
+	handles.xEast=NaN;
+	handles.yNorth=NaN;
+
+	%two files permitted
+	set(handles.inputFile,'Max',1);
+	set(handles.inputFile,'Min',0);
+
+	% Update handles structure
+	guidata(hObject, handles);
+end
+
+% --- Outputs from this function are returned to the command line.
+function varargout = data_processing_tool_OutputFcn(hObject, eventdata, handles) 
+
+	% Get default command line output from handles structure
+	varargout{1} = handles.output;
+end
+
+
+function inputFile_Callback(hObject, eventdata, handles)
+%no code needed for this callback, the listbox is only used as a visual
+end
+
+function addFiles_pushbutton_Callback(hObject, eventdata, handles)
+	%gets input file(s) from user. the sample data files have extension .s2p
+	[input_file,pathname] = uigetfile( ...
+		{'*.*', 'All Files (*.*)'}, ...
+		'Select files', ... 
+		'MultiSelect', 'on');
+
+	%if file selection is cancelled, pathname should be zero
+	%and nothing should happen
+	if pathname==0
+		return
+	end
+
+	handles.processDataCompleted=1;
+
+	%gets the current data file names inside the listbox
+	inputFileName=get(handles.inputFile,'String');
+
+	%if they only select one file, then the data will not be a cell
+	inputFileName= fullfile(pathname,input_file);
+
+	%updates the gui to display all filenames in the listbox
+	set(handles.inputFile,'String',inputFileName);
+
+	%make sure first file is always selected so it doesn't go out of range
+	%the GUI will break if this value is out of range
+	set(handles.inputFile,'Value',1);
+
+	% Update handles structure
+	guidata(hObject, handles);
+end
+
+function reset_pushbutton_Callback(hObject, eventdata, handles)
+	%resets the GUI by clearing all relevant fields
+
+	handles.processDataCompleted = 0;
+
+	%clears the axes
+	cla(handles.axes1,'reset');
+
+	%set the popupmenu to default value
+%	set(handles.plot_popupmenu,'Value',1);
+
+	%clears the contents of the listbox
+	set(handles.inputFile,'String','');
+	set(handles.inputFile,'Value',0);
+
+	%updates the handles structure
+	guidata(hObject, handles);
+end
+
+function plotdata_pushbutton_Callback(hObject, eventdata, handles)
+
+	%get the list of input file names from the listbox
+	inputFileName=get(handles.inputFile,'String');
+
+	%checks to see if the user selected any input files
+	%if not, nothing happens
+	if isempty(inputFileName)
+		errordlg('Select a file first!')
+		return
+	end
+
+	%disables the button while data is processing
+	disableButtons(handles);
+	refresh(data_processing_tool); 
+
+	%parse options
+	if ~isnan(handles.Msize)
+		M=handles.Msize;
+	else
+		errordlg('Number of lines (M) not valid')
+		return
+	end
+	if ~isnan(handles.Nsize)
+		N=handles.Nsize;
+	else
+		errordlg('Number of rows (N) not valid')
+		return
+	end
+	if ~isnan(handles.numvectors)
+		numvectors=handles.numvectors;
+		%change M
+		M=numvectors*M;
+	else
+		numvectors=1;
+	end
+	if ~isnan(handles.endian)
+		endian=handles.endian;
+	else
+		endian=1;
+	end
+	if ~isnan(handles.datatype)
+		datatype=handles.datatype;
+	else
+		datatype='float32';
+	end
+
+	%open file
+	if endian==1
+		fid=fopen(inputFileName,'r','ieee-be');
+	else
+		fid=fopen(inputFileName,'r','ieee-le');
+	end
+
+	%read file
+	[u, numpoints]=fread(fid, [M,N],datatype);
+
+	%close file
+	fclose(fid);
+
+	%Pair of vectors?
+	if numvectors==2,
+	   vx=u(1:2:M,:);vx=flipud(vx');
+	   vy=u(2:2:M,:);vx=flipud(vx');
+
+		%keep track
+		handles.vx=vx;
+		handles.vy=vy;
+
+		u=sqrt(vx.^2+vy.^2);
+	end
+
+	cla(handles.axes1); %clear the axes
+	axes(handles.axes1); %set the axes to plot
+	grid on
+	imagesc(u)
+	colorbar
+
+	%keep track
+	handles.u=u;
+
+	%to see whether the data has been processed or not
+	handles.processDataCompleted=2;
+
+	%data is done processing, so re-enable the buttons
+	enableButtons(handles);
+	guidata(hObject, handles);
+end
+
+function plotcoord_Callback(hObject, eventdata, handles)
+
+	%check
+	if handles.processDataCompleted<2
+		errordlg('Process data first !')
+		return
+	end
+
+	%parse options
+	if ~isnan(handles.dx)
+		dx=handles.dx;
+	else
+		errordlg('value of x-spacing not supported')
+		return
+	end
+	if ~isnan(handles.dy)
+		dy=handles.dy;
+	else
+		errordlg('value of y-spacing not supported')
+		return
+	end
+	if ~isnan(handles.xEast)
+		xEast=handles.xEast;
+	else
+		errordlg('value of xEast not supported')
+		return
+	end
+	if ~isnan(handles.yNorth)
+		yNorth=handles.yNorth;
+	else
+		errordlg('value of yNorth not supported')
+		return
+	end
+
+	disableButtons(handles);
+
+	%process coordinates
+	u=handles.u;
+	s=size(u);
+	M=s(1)+1;
+	N=s(2)+1;
+
+	%correction North and East -> real
+	yNorth=yNorth-M*dy; % corner north
+	x_m=xEast+dx*(0:N-1)';
+	y_m=yNorth+dy*(0:M-1)';
+
+	%plot new axes
+	cla(handles.axes1); %clear the axes
+	axes(handles.axes1); %set the axes to plot
+	grid on
+	imagesc(x_m,y_m,handles.u)
+	set(handles.axes1,'Ydir','Normal');
+	colorbar
+
+	%Keep track of x_m and y_m
+	handles.x_m=x_m;
+	handles.y_m=y_m;
+
+	%to see whether the data has been processed or not
+	handles.processDataCompleted=3;
+
+	%data is done processing, so re-enable the buttons
+	enableButtons(handles);
+	guidata(hObject, handles);
+
+end
+
+
+function save_pushbutton_Callback(hObject, eventdata, handles)
+	%if the data hasn't been processed yet, 
+	%nothing happens when this button is pressed
+	if (handles.processDataCompleted ~= 3)
+		return
+	end
+
+	disableButtons(handles);
+
+	if handles.numvectors==2,
+
+		prompt={'Enter the name of the variable 1:','Enter the name of the variable 2:','Enter the name of the file:'};
+		name='Save Matlab File';
+		numlines=1;
+		defaultanswer={'vx','vy','ProcessedFile'};
+		answer=inputdlg(prompt,name,numlines,defaultanswer);
+		variablename1=answer{1};
+		variablename2=answer{2};
+		filename=answer{3};
+
+		if ~isempty(variablename1) & ~isempty(variablename2) & ~isempty(filename)
+			%get the variables
+			x_m=handles.x_m;
+			y_m=handles.y_m;
+			eval([variablename1 ' = handles.vx;']);
+			eval([variablename2 ' = handles.vy;']);
+			x_m=handles.x_m;
+			eval(['save ' filename ' x_m y_m ' variablename1 ' ' variablename2 ]);
+			disp(['in the file ' filename ' have been saved the following variables: x_m, y_m, ' variablename1 ' and ' variablename2])
+		end
+	else
+		prompt={'Enter the name of the variable:','Enter the name of the file:'};
+		name='Save Matlab File';
+		numlines=1;
+		defaultanswer={'thickness','ProcessedFile'};
+		answer=inputdlg(prompt,name,numlines,defaultanswer);
+		variablename=answer{1};
+		filename=answer{2};
+
+		if ~isempty(variablename) & ~isempty(filename)
+			%get the variables
+			x_m=handles.x_m;
+			y_m=handles.y_m;
+			eval([variablename ' = handles.u;']);
+			eval(['save ' filename ' x_m y_m ' variablename]);
+			disp(['in the file ' filename ' have been saved the following variables: x_m, y_m, and ' variablename])
+		end
+	end
+	enableButtons(handles);
+	guidata(hObject, handles);
+end
+
+function inputFile_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function disableButtons(handles)
+	set(handles.figure1,'Pointer','watch');
+	set(handles.plotdata_pushbutton,'Enable','off');
+	set(handles.plotcoord,'Enable','off');
+	set(handles.save_pushbutton,'Enable','off');
+	set(handles.addFiles_pushbutton,'Enable','off');
+	set(handles.reset_pushbutton,'Enable','off');
+end
+
+function enableButtons(handles)
+	set(handles.figure1,'Pointer','arrow');
+	set(handles.plotdata_pushbutton,'Enable','on');
+	set(handles.plotcoord,'Enable','on');
+	set(handles.save_pushbutton,'Enable','on');
+	set(handles.addFiles_pushbutton,'Enable','on');
+	set(handles.reset_pushbutton,'Enable','on');
+end
+
+function EndianType_Callback(hObject, eventdata, handles)
+	handles.endian=get(handles.EndianType,'Value');
+	guidata(hObject, handles);
+end
+
+function EndianType_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function DataType_Callback(hObject, eventdata, handles)
+
+	datatype= get(handles.DataType,'Value');
+	switch datatype
+		case 1
+			string='float32';
+
+		case 2
+			string='single';
+
+		case 3
+			string='float64';
+
+		case 4
+			string='double';
+		end
+	handles.datatype=string;
+	guidata(hObject, handles);
+end
+
+function DataType_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function PairOfVectors_Callback(hObject, eventdata, handles)
+	handles.numvectors = get(handles.PairOfVectors,'Value');
+	guidata(hObject, handles);
+end
+
+function PairOfVectors_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function Msize_Callback(hObject, eventdata, handles)
+	handles.Msize=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+
+function Msize_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function Nsize_Callback(hObject, eventdata, handles)
+	handles.Nsize=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+
+function Nsize_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function dx_Callback(hObject, eventdata, handles)
+	handles.dx=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+function dx_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function dy_Callback(hObject, eventdata, handles)
+	handles.dy=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+function dy_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function xEast_Callback(hObject, eventdata, handles)
+	handles.xEast=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+function xEast_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
+
+function yNorth_Callback(hObject, eventdata, handles)
+	handles.yNorth=eval(get(hObject,'String'));
+	guidata(hObject, handles);
+end
+function yNorth_CreateFcn(hObject, eventdata, handles)
+	if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
+		set(hObject,'BackgroundColor','white');
+	end
+end
Index: /issm/trunk-jpl/src/m/DataProcessing/gamv.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/gamv.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/gamv.m	(revision 12996)
@@ -0,0 +1,70 @@
+function output = gamv(x,y,data,varargin);
+%GAMV - use gslib for Kriging
+%
+%   Usage:
+%      output = gamv(x,y,data,varargin)
+
+options=pairoptions(varargin{:});
+
+nlag = getfieldvalue(options,'nlag', 20);
+dlag = getfieldvalue(options,'dlag', 1000);
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+%Write parameter file
+fid=fopen('gamv.par','w');
+fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+fprintf(fid,'\t\t\t\t%s\n','*******************');
+fprintf(fid,'\n');
+fprintf(fid,'%s\n','START OF PARAMETERS:');
+fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\columns for X, Y, Z coordinates');
+fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+fprintf(fid,'%-30s %s\n','gamv.out'                   ,'\file for variogram output');
+fprintf(fid,'%-30s %s\n',num2str(nlag,'%i')           ,'\number of lags');
+fprintf(fid,'%-30s %s\n',num2str(dlag,'%g')           ,'\lag separation distance');
+fprintf(fid,'%-30s %s\n',num2str(dlag/2,'%g')         ,'\lag tolerance');
+fprintf(fid,'%-30s %s\n','3'                          ,'\number of directions');
+fprintf(fid,'%-30s %s\n','0.0 90.0 50.0 0.0 90.0 50.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','0.0 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','90. 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+fprintf(fid,'%-30s %s\n','2'                          ,'\number of variograms');
+fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail var., head vars., variogram type');
+fprintf(fid,'%-30s %s\n','1 1 3'                      ,'\tail var., head vars., variogram type');
+fclose(fid);
+
+%Call gamv
+system([issmdir() '/externalpackages/gslib/install/gamv gamv.par']);
+delete('gamv.par');
+
+%Read output
+output   = struct('Semivariogram',[],'Covariance',[]);
+counter1 = 1;
+counter2 = 1;
+fid=fopen('gamv.out','r');
+while (~feof(fid)),
+	A=fscanf(fid,'%s',1);
+	if strcmp(A,'Covariance');
+		A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction  2
+		output(counter1).Covariance=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])';
+		counter1=counter1+1;
+	elseif strcmp(A,'Semivariogram'),
+		A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction  2
+		output(counter2).Semivariogram=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])';
+		counter2=counter2+1;
+	else
+		%do nothing
+	end
+end
+fclose(fid);
+delete('gamv.out')
Index: /issm/trunk-jpl/src/m/DataProcessing/gslib.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/gslib.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/gslib.m	(revision 12996)
@@ -0,0 +1,112 @@
+function output = gslib(x,y,data,varargin);
+%GSLIB - use gslib for Kriging
+%
+%   Usage:
+%      output = gslib(x,y,data,varargin)
+
+%Output Matrix
+xmin   = xl(1);
+ymin   = yl(1);
+nx     = 101;
+ny     = 101;
+deltax = 5000;
+deltay = 5000;
+
+%Variogram
+nugget=10;
+sill  =164;
+range =25763;
+
+%Kriging options
+mindata = 1;
+maxdata = 50;
+maxsearchradius = 50000;
+
+%Some intermediaries (Convert to gslib's parameters);
+c = (sill-nugget);
+a = sqrt(3)*range;
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+if 0, %GAMV
+	%Write parameter file
+	fid=fopen('gamv.par','w');
+	fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+	fprintf(fid,'\t\t\t\t%s\n','*******************');
+	fprintf(fid,'\n');
+	fprintf(fid,'%s\n','START OF PARAMETERS:');
+	fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+	fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\columns for X, Y, Z coordinates');
+	fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+	fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+	fprintf(fid,'%-30s %s\n','gamv.out'                   ,'\file for variogram output');
+	fprintf(fid,'%-30s %s\n','20'                         ,'\number of lags');
+	fprintf(fid,'%-30s %s\n','5.0'                        ,'\lag separation distance');
+	fprintf(fid,'%-30s %s\n','3.0'                        ,'\lag tolerance');
+	fprintf(fid,'%-30s %s\n','3'                          ,'\number of directions');
+	fprintf(fid,'%-30s %s\n','0.0 90.0 50.0 0.0 90.0 50.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','0.0 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','90. 22.5 25.0 0.0 22.5 25.0','\azm, atol, bandh, dip, dtol, bandv');
+	fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+	fprintf(fid,'%-30s %s\n','2'                          ,'\number of variograms');
+	fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail var., head vars., variogram type');
+	fprintf(fid,'%-30s %s\n','1 1 3'                      ,'\tail var., head vars., variogram type');
+	fclose(fid);
+
+	%Call gamv
+	system([issmdir() '/externalpackages/gslib/install/gamv gamv.par']);
+
+else, %Kriging KB2D
+	%Write parameter file
+	fid=fopen('kb2d.par','w');
+	fprintf(fid,'\t\t\t\t%s\n','Parameters for KB2D');
+	fprintf(fid,'\t\t\t\t%s\n','*******************');
+	fprintf(fid,'\n');
+	fprintf(fid,'%s\n','START OF PARAMETERS:');
+	fprintf(fid,'%-30s %s\n','./cluster.dat'                  ,'\file with data');
+	fprintf(fid,'%-30s %s\n','1 2 3'                          ,'\columns for X, Y and variable');
+	fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'                 ,'\trimming limits');
+	fprintf(fid,'%-30s %s\n','0'                              ,'\debugging level: 0,1,2,3');
+	fprintf(fid,'%-30s %s\n','kb2d.dbg'                       ,'\file for debuggging output');
+	fprintf(fid,'%-30s %s\n','kb2d.out'                       ,'\file for kriged output');
+	fprintf(fid,'%-30s %s\n',num2str([nx xmin deltax],'%i %10g %6g')  ,'\nx, xmn, xsiz');
+	fprintf(fid,'%-30s %s\n',num2str([ny ymin deltay],'%i %10g %6g')  ,'\nx, xmn, xsiz');
+	fprintf(fid,'%-30s %s\n','1 1'                            ,'\x and y block discretization');
+	fprintf(fid,'%-30s %s\n',num2str([mindata maxdata],'%6g') ,'\min and max data for kriging');
+	fprintf(fid,'%-30s %s\n',num2str(maxsearchradius,'%6g')   ,'\max search radius');
+	fprintf(fid,'%-30s %s\n','1 2.302'                        ,'\0=SK, 1=OK, (mean if SK)');
+	fprintf(fid,'%-30s %s\n',['1 ' num2str(nugget)]           ,'\nst, nugget effect');
+	fprintf(fid,'%-30s %s\n',['3 ' num2str([c 0.0 a a],'%10g')],'\it, c, azm, a_max, a_min');
+	fclose(fid);
+
+	tic;system([issmdir() '/externalpackages/gslib/install/kb2d kb2d.par']);toc;
+	delete('kb2d.par');
+
+	%Read output
+	fid=fopen('kb2d.out','r');
+	while (~feof(fid)),
+		A=fscanf(fid,'%s',1);
+		if strcmp(A,'KB2D');
+			A=fscanf(fid,'%s',1); %Read output
+			params=fscanf(fid,'%i %i %i %i %g %g %g %g %g %g %1',[11 1]);
+		elseif strcmp(A,' Estimate'),
+			continue;
+		elseif strcmp(A,'Estimation'),
+			A=fscanf(fid,'%s',1); %Read Variance
+			A=fscanf(fid,'%g %g',[params(1) params(2)*params(3)]);
+			B=A(1,:); B=reshape(B,[params(3),params(2)])';
+			E=A(2,:); E=reshape(E,[params(3),params(2)])';
+		else
+			%do nothing
+		end
+	end
+	fclose(fid);
+end
Index: /issm/trunk-jpl/src/m/DataProcessing/pkriging.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/pkriging.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/pkriging.m	(revision 12996)
@@ -0,0 +1,55 @@
+function [B E]=pkriging(x,y,observations,x_interp,y_interp,varargin);
+%PKRIGING - parallel Kriging
+%
+%   Usage:
+%      [B E]=pkriging(x,y,observations,x_interp,y_interp,varargin);
+
+options=pairoptions(varargin{:});
+cluster=getfieldvalue(options,'cluster',generic('np',10));
+options=removefield(options,'cluster',0);
+name   = ['krig' num2str(feature('GetPid'))];
+
+% =========================================   MARSHALL.m =================================================
+disp(['marshalling file ' name '.bin']);
+fid=fopen([name '.bin'],'wb');
+if fid==-1,
+	error(['marshall error message: could not open ' name '.bin file for binary writing']);
+end
+
+%First, write MaximumNumberOfEnum to make sure that the Enums are synchronized
+WriteData(fid,'enum',MaximumNumberOfEnums(),'data',true,'format','Boolean');
+
+%Write all data
+WriteData(fid,'enum',0,'data',x,'format','DoubleMat');
+WriteData(fid,'enum',1,'data',y,'format','DoubleMat');
+WriteData(fid,'enum',2,'data',observations,'format','DoubleMat');
+WriteData(fid,'enum',3,'data',x_interp,'format','DoubleMat');
+WriteData(fid,'enum',4,'data',y_interp,'format','DoubleMat');
+options.marshall(fid,5);
+st=fclose(fid);
+if st==-1,
+	error(['marshall error message: could not close file ' name '.bin']);
+end
+% =========================================   MARSHALL.m =================================================
+
+%Launch job on remote cluster
+BuildKrigingQueueScript(cluster,name,'',1,0,0); %gather, valgrind, gprof
+tic
+LaunchQueueJob(cluster,name,name,{[name '.bin'] [name '.queue']});
+toc
+choice=input('Is the job successfully completed? (y/n)','s');
+Download(cluster,name,{[name '.outbin']});
+structure=parseresultsfromdisk([name '.outbin'],0);
+delete([name '.outlog']);
+delete([name '.errlog']);
+delete([name '.outbin']);
+delete([name '.bin']);
+if ~ispc,
+	delete([name '.tar.gz']);
+end
+
+%Process results
+B=structure.AutodiffForward;
+B=reshape(B,size(x_interp,2),size(x_interp,1))';
+E=structure.AutodiffIsautodiff;
+E=reshape(E,size(x_interp,2),size(x_interp,1))';
Index: /issm/trunk-jpl/src/m/DataProcessing/varmap.m
===================================================================
--- /issm/trunk-jpl/src/m/DataProcessing/varmap.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/DataProcessing/varmap.m	(revision 12996)
@@ -0,0 +1,55 @@
+function output = varmap(x,y,data,varargin);
+%VARMAP - use gslib for Kriging
+%
+%   Usage:
+%      output = varmap(x,y,data,varargin)
+
+options=pairoptions(varargin{:});
+
+nxlag = getfieldvalue(options,'nxlag', 20);
+nylag = getfieldvalue(options,'nylag', 20);
+dxlag = getfieldvalue(options,'dxlag', 1000);
+dylag = getfieldvalue(options,'dylag', 1000);
+
+%Write data file
+fid=fopen('cluster.dat','w');
+fprintf(fid,'%s\n','Data file');
+fprintf(fid,'%i\n',3);
+fprintf(fid,'%s\n','Xlocation');
+fprintf(fid,'%s\n','Ylocation');
+fprintf(fid,'%s\n','Data');
+fprintf(fid,'%g %g %g\n',[x y data]');
+fclose(fid);
+
+%Write parameter file
+fid=fopen('varmap.par','w');
+fprintf(fid,'\t\t\t\t%s\n','Parameters for GAMV');
+fprintf(fid,'\t\t\t\t%s\n','*******************');
+fprintf(fid,'\n');
+fprintf(fid,'%s\n','START OF PARAMETERS:');
+fprintf(fid,'%-30s %s\n','./cluster.dat'              ,'\file with data');
+fprintf(fid,'%-30s %s\n','1 3  '                      ,'\number of variables, column number');
+fprintf(fid,'%-30s %s\n','-1.0e21 1.0e21'             ,'\trimming limits');
+fprintf(fid,'%-30s %s\n','0    '                      ,'\1=regular grid, 0=scattered values');
+fprintf(fid,'%-30s %s\n','50 50 1'                    ,'\if =1: nx, ny, nz');
+fprintf(fid,'%-30s %s\n','1.0 1.0 1.0'                ,'\       xsiz, ysiz, zsiz if igrid=1');
+fprintf(fid,'%-30s %s\n','1 2 0'                      ,'\if =0: columns for x, y and z coordinates');
+fprintf(fid,'%-30s %s\n','varmap.out'                 ,'\file for variogram output');
+fprintf(fid,'%-30s %s\n',num2str([nxlag nylag 0],'%i '),'\nxlag, nylag, nzlag');
+fprintf(fid,'%-30s %s\n',num2str([dxlag dylag 1],'%g %g %i'),'\dxlag, dylag, dzlag');
+fprintf(fid,'%-30s %s\n','5'                          ,'\minimum number of pairs');
+fprintf(fid,'%-30s %s\n','0'                          ,'\standardize sill? (0=no, 1=yes)');
+fprintf(fid,'%-30s %s\n','1'                          ,'\number of variograms');
+fprintf(fid,'%-30s %s\n','1 1 1'                      ,'\tail, head, variogram type');
+fclose(fid);
+
+%Call varmap
+system([issmdir() '/externalpackages/gslib/install/varmap varmap.par']);
+delete('varmap.par');
+
+%Read output
+fid=fopen('varmap.out','r');
+A = textscan(fid,'%f %f %f %f %f %f','headerlines',8);
+fclose(fid);
+delete('varmap.out')
+output = reshape(A{1},[2*nxlag+1 2*nylag+1]);
Index: /issm/trunk-jpl/src/m/Ecco3/ecco32issm.m
===================================================================
--- /issm/trunk-jpl/src/m/Ecco3/ecco32issm.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Ecco3/ecco32issm.m	(revision 12996)
@@ -0,0 +1,8 @@
+function nodefield=ecco32issm(field,transition,xecco3,yecco3)
+
+	xecco3linear=xecco3(:); yecco3linear=yecco3(:); %linearize
+	nodefieldlinear=zeros(length(xecco3linear),1);
+	nodefieldlinear(transition(:,1))=field(transition(:,2));
+	nodefield=xecco3;
+	nodefield(:)=nodefieldlinear;
+	%nodefield=nodefield'; %not sure we need that
Index: /issm/trunk-jpl/src/m/Ecco3/issm2ecco3.m
===================================================================
--- /issm/trunk-jpl/src/m/Ecco3/issm2ecco3.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Ecco3/issm2ecco3.m	(revision 12996)
@@ -0,0 +1,8 @@
+function nodefield=issm2ecco3(field,transition,xecco3,yecco3)
+
+	xecco3linear=xecco3(:); yecco3linear=yecco3(:); %linearize
+	nodefieldlinear=zeros(length(xecco3linear),1);
+	nodefieldlinear(transition(:,1))=field(transition(:,2));
+	nodefield=xecco3;
+	nodefield(:)=nodefieldlinear;
+	%nodefield=nodefield'; %not sure we need that
Index: /issm/trunk-jpl/src/m/Exp/clicktoflowline.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/clicktoflowline.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/clicktoflowline.m	(revision 12996)
@@ -0,0 +1,24 @@
+function clicktoflowline(index,x,y,u,v,filename)
+%CLICKTOFLOWLINE - create a flowline ARGUS file
+%
+%   create a flowline contour file (named 'filename') by clicking
+%   on a velocity field once (velocity must be plotted first)
+%
+%   Usage: 
+%      clicktoflowline(index,x,y,u,v,x0,y0,filename)
+%
+%   Example: 
+%      clicktoflowline(md.mesh.elements,md.mesh.x,md.mesh.y,md.inversion.vx_obs,md.inversion.vy_obs,'flowline.exp')
+
+%Get click position
+[x0,y0]=ginput(1);
+
+%Get flowline
+line=flowlines(index,x,y,u,v,x0,y0,200);
+
+%plot
+hold on
+plot(line.x,line.y,'r-');
+
+%Write argus file
+expwrite(line,filename);
Index: /issm/trunk-jpl/src/m/Exp/downstreamflowlines.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/downstreamflowlines.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/downstreamflowlines.m	(revision 12996)
@@ -0,0 +1,110 @@
+function flowpath=downstreamflowlines(index,x,y,u,v,x0,y0,varargin)
+%DOWNSTREAMFLOWLINES - compute flowlines from a given set of seed points
+%
+%   Usage:
+%      flowpath=downstreamflowlines(index,x,y,u,v,x0,y0)
+%
+%   the velocity field is given by the couple (u,v) and the coordinates
+%   of the seed points are (x0,y0). One can use one or several seed 
+%   points
+%
+%   Example:
+%      flowpath=downstreamflowlines(md.mesh.elements,md.mesh.x,md.mesh.y,md.vx,md.initialization.vy,x0,y0)
+
+%check input size
+if nargin>9 | nargin<7,
+	help flowlines
+	error('flowlines error message: bad usage');
+end
+
+%check input
+if (length(x)~=length(y) | length(x)~=length(u) | length(x)~=length(v)),
+	error('flowlines error message: x,y,u and v must have the same length');
+end
+if length(x)<3,
+	error('flowlines error message: at least one element is required');
+end
+if length(x0)~=length(y0),
+	error('flowlines error message: x0 and y0 do not have the same length');
+end
+
+%get maxiter and precision
+if nargin==9
+	maxiter=varargin{1};%maximum number of iterations
+	precision=varargin{2}; %division of each segment (higer precision increases number of segments)
+else
+	maxiter=200; %maximum number of iterations
+	precision=1; %division of each segment (higer precision increases number of segments)
+end
+
+%check seed points
+tria=TriaSearch(index,x,y,x0,y0);
+pos=find(isnan(tria));
+x0(pos)=[];
+y0(pos)=[];
+
+%initialize other variables
+N=length(x0);
+X=x0; Y=y0;
+flowpath=struct('x',cell(N,1),'y',cell(N,1),'name','','density',1);
+for i=1:N,
+	flowpath(i).x=x0(i);
+	flowpath(i).y=y0(i);
+end
+done=zeros(N,1);
+
+%get avegared length of each element
+length_tria=1/3*(sqrt( (x(index(:,1))-x(index(:,2))).^2+(y(index(:,1))-y(index(:,2))).^2 )+...
+	sqrt((x(index(:,1))-x(index(:,3))).^2+(y(index(:,1))-y(index(:,3))).^2 )+...
+	sqrt((x(index(:,2))-x(index(:,3))).^2+(y(index(:,2))-y(index(:,3))).^2 ));
+
+%take velocity for each element
+u=u(index)*[1;1;1]/3;
+v=v(index)*[1;1;1]/3;
+
+%initialization:
+counter=1;
+
+while any(~done) 
+
+	%find current triangle
+	queue=find(~done);
+	tria=TriaSearch(index,x,y,X(queue),Y(queue));
+
+	%check that the point is actually inside a triangle of the mesh
+	listnan=find(isnan(tria));
+	for i=1:length(listnan)
+		%remove the last point
+		flowpath(queue(listnan(i))).x(end)=[];
+		flowpath(queue(listnan(i))).y(end)=[];
+		done(queue(listnan(i)))=1;
+	end
+	tria(listnan)=[]; 
+	queue(listnan)=[];
+
+	if isempty(tria),
+		break;
+	end
+
+	%velocity of the current triangle and norm it
+	ut=u(tria); vt=v(tria); normv=sqrt(ut.^2+vt.^2);
+	ut=ut./normv;vt=vt./normv;
+
+	%check counter
+	if counter>maxiter
+		disp(['Maximum number of iterations (' num2str(maxiter) ') reached while going forward'])
+		break
+	end
+	counter=counter+1;
+
+	%remove stagnant point
+	done(queue(find(ut==0 & vt==0)))=1;
+
+	%build next point
+	for i=1:length(queue)
+		X(queue(i))=flowpath(queue(i)).x(end)+ut(i)*length_tria(tria(i))/precision;
+		Y(queue(i))=flowpath(queue(i)).y(end)+vt(i)*length_tria(tria(i))/precision;
+		flowpath(queue(i)).x=[flowpath(queue(i)).x;flowpath(queue(i)).x(end)+ut(i)*length_tria(tria(i))/precision];
+		flowpath(queue(i)).y=[flowpath(queue(i)).y;flowpath(queue(i)).y(end)+vt(i)*length_tria(tria(i))/precision];
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/expbox.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expbox.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expbox.m	(revision 12996)
@@ -0,0 +1,41 @@
+function expbox(filename)
+%EXPBOX - Create a ARGUS file using to clicks
+%
+%   Two clicks on a plot are used to generate a rectangular box
+%   This box is written in EXP format on filename
+%
+%   Usage:
+%      expbox(filename)
+
+%check
+if exist(filename,'file'),
+	choice=input(['A file ' filename ' already exists, do you want to modify it? (y/n)'],'s');
+	if ~strcmpi(choice,'y'),
+		disp('no modification done ... exiting');
+		return
+	end
+end
+
+%Get points
+disp('Click twice to define a rectangular domain. First click for upper left corner, second for lower right corner');
+[x,y]=ginput(2);
+
+x1=x(1);
+x2=x(2);
+x3=x2;
+x4=x1;
+
+y1=y(1);
+y2=y1;
+y3=y(2);
+y4=y3;
+
+%Build Exp structure
+A=struct();
+A.nods=5;
+A.density=1;
+A.x=[x1 x2 x3 x4 x1]';
+A.y=[y1 y2 y3 y4 y1]';
+
+%Write structure
+expwrite(A,filename);
Index: /issm/trunk-jpl/src/m/Exp/expboxgen.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expboxgen.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expboxgen.m	(revision 12996)
@@ -0,0 +1,99 @@
+function expboxgen(x0,y0,nx,ny,parameter_filename,box_filename)
+%EXPBOXGEN -  creates a domain outline box for a tiff image
+%
+%   This function creates a domain outline box for a .tif image for the 
+%   mosaic tiff. 
+%   x0,y0 and x1,y1 are the cropping coordinates (upper left and lower right 
+%   corners in the larger tiff image).
+%   paramter_filename is the parameter file name for the mosaic tiff image.
+%   box_filename is self explanatory.
+%
+%   Usage:
+%      expboxgen(x0,y0,nx,ny,parameter_filename,box_filename)
+%
+%   See also EXPMASTER, EXPDOC
+
+%initialize
+nrows=-1;
+ncols=-1;
+X0=-1;
+Y0=-1;
+posting=-1;
+
+%first recover necessary information from the paramter_filename.
+fid=fopen(parameter_filename,'r');
+count=1;
+while(1),
+tline=fgetl(fid);
+if ~isstr(tline), break; end;
+
+ind=findstr('ant125m',tline);
+if ~isempty(ind),
+a=strsplit(tline,' ');
+a=a(2); a=char(a); a=a(1:length(a)-1);
+posting=str2num(a);
+end
+
+
+ind=findstr('no. of rows   :',tline);
+if ~isempty(ind),
+a=strsplit(tline,' ');
+nrows=str2num(char(a(length(a))));
+end
+
+ind=findstr('no. of columns:',tline);
+if ~isempty(ind),
+a=strsplit(tline,' ');
+ncols=str2num(char(a(length(a))));
+end
+
+ind=findstr('Upper Left X:',tline);
+if ~isempty(ind),
+a=strsplit(tline,' ');
+X0=str2num(char(a(length(a))));
+end
+
+ind=findstr('Upper Left Y:',tline);
+if ~isempty(ind),
+a=strsplit(tline,' ');
+Y0=str2num(char(a(length(a))));
+end
+
+
+end %while(1),
+
+
+fclose(fid);
+
+if (X0==-1 | Y0==-1 | nrows==-1  | ncols==-1 | posting==-1),
+disp(' ');
+disp(['Could not recover all parameters from ' parameter_filename]);
+disp('Here are the paramters recovered thus far: ');
+disp(['no. of rows: ' num2str(nrows)]);
+disp(['no. of columns: ' num2str(ncols)]);
+disp(['Upper Left X: ' num2str(X0)]);
+disp(['Upper Left Y: ' num2str(Y0)]);
+disp(['Posting: ' num2str(posting)]);
+end
+
+disp(' ');
+disp(['Recovered the following parameters from ' parameter_filename]);
+disp(['no. of rows: ' num2str(nrows)]);
+disp(['no. of columns: ' num2str(ncols)]);
+disp(['Upper Left X: ' num2str(X0)]);
+disp(['Upper Left Y: ' num2str(Y0)]);
+disp(['Posting: ' num2str(posting)]);
+
+%Create X,Y, arrays of coordinates:
+X(1)=X0+x0*posting
+Y(1)=Y0-y0*posting
+X(2)=X(1);
+Y(2)=Y(1)-ny*posting;
+X(3)=X(1)+nx*posting;
+Y(3)=Y(2);
+Y(4)=Y(1);
+X(4)=X(3);
+plot(X,Y,'r*');
+
+%Create box exp file using X and Y. Loop it.
+expgen(box_filename,X,Y,1);
Index: /issm/trunk-jpl/src/m/Exp/expcoarsen.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expcoarsen.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expcoarsen.m	(revision 12996)
@@ -0,0 +1,74 @@
+function expcoarsen(newfile,oldfile,resolution);
+%EXPCOARSEN - coarsen an exp contour
+%
+%   This routine read an Argus file and remove points with respect to
+%   the resolution (in meters) given in input. 
+%
+%   Usage:
+%      expcoarsen(newfile,oldfile,resolution)
+%
+%   Example:
+%       expcoarsen('DomainOutline.exp','Antarctica.exp',4000)
+
+%Some checks
+if nargin~=3 | nargout
+	error('expcoarsen usage: expcoarsen(newfile,oldfile,resolution)')
+elseif ~exist(oldfile)
+	error(['expcut error message: the file ' oldfile  'does not exist'])
+elseif exist(newfile),
+	choice=input(['A file ' newfile ' already exists, do you want to modify it? (y/n)'],'s');
+	if ~strcmpi(choice,'y'),
+		disp('no modification done ... exiting');
+		return;
+	end
+end
+
+%Get exp oldfile
+[path root ext ver]=fileparts(oldfile);
+A=expread(oldfile);
+numprofiles=size(A,2);
+
+%Go through the profiles
+count=1;
+while count<=numprofiles,
+
+	%get number of points and initialize j
+	numpoints=length(A(count).x);
+	j=1;
+
+	%stop if we have reached end of profile (always keep the last point)
+	while j<numpoints,
+
+		%See whether we keep this point or not
+		distance=sqrt((A(count).x(j)-A(count).x(j+1))^2+(A(count).y(j)-A(count).y(j+1))^2);
+		if distance<resolution & j<numpoints-1  %do not remove last point
+			A(count).x(j+1)=[];
+			A(count).y(j+1)=[];
+			numpoints=numpoints-1;
+		else
+			division=floor(distance/resolution)+1;
+			if division>=2,
+				x=linspace(A(count).x(j),A(count).x(j+1),division)';
+				y=linspace(A(count).y(j),A(count).y(j+1),division)';
+				A(count).x=[A(count).x(1:j);x(2:end-1); A(count).x(j+1:end)];
+				A(count).y=[A(count).y(1:j);y(2:end-1); A(count).y(j+1:end)];
+
+				%update current point
+				j=j+1+division-2;
+				numpoints=numpoints+division-2;
+			else
+				%update current point
+				j=j+1;
+			end
+		end
+	end
+	if length(A(count).x)<=1,
+		A(count)=[];
+		numprofiles=numprofiles-1;
+	else
+		count=count+1;
+	end
+end
+
+%write output
+expwrite(A,newfile);
Index: /issm/trunk-jpl/src/m/Exp/expcontract.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expcontract.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expcontract.m	(revision 12996)
@@ -0,0 +1,34 @@
+function normal_node=expcontract(newfile,oldfile,distance)
+%EXPCONTRACT - contract or expand a profile, according to the normal.
+% 
+%   Usage:
+%      expcontract(newfile,oldfile,distance)
+%
+%   See also EXPMASTER, EXPDOC
+
+
+contour=expread(oldfile);
+num=numel(contour.x);
+
+normal=zeros(num-1,2);
+normal_node=zeros(num-1,2);
+
+for i=1:num-1,
+	normal(i,:)=[ contour.y(i)-contour.y(i+1) contour.x(i+1)-contour.x(i)];
+	normal(i,:)=normal(i,:)/sqrt(normal(i,1)^2+normal(i,2)^2);
+end
+
+normal_node(2:end,:)=[normal(1:end-1,:)+normal(2:end,:)];
+normal_node(1,:)=normal(1,:)+normal(end,:);
+
+normal_node_norm=sqrt(normal_node(:,1).^2+normal_node(:,2).^2);
+normal_node(:,1)=normal_node(:,1)./normal_node_norm;
+normal_node(:,2)=normal_node(:,2)./normal_node_norm;
+
+contour.x(1:end-1)=contour.x(1:end-1)+distance*normal_node(:,1);
+contour.y(1:end-1)=contour.y(1:end-1)+distance*normal_node(:,2);
+
+contour.x(end)=contour.x(1);
+contour.y(end)=contour.y(1);
+
+expwrite(contour,newfile);
Index: /issm/trunk-jpl/src/m/Exp/expcreatecircle.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expcreatecircle.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expcreatecircle.m	(revision 12996)
@@ -0,0 +1,31 @@
+function expcreatecircle(filename,x0,y0,radius,numberofnodes)
+%EXPCREATECIRCLE - create a circular contour corresponding to given parameters
+%
+%   Creates a closed argus contour centered on x,y of radius size.
+%   The contour is made of numberofnodes
+%
+%   Usage:
+%      expcreatecircle(filename,x0,y0,radius,numberofnodes)
+%
+%   See also EXPMASTER, EXPDOC
+
+%Calculate the cartesians coordinates of the points
+x_list=ones(numberofnodes+1,1);
+y_list=ones(numberofnodes+1,1);
+
+theta=(0:2*pi/numberofnodes:2*pi*(1-1/numberofnodes))';
+theta=[theta;0];
+
+x_list=radius*x_list.*cos(theta);
+y_list=radius*y_list.*sin(theta);
+
+%offset x_list and y_list by x0 and y0:
+x_list=x_list+x0;
+y_list=y_list+y0;
+
+contour.x=x_list;
+contour.y=y_list;
+contour.density=1;
+contour.name='circle';
+
+expwrite(contour,filename);
Index: /issm/trunk-jpl/src/m/Exp/expcreatecontour.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expcreatecontour.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expcreatecontour.m	(revision 12996)
@@ -0,0 +1,36 @@
+function expcreatecontour(filename);
+%EXPCREATECONTOUR - create a contour from a list of points
+%
+%   expcreatecontour: from a list of (x,y) points (retrieve using ginput on an undetermined
+%   number of points: used RETURN key to end input), create an Argus .exp 
+%   file holding the corresponding closed contour.
+%    
+%   Usage:
+%      expcreatecontour(filename)
+%
+%   See also EXPMASTER, EXPDOC
+
+%Get root of filename
+[path root ext ver]=fileparts(filename);
+
+%Get contour
+disp('Click on contour points you desire. Type RETURN to end input of points');
+[x,y]=ginputquick;
+
+%close contour
+x=[x;x(1)];
+y=[y;y(1);];
+
+%plot contour
+hold on;
+plot(x,y,'r-');
+
+%create structure for expwrite routine
+a.x=x;
+a.y=y;
+a.name=root;
+a.density=1;
+
+%write contour using expwrite
+expwrite(a,filename);
+
Index: /issm/trunk-jpl/src/m/Exp/expcreateprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expcreateprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expcreateprofile.m	(revision 12996)
@@ -0,0 +1,31 @@
+function expcreateprofile(filename);
+%EXPCREATEPROFILE - create an Argus file from a list of points
+%
+%   expcreateprofile: from a list of (x,y) points (retrieve using ginput on an undetermined
+%   number of points: used RETURN key to end input), create an Argus .exp 
+%   file holding the corresponding open profile.
+%    
+%   Usage:
+%      expcreateprofile(filename)
+%
+%   See also EXPMASTER, EXPDOC
+
+%Get root of filename
+[path root ext ver]=fileparts(filename);
+
+%Get profile
+disp('Click on profile points you desire. Type RETURN to end input of points');
+[x,y]=ginputquick;
+
+%plot contour
+hold on;
+plot(x,y,'r-');
+
+%create structure for expwrite routine
+a.x=x;
+a.y=y;
+a.name=root;
+a.density=1;
+
+%write profile using expwrite
+expwrite(a,filename);
Index: /issm/trunk-jpl/src/m/Exp/expdisp.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expdisp.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expdisp.m	(revision 12996)
@@ -0,0 +1,52 @@
+function expdisp(domainoutline,varargin)
+%EXPDISP - plot the contours of a domain outline file
+%
+%   This routine reads in a domain outline file (Argus format) and plots all the contours 
+%
+%   Usage:
+%      expdisp(domainoutline,varargin)
+%      expdisp(domainoutline,figurenumber,linestyle,linewidth,unitmultiplier)
+%
+%   Example:
+%      expdisp('Domain.exp',1,'--r',2,10^3);
+%
+%   See also EXPMASTER, EXPDOC
+
+%check nargin
+if ~nargin | nargin>5
+	help expdisp
+	error('expdisp error message: bad usage');
+end
+
+%parse input
+if nargin<=1,
+	figurenumber=1;
+else
+	figurenumber=varargin{1};
+end
+if nargin<=2
+	linestyle='r-';
+else
+	linestyle=varargin{2};
+end
+if nargin<=3
+	linewidth=1;
+else
+	linewidth=varargin{3};
+end
+if nargin<=4
+	unitmultiplier=1;
+else
+	unitmultiplier=varargin{4}; if isnan(unitmultiplier), unitmultiplier=1; end
+end
+
+domain=expread(domainoutline);
+
+figure(figurenumber),hold on
+for i=1:length(domain),
+	if (isnumeric(linestyle))
+		plot(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,'Color',linestyle,'linewidth',linewidth);
+	else
+		plot(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,linestyle,'linewidth',linewidth);
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/expdoc.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expdoc.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expdoc.m	(revision 12996)
@@ -0,0 +1,36 @@
+function expdoc()
+%EXPDOC - create a doc for EXP routines
+%
+%   Usage:
+%      expdoc()
+
+disp(' ');
+disp('   Utilities dedicated to ARGUS Files (''.exp'' extension)'); 
+disp('     expboxgen: creates a domain outline box for a .tif image for the mosaic tiff');
+disp('            usage: expboxgen(x0,y0,nx,ny,parameter_filename,box_filename)');
+disp('            x0,y0 and nx,ny are the cropping coordinates (upper left and lower right corners in the larger tiff image)');
+disp('            paramter_filename is the parameter file name for the mosaic tiff image. box_filename is self explanatory.');
+disp('     expconcatenate: display all the profiles present in an Argus file and merge them accordingly to the tips selected by the user')
+disp('            usage:  expconcatenate(newfile,oldfile)')
+disp('     expcreatecircle: creates a closed Argus contour centered on (x,y), of radius radius_length. The contour is made of N points');
+disp('            usage: expcreatecircle(filename,x0,y0,radius_length,N)');
+disp('     expcreatecontour: creates a closed Argus contour delimited by the ''clicks'' of the user');
+disp('            usage: expcreatecontour(filename)');
+disp('     expcreateprofile: creates an Argus profile delimited by the ''clicks'' of the user');
+disp('            usage: expcreateprofile(filename)');
+disp('     expcut: display the contents of an Argus file and allow the user cut the profiles');
+disp('            usage: expcut(newfilename,oldfilename)');
+disp('     expdisp: display the contents of an Argus file');
+disp('            usage:  expdisp(filename,[figure number],[line style])');
+disp('     expgen: creates an Argus file from a contour (x,y) and a flag indicating if the contour must be closed or open');
+disp('            usage:  expgen(filename,contours,close_flag)');
+disp('     explink: takes a domain outline made of various segments, and links them together in one domain outline. Use expview to see end result');
+disp('            usage: explink(domainoutline,minthreshold,step)');
+disp('     exptool: allows the user to create, close, merge, remove,... Argus files and save the result in newfile');
+disp('            usage: exptool(newfile,[oldfile1],[oldfile2],[oldfile3],[...]');
+disp('     expread: reads an Argus file and build a structure that holds all the information of the file');
+disp('            usage: expread(file,close_flag)');
+disp('     expselect: display all the profiles of oldfile, the user clicks on the contour he/she wants to remove. Results saved in newfile');
+disp('            usage: expselect(newfile,oldfile)');
+disp('     expwrite: writes an Argus file from a structure given in input???');
+disp('            usage: expwrite(structure,filename)');
Index: /issm/trunk-jpl/src/m/Exp/expexcludeoutliers.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expexcludeoutliers.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expexcludeoutliers.m	(revision 12996)
@@ -0,0 +1,18 @@
+function excludeoutliers(newcontourname,contourname,domainname)
+%EXCLUDEOUTLIERS exclude points of contour that are not within the domain  contour. return new contours in a different file.
+%
+%        Usage: excludeoutliers('NewContour.exp','Contour.exp','DomainOutline.exp');
+%
+%
+%   See also EXPMASTER, EXPDOC
+
+
+contour=expread(contourname);
+
+for i=1:length(contour),
+	flags=ContourToNodes(contour(i).x,contour(i).y,domainname,0);
+	contour(i).x=contour(i).x(find(flags));
+	contour(i).y=contour(i).y(find(flags));
+end
+
+expwrite(contour,newcontourname);
Index: /issm/trunk-jpl/src/m/Exp/expflip.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expflip.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expflip.m	(revision 12996)
@@ -0,0 +1,19 @@
+function expflip(domainname)
+%EXPFLIP: flip orientation of all contours and domains in domainname exp file.
+%
+%Usage: expflip('MassFlux1.exp');a
+%
+%
+
+
+
+
+
+a=expread(domainname,1);
+
+for i=1:length(a),
+	a(i).x=flipud(a(i).x);
+	a(i).y=flipud(a(i).y);
+end
+
+expwrite(a,domainname);
Index: /issm/trunk-jpl/src/m/Exp/expgen.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expgen.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expgen.m	(revision 12996)
@@ -0,0 +1,47 @@
+function expgen(file_name,contours,close_flag);
+%EXPGEN - create an Argus file from x and y arrays
+%
+%   Create .exp domain outline type out of x,y  coordinates. 
+%   The contour defined by arrays x and y should not be closed. 
+%   Generated domain outline will not be closed, except if close_flag is set to 1.
+%
+%   Usage:
+%      expgen(file_name,contours,close_flag)
+%
+%   See also EXPMASTER, EXPDOC
+
+%Check on inputs
+if((close_flag~=0) & (close_flag~=1)),
+error('close flag must be 0 of 1');
+end
+fid=fopen(file_name,'wt');
+
+for i=1:length(contours),
+	if(length(contours(i).x)~=length(contours(i).y)),
+	error('contours x and y coordinates must be of identical size');
+	end
+
+	%get density for this profile.
+	if isfield(contours,'density'),
+		density=contours(i).density;
+	end
+
+	fprintf(fid,'%s\n','## Name:');
+	fprintf(fid,'%s\n','## Icon:0');
+	fprintf(fid,'%s\n','# Points Count Value');
+	if(close_flag==0),
+	fprintf(fid,'%i %i\n',length(contours(i).x),density);
+	else
+	fprintf(fid,'%i %i\n',length(contours(i).x)+1,density);
+	end
+	fprintf(fid,'%s\n','# X pos Y pos');
+	for j=1:length(contours(i).x),
+	 fprintf(fid,'%f %f\n',contours(i).x(j),contours(i).y(j));
+	end  
+
+	if(close_flag==1),
+	fprintf(fid,'%f %f\n',contours(i).x(1),contours(i).y(1));
+	end
+	fprintf(fid,'%s\n','');
+end
+fclose(fid);
Index: /issm/trunk-jpl/src/m/Exp/explink.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/explink.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/explink.m	(revision 12996)
@@ -0,0 +1,29 @@
+function explink(domainoutline,minthreshold,step)
+%EXPLINK - allow to link several segments of domain outline together
+%
+%   Takes a domain outline made of various segments, and links them together in one 
+%   domain outline. Use expview to see end result.
+%
+%   Usage:
+%      explink(domainoutline,minthreshold,step)
+%
+%   See also EXPMASTER, EXPDOC
+
+notdone=1;
+
+while notdone,
+
+	for i=1:1000,
+		status=expconcatenate(domainoutline,minthreshold+(i-1)*step);
+		if status==0,
+			return;
+		end
+		if status==1,
+			break;
+		end
+		if status==-1,
+			continue;
+		end
+	end
+end
+
Index: /issm/trunk-jpl/src/m/Exp/expll2xy.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expll2xy.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expll2xy.m	(revision 12996)
@@ -0,0 +1,37 @@
+function expll2xy(filename,sgn,central_meridian,standard_parallel)  
+%EXPLL2XY: switch exp argus file from lat,long to x,y
+%   Usage:
+%      expll2xy(filename,sgn,central_meridian,standard_parallel)
+%      - sgn = Sign of latitude +1 : north latitude (default is mer=45 lat=70)
+%                               -1 : south latitude (default is mer=0  lat=71)
+
+
+%Get central_meridian and standard_parallel depending on hemisphere
+if nargin==4,
+	delta = central_meridian;
+	slat  = standard_parallel;
+elseif nargin==2
+	if sgn == 1,
+		delta = 45; slat = 70;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+	elseif sgn==-1,
+		delta = 0;  slat = 71;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)');
+	else
+		error('Sign should be either +1 or -1');
+	end
+else
+	help expll2xy
+	error('bad usage');
+end
+
+%read filename: 
+domain=expread(filename);
+
+%change to x,y: 
+for i=1:length(domain),
+	[domain(i).x domain(i).y]= ll2xy(domain(i).y,domain(i).x,sgn,delta,slat);
+end
+
+%write back to filename: 
+expwrite(domain,filename);
Index: /issm/trunk-jpl/src/m/Exp/expmaster.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expmaster.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expmaster.m	(revision 12996)
@@ -0,0 +1,2 @@
+function expmaster(newfile,varargin)
+	disp('expmaster has been renamed exptool due to the unpopularity of its name')
Index: /issm/trunk-jpl/src/m/Exp/exporientation.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/exporientation.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/exporientation.m	(revision 12996)
@@ -0,0 +1,12 @@
+function exporientation(filename)
+
+a=expread(filename);
+
+dx=diff(a.x);
+dx=[dx;dx(end)];
+
+dy=diff(a.y);
+dy=[dy;dy(end)];
+
+quiver(a.x,a.y,dx,dy);
+
Index: /issm/trunk-jpl/src/m/Exp/expremovestraightsegments.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expremovestraightsegments.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expremovestraightsegments.m	(revision 12996)
@@ -0,0 +1,31 @@
+function expremovestraightsegments(newfilename,filename,cutoff)
+%EXPREMOVESTRAIGHTSEGMENTS:  remove straight segments connecting contours.
+%
+% Usage: expremovestraightsegments('argus.exp',100); 
+%
+%
+
+a=expread(filename,1);
+newcontours=a(1);
+
+for i=1:length(a),
+	contour=a(i);
+	
+	s=sqrt(contour.x.^2+contour.y.^2);
+	d=diff(s);
+	
+	pos=find(abs(d)>cutoff);
+	pos=[0;pos;length(contour.x)];
+
+	for j=1:length(pos)-1,
+
+		newcontour=contour;
+		newcontour.x=contour.x(pos(j)+1:pos(j+1));
+		newcontour.y=contour.y(pos(j)+1:pos(j+1));
+		newcontour.nods=length(newcontour.x);
+		newcontours(end+1)=newcontour;
+	end
+end
+newcontours=newcontours(2:end);
+
+expwrite(newcontours,newfilename);
Index: /issm/trunk-jpl/src/m/Exp/expsplit.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expsplit.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expsplit.m	(revision 12996)
@@ -0,0 +1,31 @@
+function expsplit(domainoutline)
+%EXPSPLIT - split exp file into sub-contours
+%
+%   This routine reads in a domain outline file (Argus format) and plots all the contours 
+%   This will create as many files there are contours in the domain, each file will be postfix with _i
+%   where i is the contour name. 
+%
+%   Usage:
+%      expsplit(domainoutline)
+%
+%   Example:
+%      expsplit('Domain.exp');
+%
+%   See also EXPMASTER, EXPDOC
+
+%check nargin
+if ~nargin | nargin>1
+	help expsplit
+	error('expsplit error message: bad usage');
+end
+
+[path,root,ext]=fileparts(domainoutline);
+
+%Read file: 
+domains=expread(domainoutline,1);
+
+%split and write contours: 
+for i=1:length(domains),
+	subdomain=domains(i);
+	expwrite(subdomain,[root '_' num2str(i)  ext]);
+end
Index: /issm/trunk-jpl/src/m/Exp/expsquare.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expsquare.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expsquare.m	(revision 12996)
@@ -0,0 +1,45 @@
+function expbox(filename)
+%EXPBOX - Create a ARGUS file using to clicks
+%
+%   Two clicks on a plot are used to generate a rectangular box
+%   This box is written in EXP format on filename
+%
+%   Usage:
+%      expbox(filename)
+
+%check
+if exist(filename,'file'),
+	choice=input(['A file ' filename ' already exists, do you want to modify it? (y/n)'],'s');
+	if ~strcmpi(choice,'y'),
+		disp('no modification done ... exiting');
+		return
+	end
+end
+
+%Get points
+disp('Click twice to define a rectangular domain. First click for upper left corner, second for lower right corner');
+[x,y]=ginput(2);
+
+xmiddle=mean(x);
+ymiddle=mean(y);
+
+x1=x(1); y1=y(1);
+x3=x(2); y3=y(2);
+
+Diag=[x1-xmiddle;y1-ymiddle];
+
+Vector=[xmiddle;ymiddle]+[-Diag(2);Diag(1)];
+x2=Vector(1); y2=Vector(2);
+
+Vector=[xmiddle;ymiddle]-[-Diag(2);Diag(1)];
+x4=Vector(1); y4=Vector(2);
+
+%Build Exp structure
+A=struct();
+A.nods=5;
+A.density=1;
+A.x=[x1 x2 x3 x4 x1]';
+A.y=[y1 y2 y3 y4 y1]';
+
+%Write structure
+expwrite(A,filename);
Index: /issm/trunk-jpl/src/m/Exp/expswapxy.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expswapxy.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expswapxy.m	(revision 12996)
@@ -0,0 +1,23 @@
+function expswapxy(filename)
+%EXPSWAP - swap x and y fields
+% 
+%   Usage:
+%      expswap(file)
+%
+%   See also EXPMASTER, EXPDOC
+
+
+contours=expread(filename,1);
+
+newcontours=contours(1);
+
+for i=1:length(contours), 
+	contour=contours(i);
+	newcontour=contour;
+	newcontour.x=contour.y;
+	newcontour.y=contour.x;
+	newcontours(end+1)=newcontour;
+end
+newcontours=newcontours(2:end);
+
+expwrite(newcontours,filename);
Index: /issm/trunk-jpl/src/m/Exp/exptool.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/exptool.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/exptool.m	(revision 12996)
@@ -0,0 +1,342 @@
+function exptool(newfile,varargin)
+%EXPMASTER - allow to create, modify, add, cut, .. segments of domain outline together
+%
+%   this routine is used to create, modify, cut,... an Argus file (.exp)
+%
+%   exptool(newprofile,'optionname',optionvalue)
+%      creation of an argus file newprofile
+%
+%   Available options:
+%      - include: include list of existing ARGUS files
+%      - color: line color (default='r')
+%      - selectioncolor: line color of selected profiles (default='b')
+%      - linestyle (default='-')
+%      - linewidth (default=0.2)
+%      - marker (default='+')
+%      - markersize (default=7)
+%      - markeredgecolor (default='r')
+%
+%   Usage:
+%      exptool(newfile,varargin)
+%
+%   Example:
+%      exptool('domain.exp','include',{'domain1.exp' 'domain2.exp'},'color','g','marker','+')
+%
+%   See also EXPDOC
+
+%recover options
+options=pairoptions(varargin{:});
+
+%Some checks
+if ~nargin | nargout
+	error('exptool usage: exptool(newfile,varargin)')
+elseif exist(newfile,'file'),
+	%recursive call to exptool if file already exists
+	if ~exist(options,'include'),
+		exptool(newfile,'include',newfile,varargin{:});
+		return;
+	end
+
+	%check modification
+	choice=input(['A file ' newfile ' already exists, do you want to modify it? (y/n)'],'s');
+	if ~strcmpi(choice,'y'),
+		disp('no modification done ... exiting');
+		return
+	end
+end
+
+%Add default options
+options=addfielddefault(options,'color','r');
+options=addfielddefault(options,'selectioncolor','b');
+options=addfielddefault(options,'LineStyle','-');
+options=addfielddefault(options,'LineWidth',0.2);
+options=addfielddefault(options,'Marker','+');
+options=addfielddefault(options,'MarkerSize',7);
+options=addfielddefault(options,'MarkerEdgeColor','r');
+
+%put all the argus profiles given in input in one structure A
+A=struct([]);
+numprofiles=0;
+numpoints=0;
+closed=[];
+
+%initialize the variables with files provided by 'include' option
+if exist(options,'include'),
+	files=getfieldvalue(options,'include');
+	if ischar(files), files={files}; end
+	for i=1:length(files),
+		filename=files{i};
+		if ~exist(filename,'file'),
+			error(['exptool error message:, ' filename ' does not exist. Exiting...']);
+		else
+			%read file
+			B=expread(filename);
+			%go through all profiles of B
+			for i=1:size(B,2)
+				%plug profile in A
+				if numprofiles
+					A(numprofiles+1)=B(i);
+				else
+					A=B(i);
+				end
+				%update numprofiles and numpoints
+				numpoints=numpoints+length(B(i).x);
+				numprofiles=numprofiles+1;
+				%figure out if the profile is closed or not
+				if (B(i).x(1)==B(i).x(end) & B(i).y(1)==B(i).y(end) & length(B(i).x)>1 )
+					closed(numprofiles)=1;
+				else
+					closed(numprofiles)=0;
+				end
+			end
+		end
+	end
+end
+
+%Get root of newfile
+[path root ext]=fileparts(newfile);
+
+%get current figure
+if ~isempty(get(0,'children')),%if there is already a figure (return the number of opened figures)
+	set(gcf,'Renderer','zbuffer'); %fixes a bug on Mac OS X (not needed in future Matlab version)
+	P=get(gcf,'position');
+	F=getframe(gca);
+	F=F.cdata;
+	%get current axis
+	xlim=get(gca,'Xlim');
+	ylim=get(gca,'Ylim');
+	%recreate x_m and y_m
+	x_m=linspace(xlim(1),xlim(2),size(F,2));
+	y_m=linspace(ylim(2),ylim(1),size(F,1)); %getframe reverse axis...
+	%plot the data in another figure
+	figure; set(gcf,'position',P);
+	imagesc(x_m,y_m,F); set(gca,'Ydir','normal');
+	prevplot=1;
+	prevplot2=1;
+else
+	figure
+	prevplot=0;
+	prevplot2=0;
+end
+
+%plot existing profile if any
+hold on
+
+%Build backup structre for do and redo
+backup=cell(1,3);
+backup{1,1}=A;
+backup{1,2}=numprofiles;
+backup{1,3}=numpoints;
+backup{1,4}=closed;
+
+loop=1;
+counter=1;
+while loop
+
+	%Go through A and rule out the empty profiles
+	list=[];
+	for i=1:size(A,2);
+		if length(A(i).x)==0
+			list(end+1)=i;
+			numprofiles=numprofiles-1;
+		end
+	end
+	A(list)=[];
+	closed(list)=[];
+
+	%Now erase all that have been done and plot the new structure A as it is
+	undoplots(prevplot);
+	if numprofiles
+		prevplot2=1;
+		for i=1:numprofiles
+			if length(A(i).x)==1,
+				plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+					'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker','o');
+			else
+				plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			end
+			prevplot2=prevplot2+1;
+		end
+	end
+
+	%display menu
+	title('Main Menu','FontSize',14);
+	button=menu('Menu','add a profile (open)',...%1
+		'add a contour (closed)',...              %2
+		'remove a profile',...                    %3
+		'modify the position of a point',...      %4
+		'add points inside a profile',...         %5
+		'add points at the end of a profile',...  %6
+		'remove points',...                       %7
+		'remove several points',...               %8
+		'cut a segment',...                       %9
+		'cut a large area',...                    %10
+		'merge profiles',...                      %11
+		'close profile',...                       %12
+		'undo',...                                %13
+		'redo',...                                %14
+		'quit');                                  %15
+
+
+	%UNDO??
+	if button==13;
+		if counter==1
+			disp('Already at oldest change');
+		else
+			counter=counter-1;
+			A=backup{counter,1};
+			numprofiles=backup{counter,2};
+			numpoints=backup{counter,3};
+			closed=backup{counter,4};
+		end
+	end
+
+	%REDO??
+	if button==14
+		if counter==size(backup,1)
+			disp('Already at newest change');
+		else
+			counter=counter+1;
+			A=backup{counter,1};
+			numprofiles=backup{counter,2};
+			numpoints=backup{counter,3};
+			closed=backup{counter,4};
+		end
+	end
+
+	switch button
+
+		case 1
+
+			[A,numprofiles,numpoints,closed]=addprofile(A,numprofiles,numpoints,closed,prevplot2,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 2
+
+			[A,numprofiles,numpoints,closed]=addcontour(A,numprofiles,numpoints,closed,prevplot2,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 3
+
+			[A,numprofiles,numpoints,closed]=removeprofile(A,numprofiles,numpoints,closed,prevplot2,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 4
+
+			[A,numprofiles,numpoints,closed]=modifyposition(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 5
+
+			[A,numprofiles,numpoints,closed]=addinsideprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 6
+
+			[A,numprofiles,numpoints,closed]=addendprofile(A,numprofiles,numpoints,closed,prevplot2,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 7
+
+			[A,numprofiles,numpoints,closed]=removepoints(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 8
+
+			[A,numprofiles,numpoints,closed]=removeseveralpoints(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 9
+
+			[A,numprofiles,numpoints,closed]=cutprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 10
+
+			[A,numprofiles,numpoints,closed]=cutarea(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+		case 11
+
+			[A,numprofiles,numpoints,closed]=mergeprofiles(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+
+		case 12
+
+			[A,numprofiles,numpoints,closed]=closeprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+			counter=counter+1;
+			backup{counter,1}=A;
+			backup{counter,2}=numprofiles;
+			backup{counter,3}=numpoints;
+			backup{counter,4}=closed;
+
+			%QUIT
+		case 15
+
+			loop=0;
+
+		otherwise
+
+			%do nothing
+
+	end
+
+end
+
+hold off
+
+%write contour using expwrite
+title('New file written, exiting...','FontSize',14);
+if isempty(A)
+	disp('Profile empty, no file written')
+else
+	expwrite(A,newfile);
+end
+
+%close window
+close;
Index: /issm/trunk-jpl/src/m/Exp/expxy2ll.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/expxy2ll.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/expxy2ll.m	(revision 12996)
@@ -0,0 +1,37 @@
+function expxy2ll(filename,sgn,central_meridian,standard_parallel)  
+%EXPLL2XY: switch exp argus file from lat,long to x,y
+%   Usage:
+%      expxy2ll(filename,sgn,central_meridian,standard_parallel)
+%      - sgn = Sign of latitude +1 : north latitude (default is mer=45 lat=70)
+%                               -1 : south latitude (default is mer=0  lat=71)
+
+
+%Get central_meridian and standard_parallel depending on hemisphere
+if nargin==4,
+	delta = central_meridian;
+	slat  = standard_parallel;
+elseif nargin==2
+	if sgn == 1,
+		delta = 45; slat = 70;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+	elseif sgn==-1,
+		delta = 0;  slat = 71;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)');
+	else
+		error('Sign should be either +1 or -1');
+	end
+else
+	help expxy2ll
+	error('bad usage');
+end
+
+%read filename: 
+domain=expread(filename);
+
+%change to x,y: 
+for i=1:length(domain),
+	[domain(i).y domain(i).x]= xy2ll(domain(i).x,domain(i).y,sgn,delta,slat); %watch out to swap lat and long
+end
+
+%write back to filename: 
+expwrite(domain,filename);
Index: /issm/trunk-jpl/src/m/Exp/flowlines.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/flowlines.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/flowlines.m	(revision 12996)
@@ -0,0 +1,163 @@
+function flowpath=flowlines(index,x,y,u,v,x0,y0,varargin)
+%FLOWLINES - compute flowlines from a given set of seed points
+%
+%   Usage:
+%      flowpath=flowlines(index,x,y,u,v,x0,y0)
+%
+%   the velocity field is given by the couple (u,v) and the coordinates
+%   of the seed points are (x0,y0). One can use one or several seed 
+%   points
+%
+%   Example:
+%      flowpath=flowlines(md.mesh.elements,md.mesh.x,md.mesh.y,md.vx,md.initialization.vy,x0,y0)
+
+%check input size
+if nargin>8 | nargin<7,
+	help flowlines
+	error('flowlines error message: bad usage');
+end
+
+%check input
+if (length(x)~=length(y) | length(x)~=length(u) | length(x)~=length(v)),
+	error('flowlines error message: x,y,u and v must have the same length');
+end
+if length(x)<3,
+	error('flowlines error message: at least one element is required');
+end
+if length(x0)~=length(y0),
+	error('flowlines error message: x0 and y0 do not have the same length');
+end
+
+%get maxiter and precision
+if nargin==8
+	maxiter=varargin{1};
+else
+	maxiter=200; %maximum number of iterations
+end
+precision=1; %division of each segment (higer precision increases number of segments)
+
+%check seed points
+tria=TriaSearch(index,x,y,x0,y0);
+pos=find(isnan(tria));
+x0(pos)=[];
+y0(pos)=[];
+
+%initialize other variables
+N=length(x0);
+X=x0; Y=y0;
+flowpath=struct('x',cell(N,1),'y',cell(N,1),'name','','density',1);
+for i=1:N,
+	flowpath(i).x=x0(i);
+	flowpath(i).y=y0(i);
+end
+done=zeros(N,1);
+
+%get avegared length of each element
+length_tria=1/3*(sqrt( (x(index(:,1))-x(index(:,2))).^2+(y(index(:,1))-y(index(:,2))).^2 )+...
+	sqrt((x(index(:,1))-x(index(:,3))).^2+(y(index(:,1))-y(index(:,3))).^2 )+...
+	sqrt((x(index(:,2))-x(index(:,3))).^2+(y(index(:,2))-y(index(:,3))).^2 ));
+
+%take velocity for each element
+u=u(index)*[1;1;1]/3;
+v=v(index)*[1;1;1]/3;
+
+%initialization:
+counter=1;
+
+while any(~done) 
+
+	%find current triangle
+	queue=find(~done);
+	tria=TriaSearch(index,x,y,X(queue),Y(queue));
+
+	%check that the point is actually inside a triangle of the mesh
+	listnan=find(isnan(tria));
+	for i=1:length(listnan)
+		%remove the last point
+		flowpath(queue(listnan(i))).x(end)=[];
+		flowpath(queue(listnan(i))).y(end)=[];
+		done(queue(listnan(i)))=1;
+	end
+	tria(listnan)=[]; 
+	queue(listnan)=[];
+
+	if isempty(tria),
+		break;
+	end
+
+	%velocity of the current triangle and norm it
+	ut=u(tria); vt=v(tria); normv=sqrt(ut.^2+vt.^2);
+	ut=ut./normv;vt=vt./normv;
+
+	%check counter
+	if counter>maxiter
+		disp(['Maximum number of iterations (' num2str(maxiter) ') reached while going forward'])
+		break
+	end
+	counter=counter+1;
+
+	%remove stagnant point
+	done(queue(find(ut==0 & vt==0)))=1;
+
+	%build next point
+	for i=1:length(queue)
+		X(queue(i))=flowpath(queue(i)).x(end)+ut(i)*length_tria(tria(i))/precision;
+		Y(queue(i))=flowpath(queue(i)).y(end)+vt(i)*length_tria(tria(i))/precision;
+		flowpath(queue(i)).x=[flowpath(queue(i)).x;flowpath(queue(i)).x(end)+ut(i)*length_tria(tria(i))/precision];
+		flowpath(queue(i)).y=[flowpath(queue(i)).y;flowpath(queue(i)).y(end)+vt(i)*length_tria(tria(i))/precision];
+	end
+end
+
+%same process but reverse (vel=-vel) to have a vcomplete flow line
+counter=1;
+X=x0; Y=y0;
+done=zeros(N,1);
+
+while any(~done) 
+
+	%find current triangle
+	queue=find(~done);
+	tria=TriaSearch(index,x,y,X(queue),Y(queue));
+
+	%check that the point is actually inside a triangle of the mesh
+	listnan=find(isnan(tria));
+	for i=1:length(listnan)
+		%remove the last point
+		flowpath(queue(listnan(i))).x(1)=[];
+		flowpath(queue(listnan(i))).y(1)=[];
+		done(queue(listnan(i)))=1;
+	end
+	tria(listnan)=[]; 
+	queue(listnan)=[];
+
+	if isempty(tria),
+		break;
+	end
+
+	%velocity of the current triangle and norm it
+	ut=-u(tria); vt=-v(tria); normv=sqrt(ut.^2+vt.^2);
+	ut=ut./normv;vt=vt./normv;
+
+	%check counter
+	if counter>maxiter
+		disp(['Maximum number of iterations (' num2str(maxiter) ') reached while going backward'])
+		break
+	end
+	counter=counter+1;
+
+	%remove stagnant point
+	done(queue(find(ut==0 & vt==0)))=1;
+
+	%build next point
+	for i=1:length(queue)
+		X(queue(i))=flowpath(queue(i)).x(1)+ut(i)*length_tria(tria(i))/precision;
+		Y(queue(i))=flowpath(queue(i)).y(1)+vt(i)*length_tria(tria(i))/precision;
+		flowpath(queue(i)).x=[flowpath(queue(i)).x(1)+ut(i)*length_tria(tria(i))/precision; flowpath(queue(i)).x];
+		flowpath(queue(i)).y=[flowpath(queue(i)).y(1)+vt(i)*length_tria(tria(i))/precision; flowpath(queue(i)).y];
+	end
+end
+
+%EXP compatibility
+for i=1:length(queue)
+	flowpath(queue(i)).name=['flowline' num2str(i)];
+end
Index: /issm/trunk-jpl/src/m/Exp/ginputquick.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/ginputquick.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/ginputquick.m	(revision 12996)
@@ -0,0 +1,221 @@
+function [out1,out2,out3] = ginput(arg1)
+%GINPUT - Graphical input from mouse.
+%
+%   [X,Y] = GINPUT(N) gets N points from the current axes and returns 
+%   the X- and Y-coordinates in length N vectors X and Y.  The cursor
+%   can be positioned using a mouse (or by using the Arrow Keys on some 
+%   systems).  Data points are entered by pressing a mouse button
+%   or any key on the keyboard except carriage return, which terminates
+%   the input before N points are entered.
+%
+%   [X,Y] = GINPUT gathers an unlimited number of points until the
+%   return key is pressed.
+% 
+%   [X,Y,BUTTON] = GINPUT(N) returns a third result, BUTTON, that 
+%   contains a vector of integers specifying which mouse button was
+%   used (1,2,3 from left) or ASCII numbers if a key on the keyboard
+%   was used.
+%
+%   Usage:
+%      [out1,out2,out3] = ginput(arg1)
+
+%   Copyright 1984-2005 The MathWorks, Inc.
+%   $Revision: 1.1 $  $Date: 2009/04/03 22:56:26 $
+
+out1 = []; out2 = []; out3 = []; y = [];
+c = computer;
+if ~strcmp(c(1:2),'PC') 
+   tp = get(0,'TerminalProtocol');
+else
+   tp = 'micro';
+end
+
+if ~strcmp(tp,'none') && ~strcmp(tp,'x') && ~strcmp(tp,'micro'),
+   if nargout == 1,
+      if nargin == 1,
+         out1 = trmginput(arg1);
+      else
+         out1 = trmginput;
+      end
+   elseif nargout == 2 || nargout == 0,
+      if nargin == 1,
+         [out1,out2] = trmginput(arg1);
+      else
+         [out1,out2] = trmginput;
+      end
+      if  nargout == 0
+         out1 = [ out1 out2 ];
+      end
+   elseif nargout == 3,
+      if nargin == 1,
+         [out1,out2,out3] = trmginput(arg1);
+      else
+         [out1,out2,out3] = trmginput;
+      end
+   end
+else
+   
+   fig = gcf;
+   figure(gcf);
+   
+   if nargin == 0
+      how_many = -1;
+      b = [];
+   else
+      how_many = arg1;
+      b = [];
+      if  ischar(how_many) ...
+            || size(how_many,1) ~= 1 || size(how_many,2) ~= 1 ...
+            || ~(fix(how_many) == how_many) ...
+            || how_many < 0
+         error('MATLAB:ginput:NeedPositiveInt', 'Requires a positive integer.')
+      end
+      if how_many == 0
+         ptr_fig = 0;
+         while(ptr_fig ~= fig)
+            ptr_fig = get(0,'PointerWindow');
+         end
+         scrn_pt = get(0,'PointerLocation');
+         loc = get(fig,'Position');
+         pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)];
+         out1 = pt(1); y = pt(2);
+      elseif how_many < 0
+         error('MATLAB:ginput:InvalidArgument', 'Argument must be a positive integer.')
+      end
+   end
+   
+   % Suspend figure functions
+   state = uisuspend(fig);
+   
+   toolbar = findobj(allchild(fig),'flat','Type','uitoolbar');
+   if ~isempty(toolbar)
+        ptButtons = [uigettool(toolbar,'Plottools.PlottoolsOff'), ...
+                     uigettool(toolbar,'Plottools.PlottoolsOn')];
+        ptState = get (ptButtons,'Enable');
+        set (ptButtons,'Enable','off');
+   end
+
+   set(fig,'pointer','fullcrosshair');
+   fig_units = get(fig,'units');
+   char = 0;
+
+   % We need to pump the event queue on unix
+   % before calling WAITFORBUTTONPRESS 
+   drawnow
+   
+   while how_many ~= 0
+      % Use no-side effect WAITFORBUTTONPRESS
+      waserr = 0;
+      try
+	keydown = wfbp;
+      catch
+	waserr = 1;
+      end
+      if(waserr == 1)
+         if(ishandle(fig))
+            set(fig,'units',fig_units);
+	    uirestore(state);
+            error('MATLAB:ginput:Interrupted', 'Interrupted');
+         else
+            error('MATLAB:ginput:FigureDeletionPause', 'Interrupted by figure deletion');
+         end
+      end
+      
+      ptr_fig = get(0,'CurrentFigure');
+      if(ptr_fig == fig)
+         if keydown
+            char = get(fig, 'CurrentCharacter');
+            button = abs(get(fig, 'CurrentCharacter'));
+            scrn_pt = get(0, 'PointerLocation');
+            set(fig,'units','pixels')
+            loc = get(fig, 'Position');
+            pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)];
+            set(fig,'CurrentPoint',pt);
+         else
+            button = get(fig, 'SelectionType');
+            if strcmp(button,'open') 
+               button = 1;
+            elseif strcmp(button,'normal') 
+               button = 1;
+            elseif strcmp(button,'extend')
+               button = 2;
+            elseif strcmp(button,'alt') 
+               button = 3;
+            else
+               error('MATLAB:ginput:InvalidSelection', 'Invalid mouse selection.')
+            end
+         end
+         pt = get(gca, 'CurrentPoint');
+         
+         how_many = how_many - 1;
+         
+         if(char == 13) % & how_many ~= 0)
+            % if the return key was pressed, char will == 13,
+            % and that's our signal to break out of here whether
+            % or not we have collected all the requested data
+            % points.  
+            % If this was an early breakout, don't include
+            % the <Return> key info in the return arrays.
+            % We will no longer count it if it's the last input.
+            break;
+         end
+
+         out1 = [out1;pt(1,1)];
+         y = [y;pt(1,2)];
+         b = [b;button];
+      end
+   end
+   
+   uirestore(state);
+   if ~isempty(toolbar) && ~isempty(ptButtons)
+        set (ptButtons(1),'Enable',ptState{1});
+        set (ptButtons(2),'Enable',ptState{2});
+   end
+   set(fig,'units',fig_units);
+   
+   if nargout > 1
+      out2 = y;
+      if nargout > 2
+         out3 = b;
+      end
+   else
+      out1 = [out1 y];
+   end
+
+   line(out1,y);
+   line([out1(length(out1)) out1(1)],[y(length(y)) y(1)]);
+   
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function key = wfbp
+%WFBP   Replacement for WAITFORBUTTONPRESS that has no side effects.
+
+fig = gcf;
+current_char = [];
+
+% Now wait for that buttonpress, and check for error conditions
+waserr = 0;
+try
+  h=findall(fig,'type','uimenu','accel','C');   % Disabling ^C for edit menu so the only ^C is for
+  set(h,'accel','');                            % interrupting the function.
+  keydown = waitforbuttonpress;
+  current_char = double(get(fig,'CurrentCharacter')); % Capturing the character.
+  if~isempty(current_char) && (keydown == 1)           % If the character was generated by the 
+	  if(current_char == 3)                       % current keypress AND is ^C, set 'waserr'to 1
+		  waserr = 1;                             % so that it errors out. 
+	  end
+  end
+  
+  set(h,'accel','C');                                 % Set back the accelerator for edit menu.
+catch
+  waserr = 1;
+end
+drawnow;
+if(waserr == 1)
+   set(h,'accel','C');                                % Set back the accelerator if it errored out.
+   error('MATLAB:ginput:Interrupted', 'Interrupted');
+end
+
+if nargout>0, key = keydown; end
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Index: /issm/trunk-jpl/src/m/Exp/manipulation/addcontour.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/addcontour.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/addcontour.m	(revision 12996)
@@ -0,0 +1,50 @@
+function [A,numprofiles,numpoints,closed]=addcontour(A,numprofiles,numpoints,closed,prevplot,root,options);
+%ADDCONTOUR - add a closed contour
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=addcontour(A,numprofiles,numpoints,closed,prevplot,root,options)
+		   
+	title('click to add a point to the new profile, RETURN to exit','FontSize',14)
+	hold on
+
+	loop=1;
+	x=[];
+	y=[];
+
+	while loop
+
+		[xi,yi] = ginput(1);
+					  
+		if ~isempty(xi)
+			x(end+1,1)=xi;
+			y(end+1,1)=yi;
+
+			%plot everything
+			undoplots(prevplot);
+			plot(x,y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+				'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+			plot(x(end),y(end),'MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+		else
+
+			%check that the profile is not empty
+			if ~isempty(x)
+				x(end+1)=x(1);
+				y(end+1)=y(1);
+				A(end+1).x=x; 
+				A(end).y=y; 
+				A(end).name=root; 
+				A(end).density=1; 
+				numprofiles=numprofiles+1;
+				numpoints=numpoints+length(x);
+				closed(end+1)=1;
+			end
+
+			%get out
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/addendprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/addendprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/addendprofile.m	(revision 12996)
@@ -0,0 +1,86 @@
+function [A,numprofiles,numpoints,closed]=addendprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%ADDENDPROFILE - add point at the end of a n existing profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=addendprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting...')
+		return
+	end	   
+	if ~any(~closed)
+		disp('all profiles are closed')
+		return
+	end	   
+	%select a profile first
+	if numprofiles>1
+		%first step, select a profile
+		isclosed=1;
+		title('click on a profile, RETURN to exit','FontSize',14)
+		while isclosed
+			[xi,yi] = ginput(1);
+			if ~isempty(xi)
+				%get the closest point 
+				[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+				if closed(profsel)
+					disp('selected profile is closed, make another selection')
+				else
+					isclosed=0;
+				end
+
+			else
+				%RETURN -> out
+				return
+			end
+		end
+	else
+		profsel=1;
+	end
+
+	%initialize x and y
+	x=A(profsel).x;
+	y=A(profsel).y;
+
+	%plot the selected profile
+	hold on
+	plot(x,y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+		'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	plot(x(end),y(end),'MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+	loop=1;
+	while loop
+
+		%first step, select a profile
+		title('click to add point to the selected profile, RETURN to exit','FontSize',14)
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+			x(end+1,1)=xi;
+			y(end+1,1)=yi;
+
+			%plot everything
+			undoplots(prevplot);
+			plot(x,y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+				'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+			plot(x(end),y(end),'MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize')+2,'Marker',getfieldvalue(options,'Marker'));
+
+		else
+
+			%check that the profile is not empty
+			if ~isempty(x)
+				A(profsel).x=x; 
+				A(profsel).y=y; 
+				A(profsel).name=root; 
+				A(profsel).density=1; 
+				numpoints=numpoints+length(x);
+			end
+
+			%get out
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/addinsideprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/addinsideprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/addinsideprofile.m	(revision 12996)
@@ -0,0 +1,79 @@
+function [A,numprofiles,numpoints,closed]=addinsideprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%ADDINSIDEPROFILE - add apoint inside a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=addinsideprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting...')
+		return
+	end	   
+	if numpoints<2
+		disp('at least two points are required, exiting...')
+		return
+	end	   
+	hold on
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	end
+
+	loop=1;
+	while loop
+
+		%first step, select a segment
+		title('click on a segment, RETURN to exit','FontSize',14)
+		[xi,yi] = ginput(1);
+
+		%first click
+		if ~isempty(xi)
+
+			%get the closest segment
+			[profsel indsel]=closestsegment(A,numprofiles,xi,yi);
+
+			%check that at least one segment exists
+			if indsel==0
+				disp('at least two points in one profile are required, exiting...')
+				return
+			end
+
+			%highlight selected segment
+			plot([A(profsel).x(indsel) A(profsel).x(indsel+1)],[A(profsel).y(indsel) A(profsel).y(indsel+1)],...
+				'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+				'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+			%next click
+			title('click on the new point''s location, RETURN to exit','FontSize',14)
+			[xi,yi,but] = ginput(1);
+
+			%second click
+			if ~isempty(xi)
+
+				%add point to A
+				A(profsel).x=[A(profsel).x(1:indsel,1); xi; A(profsel).x(indsel+1:end,1)];
+				A(profsel).y=[A(profsel).y(1:indsel,1); yi; A(profsel).y(indsel+1:end,1)];
+				numpoints=numpoints+1;
+
+				%plot new profile
+				undoplots(prevplot);
+				for i=1:numprofiles
+					plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+						'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+				end
+
+			else
+				%RETURN->exit
+				return
+			end
+		else
+			%RETURN-> exit
+			return
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/addprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/addprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/addprofile.m	(revision 12996)
@@ -0,0 +1,48 @@
+function [A,numprofiles,numpoints,closed]=addprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%ADDPROFILE - add a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=addprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+		   
+	title('click to add a point to the new profile, RETURN to exit','FontSize',14)
+	hold on
+
+	loop=1;
+	x=[];
+	y=[];
+
+	while loop
+
+		[xi,yi] = ginput(1);
+					  
+		if ~isempty(xi)
+			x(end+1,1)=xi;
+			y(end+1,1)=yi;
+
+			%plot everything
+			undoplots(prevplot);
+			plot(x,y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+				'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+			plot(x(end),y(end),'MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+		else
+
+			%check that the profile is not empty
+			if ~isempty(x)
+				A(end+1).x=x; 
+				A(end).y=y; 
+				A(end).name=root; 
+				A(end).density=1; 
+				numprofiles=numprofiles+1;
+				numpoints=numpoints+length(x);
+				closed(end+1)=0;
+			end
+
+			%get out
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/closeprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/closeprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/closeprofile.m	(revision 12996)
@@ -0,0 +1,68 @@
+function [A,numprofiles,numpoints,closed]=closeprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%CLOSEPROFILE - close one or several profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=closeprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+
+	%some checks
+	if numprofiles==0
+		disp('no profile to be closed')
+		return
+	end
+		   
+	title('click on the profiles to be closed, RETURN to exit','FontSize',14)
+	hold on
+
+	loop=1;
+	selection=[];
+
+	while loop
+
+		%some checks,
+		if numprofiles==0    
+			disp('no profile present, exiting...')
+			return            
+		end  
+		if ~any(~closed),
+			disp('All the profiles are closed, exiting...')
+			return
+		end
+
+		[xi,yi] = ginput(1);
+					  
+		if ~isempty(xi)
+
+			%get closest profile
+			[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+
+			if ismember(profsel,selection)
+				%profile was in selection, remove it from the selection
+				selection(find(selection==profsel))=[];
+				%back to regular color
+				plot(A(profsel).x,A(profsel).y,...
+					'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			elseif closed(profsel),
+				%profile already closed, do nothing
+				disp('selected profile aready closed, make another selection'),
+			else
+				%add the profile to the list to be closed
+				selection(end+1)=profsel;
+				%in selectioncolor
+				plot(A(profsel).x,A(profsel).y,...
+					'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			end
+		else
+			%close the profiles
+			for i=1:length(selection),
+				A(selection(i)).x(end+1)=A(selection(i)).x(1);
+				A(selection(i)).y(end+1)=A(selection(i)).y(1);
+				numpoints=numpoints+1;
+				closed(selection(i))=1;
+			end
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/closestpoint.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/closestpoint.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/closestpoint.m	(revision 12996)
@@ -0,0 +1,21 @@
+function [profsel indsel]=closestpoint(A,numprofiles,xi,yi)
+%CLOSESTPOINT - find the closest point of a profile
+%
+%   This routine find the point of the profile A that is the closest
+%   to (xi,yi) and return the number of the profile and the number of
+%   the point
+%
+%   Usage:
+%     [profsel indsel]=closestpoint(A,numprofiles,xi,yi) 
+
+	%loop over the points of each profile, find the closest to (xi,yi)
+	for i=1:numprofiles,
+		distance=(xi-A(i).x).^2+(yi-A(i).y).^2;
+		[newdistance p]=min(distance);
+		if ((i==1) | (newdistance<olddistance)),
+			indsel=p;
+			profsel=i;
+			olddistance=newdistance;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/closestsegment.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/closestsegment.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/closestsegment.m	(revision 12996)
@@ -0,0 +1,28 @@
+function [profsel indsel]=closestsegment(A,numprofiles,xi,yi)
+%CLOSESTSEGMENT - find the closest segment of a profile
+%
+%   This routine find the segment of the profile A that is the closest
+%   to (xi,yi) and return the number of the profile and the number of
+%   the first point belonging to this closest segment
+%
+%   Usage:
+%     [profsel indsel]=closestsegment(A,numprofiles,xi,yi) 
+
+	%loop over the middles of each profile, find the closest to (xi,yi)
+	profsel=0;
+	indsel=0;
+	first=1;
+	for i=1:numprofiles,
+		if length(A(i).x)>1
+			middles=[(A(i).x(1:end-1)+A(i).x(2:end))/2 (A(i).y(1:end-1)+A(i).y(2:end))/2];
+			distance=(xi-middles(:,1)).^2+(yi-middles(:,2)).^2;
+			[newdistance p]=min(distance);
+			if (first | (newdistance<olddistance)),
+				first=0;
+				indsel=p;
+				profsel=i;
+				olddistance=newdistance;
+			end
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/cutarea.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/cutarea.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/cutarea.m	(revision 12996)
@@ -0,0 +1,156 @@
+function [A,numprofiles,numpoints,closed]=cutarea(A,numprofiles,numpoints,closed,prevplot,root,options);
+%CUTAREA - cut several point of a profile
+%
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile. The user must click 3 times to select the
+%   area to be removed. Twice to select the tips and one to select
+%   the part of the profile to be removed
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=cutarea(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	hold on
+	loop=1;
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	end
+
+	points=[];
+
+	%loop (at least 3 clicks needed)
+	while loop
+
+		%some checks
+		if numprofiles==0
+			disp('no profile present, exiting...')
+			return
+		end	   
+		if numpoints<3
+			disp('at least two points are needed, exiting...')
+			return
+		end	   
+
+		%select a point
+		if isempty(points)
+			title('click on the first tip, RETURN to exit','FontSize',14)
+		elseif length(points)==1
+			title('click on the second tip, RETURN to exit','FontSize',14)
+		else
+			title('click in the middle of the area to be cut, RETURN to exit','FontSize',14)
+		end
+
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+			%get the closest point
+			%first time, look at all profiles
+			if isempty(points)
+				[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+				if ((closed(profsel) & length(A(profsel).x)<4) |  (~closed(profsel) & length(A(profsel).x)<3)),
+					disp('the selected profile has less than 3 points, make another selection');
+				else
+					selection=profsel;
+					points(end+1)=indsel;
+					plot(A(profsel).x,A(profsel).y,...
+						'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+					text(A(selection).x(indsel),A(selection).y(indsel),num2str(1),'FontSize',14,'background',[0.7 0.7 0.9]);
+				end
+			else
+				%get the 2d or 3d point for the given contou
+				[profsel indsel]=closestpoint(A(selection),1,xi,yi);
+				if ismember(indsel,points)
+					disp('the selected points must be distinct')
+				else
+					%second click?
+					if length(points)==1,
+						points(end+1)=indsel;
+						text(A(selection).x(indsel),A(selection).y(indsel),num2str(2),'FontSize',14,'background',[0.7 0.7 0.9]);
+					%third click?
+					else
+						p1=points(1); p2=points(2); p3=indsel;
+						x=A(selection).x; y=A(selection).y;
+						if p1<p2
+							if p3>p1 & p3<p2
+								if closed(selection)
+									%open the profile
+									n=length(A(selection).x);
+									A(selection).x=[A(selection).x(p2:end-1,1);A(selection).x(1:p1,1)];
+									A(selection).y=[A(selection).y(p2:end-1,1);A(selection).y(1:p1,1)];
+									numpoints=numpoints-(n-length(A(selection).x));
+									closed(selection)=0;
+								else
+									%cut in 2 profiles
+									A(selection).x=x(1:p1);
+									A(selection).y=y(1:p1);
+									closed(selection)=0;
+									A(end+1).x=x(p2:end);
+									A(end).y=y(p2:end);
+									A(end).density=A(selection).density;
+									A(end).name=A(selection).name;
+									closed(end+1)=0;
+									numprofiles=numprofiles+1;
+									numpoints=numpoints-(p2-p1-1);
+								end
+							else
+								%only point removal
+								n=length(A(selection).x);
+								A(selection).x=x(p1:p2);
+								A(selection).y=y(p1:p2);
+								numpoints=numpoints-(n-length(A(selection).x));
+								closed(selection)=0;
+							end
+						else
+							if p3>p2 & p3<p1
+								if closed(selection)
+									%open the profile
+									n=length(A(selection).x);
+									A(selection).x=[A(selection).x(p1:end-1,1);A(selection).x(1:p2,1)];
+									A(selection).y=[A(selection).y(p1:end-1,1);A(selection).y(1:p2,1)];
+									numpoints=numpoints-(n-length(A(selection).x));
+									closed(selection)=0;
+								else
+									%cut in 2 profiles
+									closed(selection)=0;
+									A(selection).x=x(1:p2);
+									A(selection).y=y(1:p2);
+									A(end+1).x=x(p1:end);
+									A(end).y=y(p1:end);
+									A(end).density=A(selection).density;
+									A(end).name=A(selection).name;
+									closed(end+1)=0;
+									numprofiles=numprofiles+1;
+									numpoints=numpoints-(p1-p2-1);
+								end
+							else
+								%only point removal
+								n=length(A(selection).x);
+								x(1:p2-1)=[];x(p1-p2+2:end)=[];%it should have been x(p2+1:end)
+								y(1:p2-1)=[];y(p1-p2+2:end)=[];
+								A(selection).x=x;
+								A(selection).y=y;
+								numpoints=numpoints-(n-length(A(selection).x));
+								closed(selection)=0;
+							end
+						end
+
+						%plot new profile
+						undoplots(prevplot);
+						for i=1:numprofiles
+							plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+								'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+						end
+						points=[];
+
+					end
+				end
+			end
+		else
+			%RETRUN-> quit
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/cutprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/cutprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/cutprofile.m	(revision 12996)
@@ -0,0 +1,79 @@
+function [A,numprofiles,numpoints,closed]=cutprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%CUTPROFILE - cut a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=cutprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting...')
+		return
+	end	   
+	if numpoints<2
+		disp('at least two points are needed')
+		return
+	end	   
+	hold on
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	end
+
+	loop=1;
+	while loop
+
+		%select a segment
+		title('click the segment to cut, RETURN to exit','FontSize',14)
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+
+			%get the closest segment
+			[profsel indsel]=closestsegment(A,numprofiles,xi,yi);
+
+			%check that at least one segment exists
+			if indsel==0
+				disp('at least 2 points are required');
+				return,
+			end
+
+			if ((closed(profsel) & length(A(profsel).x)<3) | (~closed(profsel) & length(A(profsel).x)<2))
+				disp('at least 2 points are required, make another selection');
+			else
+				%cut A
+				if closed(profsel)
+					%open the contour
+					A(profsel).x=[A(profsel).x(indsel+1:end-1,1);A(profsel).x(1:indsel,1)];
+					A(profsel).y=[A(profsel).y(indsel+1:end-1,1);A(profsel).y(1:indsel,1)];
+					numpoints=numpoints-1;
+					closed(profsel)=0;
+				else
+					%cut the contour in 2 profiles
+					A(end+1).x=A(profsel).x(indsel+1:end,1);
+					A(end).y=A(profsel).y(indsel+1:end,1);
+					A(end).name=root; 
+					A(end).density=1; 
+					A(profsel).x=A(profsel).x(1:indsel,1);
+					A(profsel).y=A(profsel).y(1:indsel,1);
+					numprofiles=numprofiles+1;
+					closed(end+1)=0;
+				end
+
+				%plot new profile
+				undoplots(prevplot);
+				for i=1:numprofiles
+					plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+						'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+				end
+			end
+		else
+			%RETURN->exit
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/mergeprofiles.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/mergeprofiles.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/mergeprofiles.m	(revision 12996)
@@ -0,0 +1,152 @@
+function [A,numprofiles,numpoints,closed]=mergeprofiles(A,numprofiles,numpoints,closed,prevplot,root,options);
+%MERGEPROFILES - merge profiles
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile. The user must select the two tips that
+%   he/she wants to merge
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=mergeprofiles(A,numprofiles,numpoints,closed,prevplot,root,options)
+
+hold on
+loop=1;
+
+%Take all the tips coordinates of open profiles
+counter=1; tips=[];
+for i=1:numprofiles
+	if ~closed(i),
+		%x and y coord, profile number, 1 if beginning, 2 and if end
+		if length(A(i).x)==1,
+			tips(counter,:)=[A(i).x(1)   A(i).y(1)   i  1];
+			counter=counter+1;
+		else
+			tips(counter,:)=[A(i).x(1)   A(i).y(1)   i  1];
+			tips(counter+1,:) = [A(i).x(end) A(i).y(end) i  2];
+			counter=counter+2;
+		end
+	end
+end
+
+if size(tips,1)<2
+	disp('at least one unclosed profile is required')
+	return
+end
+
+%plot the tips only
+plot(tips(:,1),tips(:,2),...
+	'LineStyle','none','MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+firsttip=1;
+
+%loop (at least 2 clicks needed)
+while loop
+
+	%some checks
+	if size(tips,1)<2
+		disp('at least one unclosed profiles are required')
+		return
+	end
+
+	%select a point
+	if firsttip
+		title('click on the first tip, RETURN to exit','FontSize',14)
+	else
+		title('click on the second tip, RETURN to exit','FontSize',14)
+	end
+
+	[xi,yi] = ginput(1);
+
+	if ~isempty(xi)
+
+		if firsttip
+			%find the selected tip
+			distance=(xi-tips(:,1)).^2+(yi-tips(:,2)).^2;
+			[dmin tip1]=min(distance);
+			numprofile1=tips(tip1,3);
+			firsttip=0;
+
+			%remove tip1 from tips list
+			newtips=tips;
+			newtips(tip1,:)=[];
+
+			%plot selected tip
+			plot(tips(tip1,1),tips(tip1,2),...
+				'LineStyle','none','MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+			plot(A(numprofile1).x,A(numprofile1).y,...
+				'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+
+		%second selection
+		else
+			distance=(xi-newtips(:,1)).^2+(yi-newtips(:,2)).^2;
+			[dmin tip2]=min(distance);
+			numprofile2=newtips(tip2,3);
+
+			if numprofile1==numprofile2
+				%close the profile
+				A(numprofile1).x(end+1)=A(numprofile1).x(1);
+				A(numprofile1).y(end+1)=A(numprofile1).y(1);
+				numpoints=numpoints+1;
+				closed(numprofile1)=1;
+
+			else
+
+				if tips(tip1,4)==1 & newtips(tip2,4)==1,
+					A(numprofile1).x=[flipud(A(numprofile2).x); A(numprofile1).x];
+					A(numprofile1).y=[flipud(A(numprofile2).y); A(numprofile1).y];
+					numprofiles=numprofiles-1;
+
+				elseif tips(tip1,4)==1 & newtips(tip2,4)==2,
+					A(numprofile1).x=[A(numprofile2).x; A(numprofile1).x];
+					A(numprofile1).y=[A(numprofile2).y; A(numprofile1).y];
+					numprofiles=numprofiles-1;
+
+				elseif tips(tip1,4)==2 & newtips(tip2,4)==1,
+					A(numprofile1).x=[A(numprofile1).x; A(numprofile2).x];
+					A(numprofile1).y=[A(numprofile1).y; A(numprofile2).y];
+					numprofiles=numprofiles-1;
+
+				elseif tips(tip1,4)==2 & newtips(tip2,4)==2,
+					A(numprofile1).x=[A(numprofile1).x; flipud(A(numprofile2).x)];
+					A(numprofile1).y=[A(numprofile1).y; flipud(A(numprofile2).y)];
+					numprofiles=numprofiles-1;
+				end
+
+				%delete profile2
+				A(numprofile2)=[];
+				closed(numprofile2)=[];
+
+			end
+
+			%update tips
+			counter=1; tips=[];
+			for i=1:numprofiles
+				if ~closed(i),
+					%x and y coord, profile number, 1 if beginning, 2 and if end
+					if length(A(i).x)==1,
+						tips(counter,:)=[A(i).x(1)   A(i).y(1)   i  1];
+						counter=counter+1;
+					else
+						tips(counter,:)=[A(i).x(1)   A(i).y(1)   i  1];
+						tips(counter+1,:) = [A(i).x(end) A(i).y(end) i  2];
+						counter=counter+2;
+					end
+				end
+			end
+
+			%plot new profile
+			undoplots(prevplot);
+			for i=1:numprofiles
+				plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			end
+			if ~isempty(tips)
+				plot(tips(:,1),tips(:,2),...
+					'LineStyle','none','MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+			end
+
+			%back to beginning
+			firsttip=1;
+		end
+	else
+		%RETRUN-> quit
+		loop=0;
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/modifyposition.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/modifyposition.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/modifyposition.m	(revision 12996)
@@ -0,0 +1,77 @@
+function [A,numprofiles,numpoints,closed]=modifyposition(A,numprofiles,numpoints,closed,prevplot,root,options);
+%MODIFYPOSITION - modify the prosition of a point of a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=modifyposition(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting..')
+		return
+	end
+
+	hold on
+	loop=1;
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	end
+
+	while loop
+
+		%select a point to be modified 
+		title('click on the point to be modified, RETURN to exit','FontSize',14)
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+
+			%get the closest point
+			[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+
+			%plot the point in blue
+			plot(A(profsel).x(indsel),A(profsel).y(indsel),...
+				'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+				'MarkerEdgeColor',getfieldvalue(options,'selectioncolor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+			%select new location
+			title('click on the new location, RETURN to exit','FontSize',14)
+			[xi,yi] = ginput(1);
+
+			if ~isempty(xi)
+
+				%modification of its coordinates
+				A(profsel).x(indsel)=xi;
+				A(profsel).y(indsel)=yi;
+
+				%modify the last point if the profile is closed and indsel=end or 1
+				if closed(profsel)
+					if indsel==1 
+						A(profsel).x(end)=xi;
+						A(profsel).y(end)=yi;
+					elseif indsel==length(A(profsel).x)
+						A(profsel).x(1)=xi;
+						A(profsel).y(1)=yi;
+					end
+				end
+
+				%plot new profile
+				undoplots(prevplot);
+				for i=1:numprofiles
+					plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+						'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+				end
+			else
+				%RETURN-> exit
+				loop=0;
+			end
+		else
+			%RETURN-> exit
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/removepoints.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/removepoints.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/removepoints.m	(revision 12996)
@@ -0,0 +1,85 @@
+function [A,numprofiles,numpoints,closed]=removepoints(A,numprofiles,numpoints,closed,prevplot,root,options);
+%REMOVEPOINTS - remove a point from a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=removepoints(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting...')
+		return
+	end
+
+	hold on
+	loop=1;
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+
+	end
+
+	while loop
+
+		%check that at least one point is present
+		if numpoints==0
+			disp('at least one point are needed')
+			return
+		end	   
+
+		%select a point to be deleted
+		title('click on the point to be removed, RETURN to exit','FontSize',14)
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+
+			%get the closest point
+			[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+
+			%remove point of A
+			A(profsel).x(indsel)=[];
+			A(profsel).y(indsel)=[];
+
+			%unclose the domain if only 2 points remaining
+			if closed(profsel)
+				if length(A(profsel).x)==3
+					A(profsel).x(end)=[];
+					A(profsel).y(end)=[];
+					numpoints=numpoints-1;
+					closed(profsel)=0;
+				end
+			end
+
+			%remove the last point if the profile is closed and indsel=end or 1
+			if closed(profsel)
+				if indsel==1 
+					A(profsel).x(end)=A(profsel).x(1);
+					A(profsel).y(end)=A(profsel).y(1);
+				elseif indsel==length(A(profsel).x)
+					A(profsel).x(1)=A(profsel).x(end);
+					A(profsel).y(1)=A(profsel).y(end);
+				end
+			end
+			numpoints=numpoints-1;
+
+			%plot new profile
+			undoplots(prevplot);
+			for i=1:numprofiles
+				plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+					'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+				if length(A(i).x)==1
+					plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+						'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker','o');
+				end
+			end
+
+		else
+			%RETURN-> exit
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/removeprofile.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/removeprofile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/removeprofile.m	(revision 12996)
@@ -0,0 +1,56 @@
+function [A,numprofiles,numpoints,closed]=removeprofile(A,numprofiles,numpoints,closed,prevplot,root,options);
+%REMOVEPROFILE - delete a profile
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=removeprofile(A,numprofiles,numpoints,closed,prevplot,root,options)
+
+	title('click on the profiles to be removed, RETURN to exit','FontSize',14)
+	hold on
+
+	loop=1;
+	selection=[];
+
+	while loop
+
+		%some checks
+		if numprofiles==0
+			disp('no profile to be removed, exiting...')
+			return
+		end
+		   
+		[xi,yi] = ginput(1);
+					  
+		if ~isempty(xi)
+
+			%get closest profile
+			[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+
+			if ismember(profsel,selection)
+				%profile was in selection, remove it
+				selection(find(selection==profsel))=[];
+				%back to regular color
+				plot(A(profsel).x,A(profsel).y,...
+					'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			else
+				%add the profile to the list to be removed
+				selection(end+1)=profsel;
+				%in selectioncolor
+				plot(A(profsel).x,A(profsel).y,...
+					'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+			end
+		else
+			%remove the profiles
+			selection=sort(selection);
+			for i=1:length(selection),
+				numprofiles=numprofiles-1;
+				numpoints=numpoints-length(A(selection(i)-(i-1)).x);
+				A(selection(i)-(i-1))=[];
+				closed(selection(i)-(i-1))=[];
+			end
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/removeseveralpoints.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/removeseveralpoints.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/removeseveralpoints.m	(revision 12996)
@@ -0,0 +1,130 @@
+function [A,numprofiles,numpoints,closed]=removeseveralpoints(A,numprofiles,numpoints,closed,prevplot,root,options);
+%REMOVESEVERALPOINTS - remove several point
+%
+%   this script is used by exptool as an elementary operation
+%   on an ARGUS profile
+%
+%   Usage:
+%      [A,numprofiles,numpoints,closed]=removeseveralpoints(A,numprofiles,numpoints,closed,prevplot,root,options)
+		
+	%some checks
+	if numprofiles==0
+		disp('no profile present, exiting...')
+		return
+	end	   
+	if numpoints<3
+		disp('at least 3 points are required, exiting...')
+		return
+	end	   
+	hold on
+	loop=1;
+
+	%plot squares
+	for i=1:numprofiles
+		plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+			'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+	end
+
+	points=[];
+
+	%loop (at least 3 clicks needed)
+	while loop
+
+		%some checks
+		if numpoints<3
+			disp('at least 3 points are required, exiting...')
+			return
+		end
+
+		%select a point
+		if isempty(points)
+			title('click on the first tip, RETURN to exit','FontSize',14)
+		elseif length(points)==1
+			title('click on the second tip, RETURN to exit','FontSize',14)
+		else
+			title('click in the middle of the area to be removed, RETURN to exit','FontSize',14)
+		end
+
+		[xi,yi] = ginput(1);
+
+		if ~isempty(xi)
+			%get the closest point
+			%first time, look at all profiles
+			if isempty(points)
+				[profsel indsel]=closestpoint(A,numprofiles,xi,yi);
+				if ((closed(profsel) & length(A(profsel).x)<4) |  (~closed(profsel) & length(A(profsel).x)<3)),
+					disp('the selected profile has less than 3 points, make another selection');
+				else
+					selection=profsel;
+					points(end+1)=indsel;
+					plot(A(profsel).x,A(profsel).y,...
+						'color',getfieldvalue(options,'selectioncolor'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'));
+					text(A(selection).x(indsel),A(selection).y(indsel),num2str(1),'FontSize',14,'background',[0.7 0.7 0.9]);
+				end
+				%disp(['p1= ' num2str(indsel)]),
+			else
+				%get the 2d or 3d point for the given contou
+				[profsel indsel]=closestpoint(A(selection),1,xi,yi);
+				if ismember(indsel,points)
+					disp('the selected points must be distinct')
+				else
+					%second click?
+					if length(points)==1,
+						points(end+1)=indsel;
+						text(A(selection).x(indsel),A(selection).y(indsel),num2str(2),'FontSize',14,'background',[0.7 0.7 0.9]);
+						%disp(['p2= ' num2str(indsel)]),
+					%third click?
+					else
+						p1=points(1); p2=points(2); p3=indsel;
+						%disp(['p3= ' num2str(indsel)]),
+						if p1<p2
+							if p3>p1 & p3<p2
+								A(selection).x(p1+1:p2-1)=[];
+								A(selection).y(p1+1:p2-1)=[];
+								numpoints=numpoints-(p2-p1-1);
+							else
+								A(selection).x=A(selection).x(p1:p2);
+								A(selection).y=A(selection).y(p1:p2);
+								numpoints=numpoints-(numpoints-1-p2)-(p1-1);
+								if closed(selection)
+									%reattach the tips
+									A(selection).x(end+1)=A(selection).x(1);
+									A(selection).y(end+1)=A(selection).y(1);
+									numpoints=numpoints+1;
+								end
+							end
+						else
+							if p3>p2 & p3<p1
+								A(selection).x(p2+1:p1-1)=[];
+								A(selection).y(p2+1:p1-1)=[];
+								numpoints=numpoints-(p1-p2-1);
+							else
+								A(selection).x=A(selection).x(p2:p1);
+								A(selection).y=A(selection).y(p2:p1);
+								numpoints=numpoints-(numpoints-1-p1)-(p2-1);
+								if closed(selection)
+									%reattach the tips
+									A(selection).x(end+1)=A(selection).x(1);
+									A(selection).y(end+1)=A(selection).y(1);
+									numpoints=numpoints+1;
+								end
+							end
+						end
+
+						%plot new profiles
+						undoplots(prevplot);
+						for i=1:numprofiles
+							plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),...
+								'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker',getfieldvalue(options,'Marker'));
+						end
+						points=[];
+
+					end
+				end
+			end
+		else
+			%RETRUN-> quit
+			loop=0;
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/manipulation/undoplots.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/manipulation/undoplots.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/manipulation/undoplots.m	(revision 12996)
@@ -0,0 +1,12 @@
+function  undoplots(prevplot)
+%UNDOPLOTS - undo plots
+%
+%   Usage:undoplots(prevplot)
+
+	%erase all previous plots
+	g=get(gca,'children');
+	L=length(g);
+	for i=1:L-prevplot
+		delete(g(i));
+	end
+end
Index: /issm/trunk-jpl/src/m/Exp/readwrite/expread.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/readwrite/expread.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/readwrite/expread.m	(revision 12996)
@@ -0,0 +1,81 @@
+function Struct=expread(filename);
+%EXPREAD - read a file exp and build a Structure
+%
+%   This routine reads a file .exp and build a Structure containing the 
+%   fields x and y corresponding to the coordinates, one for the filename of
+%   the exp file, for the density, for the nodes, and a field closed to 
+%   indicate if the domain is closed. 
+%   The first argument is the .exp file to be read and the second one (optional) 
+%   indicate if the last point shall be read (1 to read it, 0 not to).
+%
+%   Usage:
+%      Struct=expread(filename)
+%  
+%   Example:
+%      Struct=expread('domainoutline.exp')
+%      Struct=expread('domainoutline.exp')
+%
+%   See also EXPDOC, EXPWRITEASVERTICES
+
+%some checks
+if ~exist(filename),
+	error(['expread error message: file ' filename ' not found!']);
+end
+
+%initialize number of profile
+count=0;
+
+%open file
+fid=fopen(filename,'r');
+
+%loop over the number of profiles
+while (~feof(fid)),
+
+	%update number of profiles
+   count=count+1;
+
+   %Get file name
+	A=fscanf(fid,'%s %s',2);
+	if ~strncmp(A,'##Name:',7), break; end
+	if length(A)>7, 
+		Struct(count).name=A(8:end);
+	else
+		Struct(count).name='';
+	end
+
+	%Get Icon
+	A=fscanf(fid,'%s %s',2);
+	if ~strncmp(A,'##Icon:',6), break; end
+
+	%Get Info
+	A=fscanf(fid,'%s %s %s %s',4);
+	if ~strncmp(A,'#Points',7), break; end
+
+	%Get number of nods and density
+   A=fscanf(fid,'%f %f',[1 2]);
+   Struct(count).nods=A(1);
+   Struct(count).density=A(2);
+
+	%Get Info
+	A=fscanf(fid,'%s %s %s %s',5);
+	if ~strncmp(A,'#XposYpos',9), break; end
+
+	%Get Coordinates
+	A=fscanf(fid,'%f %f',[2 Struct(count).nods]);
+	Struct(count).x=A(1,:)';
+	Struct(count).y=A(2,:)';
+
+	if(Struct(count).nods~=length(Struct(count).x))error(['Profile ' num2str(count) ' reports incorrect length']); end;
+
+	%Check if closed
+	if (Struct(count).nods > 1) && ...
+	   (Struct(count).x(end) == Struct(count).x(1)) && ...
+	   (Struct(count).y(end) == Struct(count).y(1))
+		Struct(count).closed=true;
+	else
+		Struct(count).closed=false;
+	end
+end
+
+%close file
+fclose(fid);
Index: /issm/trunk-jpl/src/m/Exp/readwrite/expwrite.m
===================================================================
--- /issm/trunk-jpl/src/m/Exp/readwrite/expwrite.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Exp/readwrite/expwrite.m	(revision 12996)
@@ -0,0 +1,38 @@
+function expwrite(a,filename);
+%EXPWRITE - write an Argus file from a structure given in input
+%
+%   This routine write an Argus file form a structure containing the fields:
+%   x and y of the coordinates of the points.
+%   The first argument is the structure containing the points coordinates 
+%   and the second one the file to be write.
+%
+%   Usage:
+%      expwrite(a,filename)
+% 
+%   Example:
+%      expwrite(coordstruct,'domainoutline.exp')
+%
+%   See also EXPDOC, EXPREAD, EXPWRITEASVERTICES
+
+fid=fopen(filename,'w');
+for n=1:length(a),
+   
+   if isfield(a,'name'),
+	   if ~isempty(a(n).name),
+		   fprintf(fid,'%s%s\n','## Name:',a(n).name);
+	   else
+		   fprintf(fid,'%s\n','## Name:');
+	   end
+   else
+	   fprintf(fid,'%s\n','## Name:');
+   end
+   
+   fprintf(fid,'%s\n','## Icon:0');
+   fprintf(fid,'%s\n','# Points Count Value');
+   fprintf(fid,'%i %f\n',[length(a(n).x) a(n).density]);
+   fprintf(fid,'%s\n','# X pos Y pos');
+	fprintf(fid,'%10.10f %10.10f\n',[a(n).x a(n).y]');
+	fprintf(fid,'\n','');
+   
+end
+fclose(fid);
Index: /issm/trunk-jpl/src/m/Geometry/FlagElements.m
===================================================================
--- /issm/trunk-jpl/src/m/Geometry/FlagElements.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Geometry/FlagElements.m	(revision 12996)
@@ -0,0 +1,57 @@
+function flag=FlagElements(md,region),
+%FLAGELEMENTS - flag the elements in an region
+%
+%   The region can be given with an exp file, a list of elements.
+%
+%   Usage: 
+%      flag=FlagElements(md,region);
+%
+%   Example:
+%      flag=FlagElements(md,'all');
+%      flag=FlagElements(md,'');
+%      flag=FlagElements(md,'Domain.exp');
+%      flag=FlagElements(md,'~Domain.exp');
+%      flag=FlagElements(md,md.mask.elementongroundedice);
+
+	if ischar(region),
+		if isempty(region),
+			flag=zeros(md.mesh.numberofelements,1);
+			invert=0;
+		elseif strcmpi(region,'all')
+			flag=ones(md.mesh.numberofelements,1);
+			invert=0;
+		else
+			%make sure that we actually don't want the elements outside the domain outline!
+			if strcmpi(region(1),'~'),
+				region=region(2:length(region));
+				invert=1;
+			else
+				invert=0;
+			end
+
+			%does the region domain outline exist or do we have to look for xlim,ylim in basinzoom?
+			if ~exist(region,'file'),
+				if (length(region)>3 & ~strcmp(region(end-3),'.exp')),
+					error(['Error: File ' region ' not found!']);
+				end
+				[xlim,ylim]=basinzoom('basin',region);
+				flag_nodes=double(md.mesh.x<xlim(2) & md.mesh.x>xlim(1) &  md.mesh.y<ylim(2) & md.mesh.y>ylim(1));
+				flag=prod(flag_nodes(md.mesh.elements),2);
+			else
+				%ok, flag elements
+				flag=ContourToMesh(md.mesh.elements(:,1:3),md.mesh.x,md.mesh.y,region,'element',1);
+			end
+		end
+		if invert,
+			flag=~flag;
+		end
+	elseif isfloat(region) | islogical(region),
+		if size(region,1)~=md.mesh.numberofelements,
+			help FlagElements
+			error('Flaglist for region must be of same size as number of elements in model');
+		end
+		flag=region;
+	else
+		error('Invalid region option');
+	end
+end
Index: /issm/trunk-jpl/src/m/Geometry/FlagElements.py
===================================================================
--- /issm/trunk-jpl/src/m/Geometry/FlagElements.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/Geometry/FlagElements.py	(revision 12996)
@@ -0,0 +1,62 @@
+import numpy
+import os
+#from basinzoom import *
+#from ContourToMesh import *
+from MatlabFuncs import *
+
+def FlagElements(md,region):
+	"""
+	FLAGELEMENTS - flag the elements in an region
+
+	   The region can be given with an exp file, a list of elements.
+
+	   Usage: 
+	      flag=FlagElements(md,region);
+
+	   Example:
+	      flag=FlagElements(md,'all');
+	      flag=FlagElements(md,'');
+	      flag=FlagElements(md,'Domain.exp');
+	      flag=FlagElements(md,'~Domain.exp');
+	      flag=FlagElements(md,md.mask.elementongroundedice);
+	"""
+
+	if   isinstance(region,str):
+		if   not region:
+			flag=numpy.zeros(md.mesh.numberofelements,'bool')
+			invert=0
+		elif strcmpi(region,'all'):
+			flag=numpy.ones(md.mesh.numberofelements,'bool')
+			invert=0
+		else:
+			#make sure that we actually don't want the elements outside the domain outline!
+			if strcmpi(region[0],'~'):
+				region=region[1:]
+				invert=1
+			else:
+				invert=0
+
+			#does the region domain outline exist or do we have to look for xlim,ylim in basinzoom?
+			if not os.path.exists(region):
+				if len(region)>3 and not strcmp(region[-4:],'.exp'):
+					raise IOError("Error: File 'region' not found!" % region)
+				xlim,ylim=basinzoom('basin',region)
+				flag_nodes=numpy.logical_and(numpy.logical_and(md.mesh.x<xlim[1],md.mesh.x>xlim[0]),numpy.logical_and(md.mesh.y<ylim[1],md.mesh.y>ylim[0])).astype(float)
+				flag=numpy.prod(flag_nodes[md.mesh.elements],axis=1)
+			else:
+				#ok, flag elements
+				flag=ContourToMesh(md.mesh.elements[:,0:3],md.mesh.x,md.mesh.y,region,'element',1)
+
+		if invert:
+			flag=numpy.logical_not(flag)
+
+	elif isinstance(region,numpy.nparray) or isinstance(region,bool):
+		if not numpy.size(region,0)==md.mesh.numberofelements:
+			raise TypeError("Flaglist for region must be of same size as number of elements in model.")
+		flag=region
+
+	else:
+		raise TypeError("Invalid region option")
+
+	return flag
+
Index: /issm/trunk-jpl/src/m/Geometry/SegIntersect.m
===================================================================
--- /issm/trunk-jpl/src/m/Geometry/SegIntersect.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Geometry/SegIntersect.m	(revision 12996)
@@ -0,0 +1,81 @@
+function bool=SegIntersect(seg1,seg2)
+%SEGINTERSECT - test of segments intersection
+%
+%   return 1 if the two segments intersect
+%   seg1=[x1 y1; x2 y2]
+%   seg2=[x1 y1; x2 y2]
+%
+%   Usage:
+%      bool=SegIntersect(seg1,seg2)
+
+bool=1;
+
+xA=seg1(1,1); yA=seg1(1,2);
+xB=seg1(2,1); yB=seg1(2,2);
+xC=seg2(1,1); yC=seg2(1,2);
+xD=seg2(2,1); yD=seg2(2,2);
+
+O2A=[xA;yA]-[xD/2+xC/2;yD/2+yC/2];
+O2B=[xB;yB]-[xD/2+xC/2;yD/2+yC/2];
+O1C=[xC;yC]-[xA/2+xB/2;yB/2+yA/2];
+O1D=[xD;yD]-[xA/2+xB/2;yB/2+yA/2];
+
+n1=[yA-yB;xB-xA]; %normal vector to segA
+n2=[yC-yD;xD-xC]; %normal vectot to segB
+
+test1=n2'*O2A;
+test2=n2'*O2B;
+
+if test1*test2>0
+	bool=0;
+	return;
+end
+
+test3=n1'*O1C;
+test4=n1'*O1D;
+
+if test3*test4>0
+	bool=0;
+	return;
+end
+
+%if colinear
+if test1*test2==0 & test3*test4==0 & det([n1 n2])==0
+
+	%projection on the axis O1O2
+	O2O1=[xA/2+xB/2;yB/2+yA/2]-[xD/2+xC/2;yD/2+yC/2];
+	O1A=O2O1'*(O2A-O2O1);
+	O1B=O2O1'*(O2B-O2O1);
+	O1C=O2O1'*O1C;
+	O1D=O2O1'*O1D;
+	
+	%test if one point is included in the other segment (->bool=1)
+	if (O1C-O1A)*(O1D-O1A)<0
+		bool=1;
+		return;
+	end
+	if (O1C-O1B)*(O1D-O1B)<0
+		bool=1;
+		return;
+	end
+	if (O1A-O1C)*(O1B-O1C)<0
+		bool=1;
+		return;
+	end
+	if (O1A-O1D)*(O1B-O1D)<0
+		bool=1;
+		return;
+	end
+
+	 %test if the 2 segments have the same middle (->bool=1)
+	if O2O1==0
+		bool=1;
+		return;
+	end
+
+	%else
+	bool=0;
+	return;
+
+end
+
Index: /issm/trunk-jpl/src/m/Geometry/find_point.m
===================================================================
--- /issm/trunk-jpl/src/m/Geometry/find_point.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Geometry/find_point.m	(revision 12996)
@@ -0,0 +1,14 @@
+function f=find_point(tabx,taby,pointx,pointy)
+%FIND_POINT - find closest point
+%
+%   find which point of the list (tabx,taby) is
+%   the closest to (poinx,pointy)
+%
+%   Usage:
+%      f=find_point(tabx,taby,pointx,pointy)
+
+%Compute distance between point and cloud of points
+distance=sqrt((tabx-pointx).^2+(taby-pointy).^2);
+
+%find index of the minimum distance and return the first one only
+f=find(distance==min(min(distance)),1);
Index: /issm/trunk-jpl/src/m/ImageProcessing/im_resize.m
===================================================================
--- /issm/trunk-jpl/src/m/ImageProcessing/im_resize.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/ImageProcessing/im_resize.m	(revision 12996)
@@ -0,0 +1,16 @@
+function newimg = im_resize(img,nw,nh)
+%IM_RESIZE - resize an image using bicubic interpolation
+%
+%   NEWIMG = IM_RESIZE(IMG,NW,NH) Given input image IMG,
+%   returns a new image NEWIMG of size NWxNH.
+%
+% Matthew Dailey 2000
+
+  if nargin ~= 3
+    error('usage: im_resize(image,new_wid,new_ht)');
+  end;
+  
+  ht_scale = size(img,1) / nh;
+  wid_scale = size(img,2) / nw;
+  
+  newimg = interp2(img,(1:nw)*wid_scale,(1:nh)'*ht_scale,'cubic');
Index: /issm/trunk-jpl/src/m/ImageProcessing/immerge.m
===================================================================
--- /issm/trunk-jpl/src/m/ImageProcessing/immerge.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/ImageProcessing/immerge.m	(revision 12996)
@@ -0,0 +1,43 @@
+function out = immerge(bg, fg, coef)
+% Creates an image 'out' of same type as bg.
+% 'out' has 'bg' as background, and 'fg' (transparent, 
+% weighted by 'coef') above 'bg'.
+% Useful when one cannot use OpenGL as renderer, but still 
+% wants to have transparency!
+% 'out', 'bg', and 'fg' are RGB images.
+%
+% merged = immerged(bg, fg, coef)
+%	- bg matrix of type double or uint8
+%	- fg matrix of type double or uint8
+%	- coef is a scalar between 0 and 1, or a matrix of 
+%	  such scalars, same size as 'fg' and 'bg' (AlphaData).
+%
+% Suggestions for future development:
+%	- allow to have 'coef' referring to the AlphaMap
+%	- allow 'coef' to take values between 1 and 64.
+%
+% Gauthier Fleutot 28-07-2004
+% fleutotg@esiee.fr
+
+intOutput = 0;	% if we want the output to be of type integer
+
+if ~isa(bg, 'double')
+	bg = double(bg);	% because '-' isn't defined for uint8
+	intOutput = 1;
+end
+if ~isa(fg, 'double')
+	fg = double(fg);	% because '-' isn't defined for uint8
+end
+
+dif = fg-bg;
+
+if size(coef) == [1 1]
+	out = bg + coef.*dif;
+else
+	coef = cat(3,coef,coef,coef);	% extend the coef matric in the 3rd dim.
+	out = bg + coef .* dif;
+end
+
+if intOutput == 1
+	out = uint8(out);
+end
Index: /issm/trunk-jpl/src/m/ImageProcessing/mean_congrid.m
===================================================================
--- /issm/trunk-jpl/src/m/ImageProcessing/mean_congrid.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/ImageProcessing/mean_congrid.m	(revision 12996)
@@ -0,0 +1,59 @@
+function res=mean_congrid(a,n,choice);
+%MEAN_CONGRID - average the values around a pixel
+%
+%   INPUT a,n,choice, where a is the matrix, and n the size of the area averaged around
+%   one pixel, odd number. choice=1 if the NaN values remain NaN values.
+%
+%   Usage:
+%      res=mean_congrid(a,n,choice)
+
+s=size(a);
+aa=a;
+pos=find(isnan(aa));
+aa(pos)=0;
+
+if (mod(n,2)==0),
+   disp('Cannot rebin, the dimensions of the matrix and n are not compatible');
+   break
+end
+mm=(n-1)/2;
+
+res=zeros(s(1),s(2));
+
+for m=mm+1:s(1)-mm,
+   if mod(m,10)==0,
+      disp(m/s(1)*100);
+   end
+   
+   for l=mm+1:s(2)-mm,
+      
+      
+      if sum(sum(~isnan(a(m-mm:m+mm,l-mm:l+mm))))~=0,
+      res(m,l)=sum(...
+                   sum(...
+                   ~isnan(...
+                          a(m-mm:m+mm,l-mm:l+mm)...
+                          ).*...
+                          aa(m-mm:m+mm,l-mm:l+mm)...
+                       )...
+                   )...
+                   /sum(sum(~isnan(a(m-mm:m+mm,l-mm:l+mm))));
+             else
+                res(m,l)=NaN;
+             end
+             
+   end
+end
+
+if choice==1,
+   pos=find(isnan(a));
+   res(pos)=NaN;
+end
+
+   
+
+
+
+
+
+
Index: /issm/trunk-jpl/src/m/ImageProcessing/rebin.m
===================================================================
--- /issm/trunk-jpl/src/m/ImageProcessing/rebin.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/ImageProcessing/rebin.m	(revision 12996)
@@ -0,0 +1,44 @@
+function res=rebin(a,n);
+%REBIN - average values of a matrix by bloc
+%
+%   INPUT a,n, where a is the matrix, and n the size of the area averaged around
+%   one pixel
+%
+%   Usage:
+%      res=rebin(a,n)
+
+s=size(a);
+
+if (mod(s(1)/n,2)~=0 | mod(s(2)/n,2)~=0),
+   disp('Cannot rebin, the dimensions of the matrix and n are not compatible');
+   break
+end
+
+res=zeros(s(1)/n,s(2)/n);
+
+for m=1:s(1)/n,
+   for l=1:s(2)/n,
+      if sum(sum(~isnan(a((m-1)*n+1:m*n,(l-1)*n+1:l*n))))~=0,
+      res(m,l)=sum(...
+                   sum(...
+                       ~isnan(...
+                              a((m-1)*n+1:m*n,(l-1)*n+1:l*n)...
+                              ).*...
+                       a((m-1)*n+1:m*n,(l-1)*n+1:l*n)...
+                       )...
+                   )...
+                   /sum(sum(~isnan(a((m-1)*n+1:m*n,(l-1)*n+1:l*n))));
+             else
+                res(m,l)=NaN;
+             end
+             
+   end
+end
+
+   
+
+
+
+
+
+
Index: /issm/trunk-jpl/src/m/Interp/FieldFindVarNames.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/FieldFindVarNames.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/FieldFindVarNames.m	(revision 12996)
@@ -0,0 +1,153 @@
+function Names=FieldFindVarNames(filename)
+%FIELDFINDVARNAMES - find names of variables in a data set file
+%
+%   This routines looks at the variables contained in a file and finds out
+%   the names of the variables that are needed for an interpolation (x,y,data)
+%   or (index,x,y,data)
+%
+%   Usage:
+%      Names=FieldFindVarNames(filename)
+%
+%   Example:
+%      Names=FieldFindVarNames('thickness.mat')
+%
+%   See also: INTERPFROMFILE, GRIDDATA
+
+%some checks
+if nargin~=1 | nargout~=1
+	help FieldFindVarNames
+	error('FieldFindVarNames error message: bad usage');
+end
+if ~exist(filename)
+	error(['FieldFindVarNames error message: file ' filename  ' does not exist']);
+end
+
+%Get variables
+A=whos('-file',filename);
+
+%find x,y,vx and vy
+xenum=NaN; yenum=NaN; dataenum=NaN; indexenum=NaN;
+if length(A)==3,
+	isnode=1;
+	for i=1:3
+		if strcmpi(A(i).name(1),'x');
+			xenum=i;
+		elseif strcmpi(A(i).name(1),'y');
+			yenum=i;
+		elseif (strncmpi(A(i).name,filename,3) | strncmpi(A(i).name,'data',4)),
+			dataenum=i;
+		else
+			%nothing
+		end
+	end
+elseif length(A)==4,
+	isnode=0;
+	for i=1:4
+		if strcmpi(A(i).name(1),'x');
+			xenum=i;
+		elseif strcmpi(A(i).name(1),'y');
+			yenum=i;
+		elseif (strncmpi(A(i).name,'index',5) | strncmpi(A(i).name,'elements',7));
+			indexenum=i;
+		elseif (strncmpi(A(i).name,filename,3) | strncmpi(A(i).name,'data',4)),
+			dataenum=i;
+		else
+			%nothing
+		end
+	end
+else
+	error(['FieldFindVarNames error message: file ' filename  ' not supported yet (it should hold 3 variables x,y and data (for nodes) OR 4 variables  x,y,index and data (for mesh))']);
+end
+
+%2: if only one item is missing, find it by elimination
+if ~isnode,
+	pos=find(isnan([xenum yenum indexenum dataenum]));
+	if length(pos)==1,
+		list=[xenum yenum indexenum dataenum]; list(pos)=[];
+		if pos==1,
+			xenum=setdiff(1:4,list);
+		elseif pos==2,
+			yenum=setdiff(1:4,list);
+		elseif pos==3,
+			indexenum=setdiff(1:4,list);
+		elseif pos==4,
+			dataenum=setdiff(1:4,list);
+		end
+	end
+else
+	pos=find(isnan([xenum yenum dataenum]));
+	if length(pos)==1,
+		list=[xenum yenum indexenum dataenum]; list(pos)=[];
+		if pos==1,
+			xenum=setdiff(1:3,list);
+		elseif pos==2,
+			yenum=setdiff(1:3,list);
+		elseif pos==3,
+			dataenum=setdiff(1:3,list);
+		end
+	end
+end
+
+%assum that we have found at least xenum and yenum
+if ( isnan(xenum) | isnan(yenum))
+	error(['FieldFindVarNames error message: file ' filename  ' not supported yet (the coordinates vectors should be named x and y)']);
+end
+
+%find index
+if (~isnode & isnan(indexenum)),
+	for i=1:4
+		lengthi=min(A(i).size);
+		if (lengthi==3),
+			indexenum=i;
+		end
+	end
+	if isnan(indexenum),
+		error(['FieldFindVarNames error message: file ' filename  ' not supported yet (index not found)']);
+	end
+end
+
+%4: last chance
+if ~isnode,
+	pos=find(isnan([xenum yenum indexenum dataenum]));
+	if length(pos)==1,
+		list=[xenum yenum indexenum dataenum]; list(pos)=[];
+		if pos==1,
+			xenum=setdiff(1:4,list);
+		elseif pos==2,
+			yenum=setdiff(1:4,list);
+		elseif pos==3,
+			indexenum=setdiff(1:4,list);
+		elseif pos==4,
+			dataenum=setdiff(1:4,list);
+		end
+	end
+else
+	pos=find(isnan([xenum yenum dataenum]));
+	if length(pos)==1,
+		list=[xenum yenum indexenum dataenum]; list(pos)=[];
+		if pos==1,
+			xenum=setdiff(1:3,list);
+		elseif pos==2,
+			yenum=setdiff(1:3,list);
+		elseif pos==3,
+			dataenum=setdiff(1:3,list);
+		end
+	end
+end
+
+%last check
+if isnan(dataenum)
+	error(['FieldFindVarNames error message: file ' filename  ' not supported yet (data not found)']);
+end
+
+%create output
+Names=struct();
+Names.xname=A(xenum).name;
+Names.yname=A(yenum).name;
+Names.dataname=A(dataenum).name;
+if ~isnode,
+	Names.indexname=A(indexenum).name; 
+	Names.interp='mesh';
+else
+	Names.interp='node';
+end
Index: /issm/trunk-jpl/src/m/Interp/FillHole.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/FillHole.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/FillHole.m	(revision 12996)
@@ -0,0 +1,39 @@
+function field=FillHole(index,x,y,field)
+%FILLHOLE - fill mesh data that has holes in it (hole is defined by field==NaN). Get the nearest neighboors to fill the holes.
+%
+%   Usage:
+%      surface=FillHole(index,x,y,surface)
+%
+%   Example:
+%      md.geometry.surface=FillHole(md.mesh.elements,x,md.mesh.y,md.geometry.surface)
+%
+
+%some checks
+if nargin~=4 | nargout~=1
+	help FillHole
+	error('FillHole error message: bad usage');
+end
+
+if length(x)~=length(y),
+	error('plugdata error message: x and y should have the same length');
+end
+
+
+pos_hole=find(isnan(field));
+pos_full=find(~isnan(field));
+
+%reduce our field to not include any holes: 
+field_noholes=field(pos_full);
+x_noholes=x(pos_full);
+y_noholes=y(pos_full);
+
+for i=1:length(pos_hole)
+
+	if (mod(i,100)==0),
+		fprintf('\b\b\b\b\b\b\b%5.2f%s',i/length(pos_hole)*100,' %');
+	end
+
+	%search the node on the closest to i, that is not in a hole either
+	[d posd]=min(sqrt((x(pos_hole(i))-x_noholes).^2+(y(pos_hole(i))-y_noholes).^2));
+	field(pos_hole(i))=field_noholes(posd);
+end
Index: /issm/trunk-jpl/src/m/Interp/InterpFromFile.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/InterpFromFile.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/InterpFromFile.m	(revision 12996)
@@ -0,0 +1,44 @@
+function data_out=InterpFromFile(x,y,filename,default_value)
+%INTERPFROMFILE - load data and interpolate on the given nodes
+%
+%   load a matlab file (extension .mat) which holds 3 or 4 variables
+%   and interpolate the data on the mesh and plug it onto the model.
+%
+%   o 3 variables
+%     - a vector x (if the name of the variable do not begin with "x", an error can appear)
+%     - a vector y (if the name of the variable do not begin with "y", an error can appear)
+%     - a vector or matrix data (if the name of the variable do not begin with the field name, an error can appear)
+%   o 4 variables
+%     - a vector x (if the name of the variable do not begin with "x", an error can appear)
+%     - a vector y (if the name of the variable do not begin with "y", an error can appear)
+%     - a matrix with 3 columns (if the name of the variable do not begin with "index" or "elements", an error can appear)
+%     - a vector data (if the name of the variable do not begin with the field name, an error can appear)
+%
+%   Usage:
+%      data=InterpFromFile(x,y,filename,default_value);
+%
+%   Example:
+%      md.geometry.surface=InterpFromFile(md.mesh.x,md.mesh.y,'surfacefile.mat',0);
+%
+%   See also: PLUGVELOCITIES, INTERPFROMGRID, INTERPFROMMESH2D, INTERPFROMMESH3D
+
+%some checks
+if nargin~=4 | nargout~=1
+	help InterpFromFile
+	error('plugdata error message: bad usage');
+end
+if ~exist(filename)
+	error(['plugdata error message: file ' filename  ' does not exist']);
+end
+if length(x)~=length(y),
+	error('plugdata error message: x and y should have the same length');
+end
+
+%load file
+Names=FieldFindVarNames(filename);
+Data=load(filename);
+if strcmpi(Names.interp,'node'),
+	data_out=InterpFromGridToMesh(Data.(Names.xname),Data.(Names.yname),Data.(Names.dataname),x,y,default_value);
+else
+	data_out=InterpFromMeshToMesh2d(Data.(Names.indexname),Data.(Names.xname),Data.(Names.yname),Data.(Names.dataname),x,y);
+end
Index: /issm/trunk-jpl/src/m/Interp/PatchToVec.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/PatchToVec.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/PatchToVec.m	(revision 12996)
@@ -0,0 +1,21 @@
+function vec=PatchToVec(Patch);
+%PATCHTOVEC - converts a patch to a vector by averaging over each vertex
+%
+%   Usage:
+%      vec=PatchToVec(Patch)
+
+%if the patch is P0: we have element values, return an element vector
+switch(size(Patch.value,2)),
+	case 1,
+		vec(Patch.element)=Patch.value;
+	case 3,
+		connectivity=sparse(Patch.index(:),1,1);
+		value       =sparse(Patch.index(:),1,Patch.value(:));
+		vec=full(value./connectivity);
+	case 6,
+		connectivity=sparse(Patch.index(:),1,1);
+		value       =sparse(Patch.index(:),1,Patch.value(:));
+		vec=full(value./connectivity);
+	otherwise,
+		error('interpolation not supported yet');
+	end
Index: /issm/trunk-jpl/src/m/Interp/VelFindVarNames.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/VelFindVarNames.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/VelFindVarNames.m	(revision 12996)
@@ -0,0 +1,122 @@
+function Names=VelFindVarNames(filename)
+%VELFINDVARNAMES - find names of variables in a velocity data set file
+%
+%   This routines looks at the variables contained in a file and finds out
+%   the names of the variables that are needed for an interpolation (x,y,vx,vy)
+%   or (index,x,y,vx,vy)
+%
+%   Usage:
+%      Names=VelFindVarNames(filename)
+%
+%   Example:
+%      Names=VelFindVarNames('velocities.mat')
+%
+%   See also: INTERPFROMFILE, GRIDDATA
+
+%some checks
+if nargin~=1 | nargout~=1
+	help VelFindVarNames
+	error('VelFindVarNames error message: bad usage');
+end
+if ~exist(filename)
+	error(['VelFindVarNames error message: file ' filename  ' does not exist']);
+end
+
+%Get variables
+A=whos('-file',filename);
+
+%find x,y,vx and vy
+xenum=NaN; yenum=NaN; vxenum=NaN; vyenum=NaN; indexenum=NaN;
+if length(A)==4,
+	isnode=1;
+	for i=1:4
+		if strcmpi(A(i).name(1),'x');
+			xenum=i;
+		elseif strcmpi(A(i).name(1),'y');
+			yenum=i;
+		else
+			if (strcmpi(A(i).name(end),'x') | strncmpi(A(i).name,'vx',2));
+				vxenum=i;
+			elseif (strcmpi(A(i).name(end),'y') | strncmpi(A(i).name,'vy',2));
+				vyenum=i;
+			end
+		end
+	end
+elseif length(A)==5,
+	isnode=0;
+	for i=1:5
+		if strcmpi(A(i).name(1),'x');
+			xenum=i;
+		elseif strcmpi(A(i).name(1),'y');
+			yenum=i;
+		elseif (strcmpi(A(i).name(1),'index') | strcmpi(A(i).name(1),'elements'));
+			indexenum=i;
+		else
+			if (strcmpi(A(i).name(end),'x') | strncmpi(A(i).name,'vx',2));
+				vxenum=i;
+			elseif (strcmpi(A(i).name(end),'y') | strncmpi(A(i).name,'vy',2));
+				vyenum=i;
+			end
+		end
+	end
+else
+	error(['VelFindVarNames error message: file ' filename  ' not supported yet (it should hold 4 variables x,y,vx and vy (for nodes) OR 5 variables  x,y,index,vx and vy (for mesh))']);
+end
+
+%assum that we have found at least vxenum and vyenum
+if ( isnan(vxenum) | isnan(vyenum))
+	error(['VelFindVarNames error message: file ' filename  ' not supported yet (the velocities should be named vx and vy)']);
+end
+
+%find index
+if (~isnode & isnan(indexenum)),
+	for i=1:5
+		lengthi=min(A(i).size);
+		if (lengthi==3),
+			indexenum=i;
+		end
+	end
+	if isnan(indexenum),
+		error(['VelFindVarNames error message: file ' filename  ' not supported yet (index not found)']);
+	end
+end
+
+%find x y
+if (isnan(xenum) | isnan(yenum))
+
+	%check the size
+	if A(vxenum).size(1)==A(vxenum).size(2),
+		error(['VelFindVarNames error message: file ' filename  ' not supported (velocities is a square matrix, save x and y with another name)']);
+	end
+	if ~(A(vxenum).size(1)==A(vyenum).size(1) & A(vxenum).size(2)==A(vyenum).size(2)),
+		error(['VelFindVarNames error message: file ' filename  ' not supported (vx and vy matrices do not have the same size)']);
+	end
+
+	%find xenum and yenum
+	for i=1:4
+		lengthi=max(A(i).size);
+		if ((i~=vxenum) & (lengthi==A(vxenum).size(1) | lengthi==A(vxenum).size(1)+1)),
+			yenum=i;
+		elseif ((i~=vxenum) & (lengthi==A(vxenum).size(2) | lengthi==A(vxenum).size(2)+1)),
+			xenum=i;
+		end
+	end
+
+	%last check
+	if (isnan(xenum) | isnan(yenum))
+		error(['plugdata error message: file ' filename  ' not supported yet']);
+	end
+end
+
+%create output
+Names=struct();
+Names.xname=A(xenum).name;
+Names.yname=A(yenum).name;
+Names.vxname=A(vxenum).name;
+Names.vyname=A(vyenum).name;
+if ~isnode,
+	Names.indexname=A(indexenum).name; 
+	Names.interp='mesh';
+else
+	Names.interp='node';
+end
Index: /issm/trunk-jpl/src/m/Interp/plugvelocities.m
===================================================================
--- /issm/trunk-jpl/src/m/Interp/plugvelocities.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Interp/plugvelocities.m	(revision 12996)
@@ -0,0 +1,41 @@
+function md=plugvelocities(md,filename,default_value)
+%PLUGVELOCITIES - load velocities on a model
+%
+%   load a matlab file (extension .mat) which holds 4 variables
+%   x,y,vx,vy to be plugged onto the model (or similar names)
+%   x and y must be vectors, vx, vy matrices
+%
+%   Usage:
+%      md=plugvelocities(md,filename,default_value)
+%
+%   Example:
+%      md=plugvelocities(md,'velocityfile.mat',0);
+%
+%   See also: INTERPFROMFILE, GRIDDATA
+
+%some checks
+if nargin~=3 | nargout~=1
+	help plugvelocities
+	error('plugvelocities error message: bad usage');
+end
+if ~exist(filename)
+	error(['plugvelocities error message: file ' filename  ' does not exist']);
+end
+
+%load velocities 
+Names=VelFindVarNames(filename);
+Vel=load(filename);
+
+%Interpolation
+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,default_value);
+	md.inversion.vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,default_value);
+else
+	md.inversion.vx_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,default_value);
+	md.inversion.vy_obs=InterpFromMeshToMesh2d(Vel.(Names.indexname),Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,default_value);
+end
+
+md.inversion.vel_obs=sqrt(md.inversion.vx_obs.^2+md.inversion.vy_obs.^2);
+md.initialization.vx=md.inversion.vx_obs;
+md.initialization.vy=md.inversion.vy_obs;
+md.initialization.vel=md.inversion.vel_obs;
Index: /issm/trunk-jpl/src/m/Kml/exp2kml.m
===================================================================
--- /issm/trunk-jpl/src/m/Kml/exp2kml.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Kml/exp2kml.m	(revision 12996)
@@ -0,0 +1,19 @@
+function exp2kml(input,output)
+%EXP2KML: transform Argus exp file to kml
+%
+% Usage:    exp2kml('temp.exp','temp2.kml')
+%
+%
+
+
+%First, read exp file
+domain=expread(input);
+
+
+%then transform: 
+string=ge_plot(domain.x,domain.y,'name',domain.name);
+
+%open kml file for writing: 
+fid=fopen(output,'w');
+fprintf(fid,'%s',string);
+fclose(fid);
Index: /issm/trunk-jpl/src/m/Kml/kml2exp.m
===================================================================
--- /issm/trunk-jpl/src/m/Kml/kml2exp.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Kml/kml2exp.m	(revision 12996)
@@ -0,0 +1,29 @@
+function kml2exp(input,output)
+%KML2EXP: transform kml file Argus exp file.
+%
+% Usage:    kmltoexp('temp.kml','temp2.exp')
+%
+%
+
+
+
+
+%First, read polygon kml file.
+structure=kml_shapefile(input);
+	
+%create exp file: 
+domain=struct();
+for i=1:length(structure),
+
+	if isfield(structure,'name'),
+		domain(end+1).name=structure(i).name;
+	else
+		domain(end+1).name='NaN';
+	end
+
+	domain(end).density=1;
+	domain(end).x=structure(i).X;
+	domain(end).y=structure(i).Y;
+end
+domain=domain(2:end);
+expwrite(domain,output);
Index: /issm/trunk-jpl/src/m/Kml/kml2expg.m
===================================================================
--- /issm/trunk-jpl/src/m/Kml/kml2expg.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Kml/kml2expg.m	(revision 12996)
@@ -0,0 +1,13 @@
+function kml2expg(filename)
+
+	[path,name,ext]=fileparts(filename);
+
+	if strcmpi(ext,'.kmz'),
+		eval(['!unzip ' filename]);
+		eval(['!mv doc.kml ' name '.kml']);
+		kml2exp([name '.kml'],[name '.exp']);
+		expll2xy([name '.exp'],1);
+	end
+
+	kml2exp([name '.kml'],[name '.exp']);
+	expll2xy([name '.exp'],1);
Index: /issm/trunk-jpl/src/m/LatLong/ll2xy.m
===================================================================
--- /issm/trunk-jpl/src/m/LatLong/ll2xy.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/LatLong/ll2xy.m	(revision 12996)
@@ -0,0 +1,66 @@
+function [x,y] = ll2xy(lat,lon,sgn,central_meridian,standard_parallel)  
+%LL2XY - converts lat long to polar stereographic
+%
+%   Converts from geodetic latitude and longitude to Polar 
+%   Stereographic (X,Y) coordinates for the polar regions.
+%   Author: Michael P. Schodlok, December 2003 (map2ll)
+%
+%   Usage:
+%      [x,y] = ll2xy(lat,lon,sgn)
+%      [x,y] = ll2xy(lat,lon,sgn,central_meridian,standard_parallel)
+%
+%      - sgn = Sign of latitude +1 : north latitude (default is mer=45 lat=70)
+%                               -1 : south latitude (default is mer=0  lat=71)
+
+%Get central_meridian and standard_parallel depending on hemisphere
+if nargin==5,
+	delta = central_meridian;
+	slat  = standard_parallel;
+elseif nargin==3
+	if sgn == 1,
+		delta = 45; slat = 70;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+	elseif sgn==-1,
+		delta = 0;  slat = 71;
+		disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)');
+	else
+		error('Sign should be either +1 or -1');
+	end
+else
+	help ll2xy
+	error('bad usage');
+end
+
+% Conversion constant from degrees to radians
+cde  = 57.29577951;
+% Radius of the earth in meters
+re   = 6378.273*10^3;
+% Eccentricity of the Hughes ellipsoid squared
+ex2   = .006693883;
+% Eccentricity of the Hughes ellipsoid
+ex    =  sqrt(ex2);
+
+latitude  = abs(lat) * pi/180.;
+longitude = (lon + delta) * pi/180.;
+
+% compute X and Y in grid coordinates.
+T = tan(pi/4-latitude/2) ./ ((1-ex*sin(latitude))./(1+ex*sin(latitude))).^(ex/2);
+
+if (90 - slat) <  1.e-5 
+	rho = 2.*re*T/sqrt((1.+ex)^(1.+ex)*(1.-ex)^(1.-ex));
+else
+	sl  = slat*pi/180.;
+	tc  = tan(pi/4.-sl/2.)/((1.-ex*sin(sl))/(1.+ex*sin(sl)))^(ex/2.);
+	mc  = cos(sl)/sqrt(1.0-ex2*(sin(sl)^2));
+	rho = re*mc*T/tc;
+end
+
+y = -rho .* sgn .* cos(sgn.*longitude);
+x =  rho .* sgn .* sin(sgn.*longitude);
+
+[cnt1,cnt2] = find(latitude >= pi / 2.);
+
+if cnt1
+	x(cnt1,1) = 0.0;
+	y(cnt1,1) = 0.0;
+end
Index: /issm/trunk-jpl/src/m/LatLong/pargenerate.m
===================================================================
--- /issm/trunk-jpl/src/m/LatLong/pargenerate.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/LatLong/pargenerate.m	(revision 12996)
@@ -0,0 +1,45 @@
+function pargenerate(filename,xm,ym,data,varargin)
+%PARGENERATE - generate parameter file for images ala Rignot
+%
+%   Usage: 
+%      pargenerate(filename,data,xm,ym,options);
+%
+%   Supported options:
+%      - title: dataset title
+%      - latitude: standard latitude (degree)
+%      - meridian: meridian (degree)
+%      - format: binary format
+
+%process options
+options=pairoptions(varargin{:});
+Title=getfieldvalue(options,'title','N/A');
+latitude=getfieldvalue(options,'latitude','N/A');
+meridian=getfieldvalue(options,'meridian','N/A');
+format=getfieldvalue(options,'format','single');
+
+%Get data info
+[nlines ncols]=size(data);
+xmin=min(xm);
+ymax=max(ym);
+postx=abs(xm(2)-xm(1));
+posty=abs(ym(2)-ym(1));
+
+%Open header file and get machine type
+fid=fopen(filename,'wt');
+[filename, permission, machineformat, encoding] = fopen(fid);
+
+%write header file
+fprintf(fid,'%s\n','ISSM gridded dataset parameter file');
+fprintf(fid,'%s%s\n','title: ',Title);
+fprintf(fid,'%s  \n','DEM_projection: PS');
+fprintf(fid,'%s%s\n','data_format: ',format);
+fprintf(fid,'%s%s\n','endian:      ',machineformat);
+fprintf(fid,'%s%d\n','width:  ',ncols);
+fprintf(fid,'%s%d\n','nlines: ',nlines);
+fprintf(fid,'%s%g%s\n','PS_secant_lat:    ',latitude,'   decimal degrees');
+fprintf(fid,'%s%g%s\n','PS_meridian_long: ',meridian,'   decimal degrees');
+fprintf(fid,'%s%-15.10g\n','PS_corner_north:  ',ymax);
+fprintf(fid,'%s%-15.10g\n','PS_corner_east:   ',xmin);
+fprintf(fid,'%s%g%s\n','PS_post_north:    ',postx,' m');
+fprintf(fid,'%s%g%s\n','PS_post_east:     ',posty,' m');
+fclose(fid);
Index: /issm/trunk-jpl/src/m/LatLong/utm2ll.m
===================================================================
--- /issm/trunk-jpl/src/m/LatLong/utm2ll.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/LatLong/utm2ll.m	(revision 12996)
@@ -0,0 +1,117 @@
+function  [Lat,Lon] = utm2ll(xx,yy,utmzone)
+% -------------------------------------------------------------------------
+% [Lat,Lon] = utm2ll(x,y,utmzone)
+%
+% Description: Function to convert vectors of UTM coordinates into Lat/Lon vectors (WGS84).
+% Some code has been extracted from UTMIP.m function by Gabriel Ruiz Martinez.
+%
+% Inputs:on)
+%    -3.485713    7.801235 -119.955246  -17.759537  -94.799019  121.640266
+%
+% Example 2: If you need Lat/Lon coordinates in Degrees, Minutes and Seconds
+% [Lat, Lon]=utm2ll(x,y,utmzone);
+% LatDMS=dms2mat(deg2dms(Lat))
+%LatDMS =
+%    40.00         18.00         55.55
+%    46.00         17.00          2.01
+%    37.00         34.00         40.17
+%    28.00         38.00         44.33
+%    38.00         51.00         19.96
+%    25.00          3.00         42.41
+% LonDMS=dms2mat(deg2dms(Lon))
+%LonDMS =
+%    -3.00         29.00          8.61
+%     7.00         48.00          4.40
+%  -119.00         57.00         18.93
+%   -17.00         45.00         34.33
+%   -94.00         47.00         56.47
+%   121.00         38.00         24.96
+%
+% Author:
+%   Rafael Palacios
+%   Universidad Pontificia Comillas
+%   Madrid, Spain
+% Version: Apr/06, Jun/06, Aug/06
+% Aug/06: corrected m-Lint warnings
+%-------------------------------------------------------------------------
+
+% Argument checking
+%
+error(nargchk(3, 3, nargin)); %3 arguments required
+n1=length(xx);
+n2=length(yy);
+n3=size(utmzone,1);
+if (n1~=n2 || n1~=n3)
+	error('x,y and utmzone vectors should have the same number or rows');
+end
+c=size(utmzone,2);
+if (c~=4)
+	error('utmzone should be a vector of strings like "30 T"');
+end
+
+% Memory pre-allocation
+%
+Lat=zeros(n1,1);
+Lon=zeros(n1,1);
+
+% Main Loop
+%
+for i=1:n1
+	if (utmzone(i,4)>'X' || utmzone(i,4)<'C')
+		fprintf('utm2ll: Warning utmzone should be a vector of strings like "30 T", not "30 t"\n');
+	end
+	if (utmzone(i,4)>'M')
+		hemis='N';   % Northern hemisphere
+	else
+		hemis='S';
+	end
+
+	x=xx(i);
+	y=yy(i);
+	zone=str2double(utmzone(i,1:2));
+
+	sa = 6378137.000000 ; sb = 6356752.314245;
+
+	%   e = ( ( ( sa ^ 2 ) - ( sb ^ 2 ) ) ^ 0.5 ) / sa;
+	e2 = ( ( ( sa ^ 2 ) - ( sb ^ 2 ) ) ^ 0.5 ) / sb;
+	e2cuadrada = e2 ^ 2;
+	c = ( sa ^ 2 ) / sb;
+	%   alpha = ( sa - sb ) / sa;             %f
+	%   ablandamiento = 1 / alpha;   % 1/f
+
+	X = x - 500000;
+
+	if hemis == 'S' || hemis == 's'
+		Y = y - 10000000;
+	else
+		Y = y;
+	end
+
+	S = ( ( zone * 6 ) - 183 );
+	lat =  Y / ( 6366197.724 * 0.9996 );
+	v = ( c / ( ( 1 + ( e2cuadrada * ( cos(lat) ) ^ 2 ) ) ) ^ 0.5 ) * 0.9996;
+	a = X / v;
+	a1 = sin( 2 * lat );
+	a2 = a1 * ( cos(lat) ) ^ 2;
+	j2 = lat + ( a1 / 2 );
+	j4 = ( ( 3 * j2 ) + a2 ) / 4;
+	j6 = ( ( 5 * j4 ) + ( a2 * ( cos(lat) ) ^ 2) ) / 3;
+	alfa = ( 3 / 4 ) * e2cuadrada;
+	beta = ( 5 / 3 ) * alfa ^ 2;
+	gama = ( 35 / 27 ) * alfa ^ 3;
+	Bm = 0.9996 * c * ( lat - alfa * j2 + beta * j4 - gama * j6 );
+	b = ( Y - Bm ) / v;
+	Epsi = ( ( e2cuadrada * a^ 2 ) / 2 ) * ( cos(lat) )^ 2;
+	Eps = a * ( 1 - ( Epsi / 3 ) );
+	nab = ( b * ( 1 - Epsi ) ) + lat;
+	senoheps = ( exp(Eps) - exp(-Eps) ) / 2;
+	Delt = atan(senoheps / (cos(nab) ) );
+	TaO = atan(cos(Delt) * tan(nab));
+	longitude = (Delt *(180 / pi ) ) + S;
+	latitude = ( lat + ( 1 + e2cuadrada* (cos(lat)^ 2) - ( 3 / 2 ) * e2cuadrada * sin(lat) * cos(lat) * ( TaO - lat ) ) * ( TaO - lat ) ) * ...
+		(180 / pi);
+
+	Lat(i)=latitude;
+	Lon(i)=longitude;
+
+end
Index: /issm/trunk-jpl/src/m/LatLong/xy2ll.m
===================================================================
--- /issm/trunk-jpl/src/m/LatLong/xy2ll.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/LatLong/xy2ll.m	(revision 12996)
@@ -0,0 +1,72 @@
+function [lat,lon] = xy2ll(x,y,sgn,central_meridian,standard_parallel)
+%XY2LL - converts xy to lat long
+%
+%   Converts Polar  Stereographic (X,Y) coordinates for the polar regions to
+%   latitude and longitude Stereographic (X,Y) coordinates for the polar
+%   regions.
+%   Author: Michael P. Schodlok, December 2003 (map2xy.m)
+%
+%   Usage:
+%      [lat,lon] = xy2ll(x,y,sgn);
+%      [lat,lon] = xy2ll(x,y,sgn,central_meridian,standard_parallel);
+%
+%      - sgn = Sign of latitude +1 : north latitude (default is mer=45 lat=70)
+%                               -1 : south latitude (default is mer=0  lat=71)
+
+%Get central_meridian and standard_parallel depending on hemisphere
+if nargin==5,
+	delta = central_meridian;
+	slat  = standard_parallel;
+elseif nargin==3
+	if sgn == 1,
+		delta = 45; slat = 70;
+		disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)');
+	elseif sgn==-1,
+		delta = 0;  slat = 71;
+		disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)');
+	else
+		error('Sign should be either +1 or -1');
+	end
+else
+	help xy2ll
+	error('bad usage');
+end
+
+% Conversion constant from degrees to radians
+cde  = 57.29577951;
+% Radius of the earth in meters
+re   = 6378.273*10^3;
+% Eccentricity of the Hughes ellipsoid squared
+ex2   = .006693883;
+% Eccentricity of the Hughes ellipsoid
+ex    =  sqrt(ex2);
+
+sl  = slat*pi/180.;
+rho = sqrt(x.^2 + y.^2);
+cm = cos(sl) / sqrt(1.0 - ex2 * (sin(sl)^2));
+T = tan((pi / 4.0) - (sl / 2.0)) / ((1.0 - ex * sin(sl)) / (1.0 + ex * sin(sl)))^(ex / 2.0);
+
+if  abs(slat-90.) < 1.e-5
+	T = rho * sqrt((1. + ex)^(1. + ex) * (1. - ex)^(1. - ex)) / 2. / re;
+else
+	T = rho * T / (re * cm);
+end
+
+chi = (pi / 2.0) - 2.0 * atan(T);
+lat = chi + ((ex2 / 2.0) + (5.0 * ex2^2.0 / 24.0) + (ex2^3.0 / 12.0)) * ...
+	sin(2 * chi) + ((7.0 * ex2^2.0 / 48.0) + (29.0 * ex2^3 / 240.0)) * ...
+	sin(4.0 * chi) + (7.0 * ex2^3.0 / 120.0) * sin(6.0 * chi) ;
+
+lat = sgn * lat;
+lon = atan2(sgn * x,-sgn * y);
+lon = sgn * lon;
+
+[res1,res2] = find(rho <= 0.1);
+if res1
+	lat(res1,1) = 90. * sgn;
+	lon(res1,1) = 0.0;
+end
+
+lon = lon * 180. / pi;
+lat = lat * 180. / pi;
+lon = lon - delta; 
Index: /issm/trunk-jpl/src/m/Math/fixdec.m
===================================================================
--- /issm/trunk-jpl/src/m/Math/fixdec.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Math/fixdec.m	(revision 12996)
@@ -0,0 +1,41 @@
+function y = fixdec(x, n)
+%FIXDEC -  Round towards zero with a specified number of decimals.
+%
+%   This routine rounds the elements of X to N decimals.
+%
+%   Usage:
+%      y = fixdec(x, n)
+%
+%   Example:
+%      fixdec(10*sqrt(2) + i*pi/10, 4) returns 14.1421 + 0.3141i
+%
+%   See also: FIX, FLOOR, CEIL, ROUND, FIXDIG, ROUNDDEC, ROUNDDIG.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2004-09-22 20:08:10 +0200
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   % Check number of input arguments.
+   error(nargchk(2, 2, nargin));
+
+   % Quick exit if either argument is empty.
+   if (isempty(x) |isempty(n))
+      y = [];
+      return
+   end
+
+   % Get size of input arguments.
+   size_x   = size(x);
+   size_n   = size(n);
+   scalar_x = all(size_x == 1);           % True if x is a scalar.
+   scalar_n = all(size_n == 1);           % True if n is a scalar.
+
+   % Check size of input arguments.
+   if ~scalar_x & ~scalar_n & ~isequal(size_x, size_n)
+      error(['When both arguments are non-scalars they must have' ...
+             ' the same size']);
+   end
+
+   f = 10.^n;
+   y = fix(x .* f) ./ f;
Index: /issm/trunk-jpl/src/m/Math/isnans.m
===================================================================
--- /issm/trunk-jpl/src/m/Math/isnans.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Math/isnans.m	(revision 12996)
@@ -0,0 +1,15 @@
+function returnvalue=isnans(array)
+%ISNANS: figure out if an array is nan. wrapper to isnan from matlab which stupidly does not allow this test  for structures!
+%
+%  Usage:    isnans(array)
+%
+%  See also : ISNAN 
+
+
+if isstruct(array), 
+	returnvalue=0;
+elseif iscell(array)
+	returnvalue=0;
+else
+	returnvalue=isnan(array);
+end
Index: /issm/trunk-jpl/src/m/Math/isnans.py
===================================================================
--- /issm/trunk-jpl/src/m/Math/isnans.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/Math/isnans.py	(revision 12996)
@@ -0,0 +1,18 @@
+import numpy
+
+def isnans(array):
+	"""
+	ISNANS: figure out if an array is nan. wrapper to isnan from matlab which stupidly does not allow this test  for structures!
+
+	   Usage:    isnans(array)
+
+	      See also : ISNAN 
+	"""
+
+	if   isinstance(array,(tuple,list,dict)): 
+		returnvalue=0
+	else:
+		returnvalue=numpy.isnan(array)
+
+	return returnvalue
+
Index: /issm/trunk-jpl/src/m/Math/round_ice.m
===================================================================
--- /issm/trunk-jpl/src/m/Math/round_ice.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Math/round_ice.m	(revision 12996)
@@ -0,0 +1,38 @@
+function new_x=round_ice(x,numnonzeros)
+%ROUND_ICE - rounds up x so that it has only numnonzeros non zero digits
+%
+%   numnonzeros must be an integer larger or equal to 1
+%
+%   Usage:
+%      new_x=round_ice(x,numnonzeros)
+
+%some checks
+if (nargin ~=2 | nargout>1),
+	error('round_ice usage: new_x=round_ice(x,numonzeros)');
+end
+if ~isnumeric(x)
+	error('round_ice error message: x must be a number and numzeros an integer');
+end
+if round(numnonzeros)~=numnonzeros
+	error('round_ice error message: numnonzeros must be an integer larger or equal to 1')
+end
+if any(numnonzeros<1)
+	error('round_ice error message: numnonzeros must be an integer larger or equal to 1')
+end
+if (length(numnonzeros)~=1 & size(numnonzeros)~=size(x))
+	error('round_ice error message: numnonzeros must be an integer larger or equal to 1 or a list of integers of length length(x)')
+end
+
+%figure out how long x is
+lengthx=ceil(log10(abs(x)));
+
+%if x contains 0, lengthx=-Inf
+lengthx(isinf(lengthx))=1;
+
+%get its sign
+si=sign(x);
+
+%rule out zeros
+new_x=si.*round(abs(x).*10.^(-lengthx+numnonzeros)).*10.^(lengthx-numnonzeros);
+
+
Index: /issm/trunk-jpl/src/m/Meca/carter.m
===================================================================
--- /issm/trunk-jpl/src/m/Meca/carter.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Meca/carter.m	(revision 12996)
@@ -0,0 +1,28 @@
+function attenuation=carter(temperature)
+%CARTER - attenuation as a function of temperature
+%
+%   TWO WAY - Attenuation (in dB/m) as a function of temperature (K)
+%   From Carter at al. 2007 (Radar-based subglacial lake classification in Antarctica)
+%   Figure 4
+%
+%   Usage:
+%      attenuation=carter(temperature)
+
+if(temperature<0)
+	error('input temperature should be in Kelvin (positive)');
+end
+T=temperature-273.15;
+
+Temp=[-50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0]';
+A=[0.0015 0.002 0.003 0.0042 0.0055 0.0083 0.012 0.0175 0.026 0.038 0.055]';
+
+%Now, do a cubic fit between Temp and B: 
+[cfun,gof,output]=fit(Temp,A,'cubicspline');
+%breaks=cfun.p.breaks;
+%coeff=cfun.p.coefs;
+
+%Calculate attenuation
+attenuation=cfun(T);
+
+%Make it a 2 way attenuation
+attenuation=2*attenuation;
Index: /issm/trunk-jpl/src/m/Meca/lithostaticpressure.m
===================================================================
--- /issm/trunk-jpl/src/m/Meca/lithostaticpressure.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Meca/lithostaticpressure.m	(revision 12996)
@@ -0,0 +1,7 @@
+function pressure=lithostaticpressure(rho_ice,g,s,z);
+%LITHOSTATICPRESSURE - compute the lithostatic pressure
+%
+%   Usage:
+%      pressure=lithostacticpressure(rho_ice,g,surface,z)
+
+pressure=rho_ice*g*(s-z);
Index: /issm/trunk-jpl/src/m/Meca/paterson.m
===================================================================
--- /issm/trunk-jpl/src/m/Meca/paterson.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Meca/paterson.m	(revision 12996)
@@ -0,0 +1,42 @@
+function rigidity=paterson(temperature)
+%PATERSON - figure out the rigidity of ice for a given temperature
+%
+%   rigidigty (in s^(1/3)Pa) is the flow law paramter in the flow law sigma=B*e(1/3) (Paterson, p97). 
+%   temperature is in Kelvin degrees
+%
+%   Usage:
+%      rigidity=paterson(temperature)
+
+if(temperature<0)
+	error('input temperature should be in Kelvin (positive)');
+end
+T=temperature-273.15;
+
+%The routine below is equivalent to:
+
+% n=3; T=temperature-273;
+% %From paterson,
+% Temp=[0;-2;-5;-10;-15;-20;-25;-30;-35;-40;-45;-50];
+% A=[6.8*10^-15;2.4*10^-15;1.6*10^-15;4.9*10^-16;2.9*10^-16;1.7*10^-16;9.4*
+% 10^-17;5.1*10^-17;2.7*10^-17;1.4*10^-17;7.3*10^-18;3.6*10^-18];;%s-1(kPa-3)
+% %Convert into rigidity B
+% B=A.^(-1/n)*10^3; %s^(1/3)Pa
+% %Now, do a cubic fit between Temp and B: 
+% fittedmodel=fit(Temp,B,'cubicspline');
+% rigidity=fittedmodel(temperature);
+
+rigidity=zeros(length(T),1);
+pos1=find(T<=-45);           rigidity(pos1)=10^8*(-0.000292866376675*(T(pos1)+50).^3+ 0.011672640664130*(T(pos1)+50).^2  -0.325004442485481*(T(pos1)+50)+  6.524779401948101);
+pos2=find(-45<=T & T<-40);   rigidity(pos2)=10^8*(-0.000292866376675*(T(pos2)+45).^3+ 0.007279645014004*(T(pos2)+45).^2  -0.230243014094813*(T(pos2)+45)+  5.154964909039554);
+pos3=find(-40<=T & T<-35);   rigidity(pos3)=10^8*(0.000072737147457*(T(pos3)+40).^3+  0.002886649363879*(T(pos3)+40).^2  -0.179411542205399*(T(pos3)+40)+  4.149132666831214);
+pos4=find(-35<=T & T<-30);   rigidity(pos4)=10^8*(-0.000086144770023*(T(pos4)+35).^3+ 0.003977706575736*(T(pos4)+35).^2  -0.145089762507325*(T(pos4)+35)+  3.333333333333331);
+pos5=find(-30<=T & T<-25);   rigidity(pos5)=10^8*(-0.000043984685769*(T(pos5)+30).^3+ 0.002685535025386*(T(pos5)+30).^2  -0.111773554501713*(T(pos5)+30)+  2.696559088937191);
+pos6=find(-25<=T & T<-20);   rigidity(pos6)=10^8*(-0.000029799523463*(T(pos6)+25).^3+ 0.002025764738854*(T(pos6)+25).^2  -0.088217055680511*(T(pos6)+25)+  2.199331606342181);
+pos7=find(-20<=T & T<-15);   rigidity(pos7)=10^8*(0.000136920904777*(T(pos7)+20).^3+  0.001578771886910*(T(pos7)+20).^2  -0.070194372551690*(T(pos7)+20)+  1.805165505978111);
+pos8=find(-15<=T & T<-10);   rigidity(pos8)=10^8*(-0.000899763781026*(T(pos8)+15).^3+ 0.003632585458564*(T(pos8)+15).^2  -0.044137585824322*(T(pos8)+15)+  1.510778053489523);
+pos9=find(-10<=T & T<-5);    rigidity(pos9)=10^8*(0.001676964325070*(T(pos9)+10).^3-  0.009863871256831*(T(pos9)+10).^2  -0.075294014815659*(T(pos9)+10)+  1.268434288203714);
+pos10=find(-5<=T & T<-2);    rigidity(pos10)=10^8*(-0.003748937622487*(T(pos10)+5).^3+0.015290593619213*(T(pos10)+5).^2  -0.048160403003748*(T(pos10)+5)+  0.854987973338348);
+pos11=find(-2<=T);           rigidity(pos11)=10^8*(-0.003748937622488*(T(pos11)+2).^3-0.018449844983174*(T(pos11)+2).^2  -0.057638157095631*(T(pos11)+2)+  0.746900791092860);
+
+%Now make sure that rigidity is positive
+pos=find(rigidity<0);        rigidity(pos)=10^6;
Index: /issm/trunk-jpl/src/m/Meca/paterson.py
===================================================================
--- /issm/trunk-jpl/src/m/Meca/paterson.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/Meca/paterson.py	(revision 12996)
@@ -0,0 +1,50 @@
+from numpy import *
+
+def paterson(temperature):
+
+    # Local Variables: pos11, pos5, pos10, temperature, pos, T, pos8, pos9, pos6, pos7, pos4, rigidity, pos2, pos3, pos1
+    # Function calls: length, zeros, argwhere, paterson, error
+    #PATERSON - figure out the rigidity of ice for a given temperature
+    #
+    #   rigidigty (in s^(1/3)Pa) is the flow law paramter in the flow law sigma=B*e(1/3) (Paterson, p97). 
+    #   temperature is in Kelvin degrees
+    #
+    #   Usage:
+    #      rigidity=paterson(temperature)
+    
+	pos=argwhere(temperature<0.)
+	if len(pos):
+		print 'input temperature should be in Kelvin (positive)'
+		return []
+    
+	T = temperature-273.15
+	#The routine below is equivalent to:
+	# n=3; T=temperature-273;
+	# %From paterson,
+	# Temp=[0;-2;-5;-10;-15;-20;-25;-30;-35;-40;-45;-50];
+	# A=[6.8*10^-15;2.4*10^-15;1.6*10^-15;4.9*10^-16;2.9*10^-16;1.7*10^-16;9.4*
+	# 10^-17;5.1*10^-17;2.7*10^-17;1.4*10^-17;7.3*10^-18;3.6*10^-18];;%s-1(kPa-3)
+	# %Convert into rigidity B
+	# B=A.^(-1/n)*10^3; %s^(1/3)Pa
+	# %Now, do a cubic fit between Temp and B: 
+	# fittedmodel=fit(Temp,B,'cubicspline');
+	# rigidity=fittedmodel(temperature);
+
+	rigidity=zeros(len(T))
+	pos1=argwhere(T<=-45);           rigidity[pos1]=10**8*(-0.000292866376675*(T[pos1]+50)**3+ 0.011672640664130*(T[pos1]+50)**2  -0.325004442485481*(T[pos1]+50)+  6.524779401948101)
+	pos2=argwhere(logical_and(-45<=T,T<-40));   rigidity[pos2]=10**8*(-0.000292866376675*(T[pos2]+45)**3+ 0.007279645014004*(T[pos2]+45)**2  -0.230243014094813*(T[pos2]+45)+  5.154964909039554)
+	pos3=argwhere(logical_and(-40<=T,T<-35));   rigidity[pos3]=10**8*(0.000072737147457*(T[pos3]+40)**3+  0.002886649363879*(T[pos3]+40)**2  -0.179411542205399*(T[pos3]+40)+  4.149132666831214)
+	pos4=argwhere(logical_and(-35<=T,T<-30));   rigidity[pos4]=10**8*(-0.000086144770023*(T[pos4]+35)**3+ 0.003977706575736*(T[pos4]+35)**2  -0.145089762507325*(T[pos4]+35)+  3.333333333333331)
+	pos5=argwhere(logical_and(-30<=T,T<-25));   rigidity[pos5]=10**8*(-0.000043984685769*(T[pos5]+30)**3+ 0.002685535025386*(T[pos5]+30)**2  -0.111773554501713*(T[pos5]+30)+  2.696559088937191)
+	pos6=argwhere(logical_and(-25<=T,T<-20));   rigidity[pos6]=10**8*(-0.000029799523463*(T[pos6]+25)**3+ 0.002025764738854*(T[pos6]+25)**2  -0.088217055680511*(T[pos6]+25)+  2.199331606342181)
+	pos7=argwhere(logical_and(-20<=T,T<-15));   rigidity[pos7]=10**8*(0.000136920904777*(T[pos7]+20)**3+  0.001578771886910*(T[pos7]+20)**2  -0.070194372551690*(T[pos7]+20)+  1.805165505978111)
+	pos8=argwhere(logical_and(-15<=T,T<-10));   rigidity[pos8]=10**8*(-0.000899763781026*(T[pos8]+15)**3+ 0.003632585458564*(T[pos8]+15)**2  -0.044137585824322*(T[pos8]+15)+  1.510778053489523)
+	pos9=argwhere(logical_and(-10<=T,T<-5));    rigidity[pos9]=10**8*(0.001676964325070*(T[pos9]+10)**3-  0.009863871256831*(T[pos9]+10)**2  -0.075294014815659*(T[pos9]+10)+  1.268434288203714)
+	pos10=argwhere(logical_and(-5<=T,T<-2));    rigidity[pos10]=10**8*(-0.003748937622487*(T[pos10]+5)**3+0.015290593619213*(T[pos10]+5)**2  -0.048160403003748*(T[pos10]+5)+  0.854987973338348)
+	pos11=argwhere(-2<=T);           rigidity[pos11]=10**8*(-0.003748937622488*(T[pos11]+2)**3-0.018449844983174*(T[pos11]+2)**2  -0.057638157095631*(T[pos11]+2)+  0.746900791092860)
+
+	#Now make sure that rigidity is positive
+	pos=argwhere(rigidity<0);        rigidity[pos]=1**6 
+
+	return rigidity
+
Index: /issm/trunk-jpl/src/m/Mesh/BamgCall.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/BamgCall.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/BamgCall.m	(revision 12996)
@@ -0,0 +1,84 @@
+function md=BamgCall(md,field,hmin,hmax,gradation,epsilon),
+%BAMGCALL - call bam
+%
+%   build a metric using the Hessian of the given field
+%   call Bamg and the output mesh is plugged onto the model
+%   -hmin = minimum edge length (m)
+%   -hmax = maximum edge length (m)
+%   -gradation = maximum edge length gradation between 2 elements
+%   -epsilon = average error on each element (m/yr)
+%
+%   Usage:
+%      md=BamgCall(md,field,hmin,hmax,gradation,epsilon);
+%
+%   Example:
+%      md=BamgCall(md,md.inversion.vel_obs,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%Compute Hessian
+t1=clock; fprintf('%s','      computing Hessian...');
+hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node');
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%Compute metric
+t1=clock; fprintf('%s','      computing metric...');
+if length(md.nodeonwater)==md.mesh.numberofvertices,
+	pos=find(md.nodeonwater);
+else
+	pos=[];
+end
+metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('carre0.met','w');
+fprintf(fid,'%i %i\n',md.mesh.numberofvertices,3);
+fprintf(fid,'%i %i %i\n',metric');
+fclose(fid);
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'%s %i\n','MeshVersionFormatted',0);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements ones(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call bamg
+fprintf('%s\n','      call Bamg...');
+system(['bamg -ratio ' num2str(gradation) ' -splitpbedge -nbv 1000000 -M carre0.met -b carre0.mesh -o carre1.mesh']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+A=meshread('carre1.mesh');
+md.mesh.x=A.x;
+md.mesh.y=A.y;
+md.z=zeros(A.nods,1);
+md.mesh.elements=A.index;
+md.mesh.numberofvertices=A.nods;
+md.mesh.numberofelements=A.nels;
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.mesh carre1.mesh.gmsh');
Index: /issm/trunk-jpl/src/m/Mesh/BamgCallFromMetric.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/BamgCallFromMetric.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/BamgCallFromMetric.m	(revision 12996)
@@ -0,0 +1,65 @@
+function md=BamgCallFromMetric(md,metric,gradation),
+%BAMGCALL - call bam
+%
+%   call Bamg and the output mesh is plugged onto the model
+%   -gradation = maximum edge length gradation between 2 elements
+%
+%   Usage:
+%      md=BamgCallFromMetric(md,metric,gradation);
+%
+%   Example:
+%      md=BamgCall(md,metric,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+fid=fopen('carre0.met','w');
+fprintf(fid,'%i %i\n',md.mesh.numberofvertices,3);
+fprintf(fid,'%i %i %i\n',metric');
+fclose(fid);
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'%s %i\n','MeshVersionFormatted',0);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements ones(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call bamg
+fprintf('%s\n','      call Bamg...');
+system(['bamg -ratio ' num2str(gradation) ' -splitpbedge -nbv 1000000 -M carre0.met -b carre0.mesh -o carre1.mesh']);
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+A=meshread('carre1.mesh');
+md.mesh.x=A.x;
+md.mesh.y=A.y;
+md.z=zeros(A.nods,1);
+md.mesh.elements=A.index;
+md.mesh.numberofvertices=A.nods;
+md.mesh.numberofelements=A.nels;
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.mesh carre1.mesh.gmsh');
Index: /issm/trunk-jpl/src/m/Mesh/ComputeHessian.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/ComputeHessian.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/ComputeHessian.m	(revision 12996)
@@ -0,0 +1,60 @@
+function hessian=ComputeHessian(index,x,y,field,type)
+%COMPUTEHESSIAN - compute hessian matrix from a field
+%
+%   Compute the hessian matrix of a given field
+%   return the three components Hxx Hxy Hyy
+%   for each element or each node
+%
+%   Usage:
+%      hessian=ComputeHessian(index,x,y,field,type)
+%
+%   Example:
+%      hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,md.inversion.vel_obs,'node')
+
+%some variables
+numberofnodes=length(x);
+numberofelements=size(index,1);
+
+%some checks
+if length(field)~=numberofnodes & length(field)~=numberofelements,
+	error('ComputeHessian error message: the given field size not supported yet');
+end
+if strcmpi(type,'node') & strcmpi(type,'element'),
+	error('ComputeHessian error message: only ''node'' or ''element'' type supported yet');
+end
+
+%initialization
+line=index(:);
+linesize=3*numberofelements;
+
+%get areas and  nodal functions coefficients N(x,y)=alpha x + beta y + gamma 
+[alpha beta]=GetNodalFunctionsCoeff(index,x,y);
+areas=GetAreas(index,x,y);
+
+%comput weights that holds the volume of all the element holding the node i
+weights=sparse(line,ones(linesize,1),repmat(areas,3,1),numberofnodes,1);
+
+%compute field on nodes if on elements
+if length(field)==numberofelements,
+	field=sparse(line,ones(linesize,1),repmat(areas.*field,3,1),numberofnodes,1)./weights ;
+end
+
+%Compute gradient for each element
+grad_elx=sum(field(index).*alpha,2); 
+grad_ely=sum(field(index).*beta,2);
+
+%Compute gradient for each node (average of the elements around)
+gradx=sparse(line,ones(linesize,1),repmat(areas.*grad_elx,3,1),numberofnodes,1);
+grady=sparse(line,ones(linesize,1),repmat(areas.*grad_ely,3,1),numberofnodes,1);
+gradx=gradx./weights;
+grady=grady./weights;
+
+%Compute hessian for each element
+hessian=[sum(gradx(index).*alpha,2) sum(grady(index).*alpha,2) sum(grady(index).*beta,2)];
+
+if strcmpi(type,'node')
+	%Compute Hessian on the nodes (average of the elements around)
+	hessian=[sparse(line,ones(linesize,1),repmat(areas.*hessian(:,1),3,1),numberofnodes,1)./weights ...
+		sparse(line,ones(linesize,1),repmat(areas.*hessian(:,2),3,1),numberofnodes,1)./weights ...
+		sparse(line,ones(linesize,1),repmat(areas.*hessian(:,3),3,1),numberofnodes,1)./weights ];
+end
Index: /issm/trunk-jpl/src/m/Mesh/ComputeMetric.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/ComputeMetric.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/ComputeMetric.m	(revision 12996)
@@ -0,0 +1,66 @@
+function metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos)
+%COMPUTEMETRIC - compute metric from an Hessian
+%
+%   Usage:
+%      metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos)
+%      pos is contains the positions where the metric is wished to be maximized (water?)
+%
+%   Example:
+%      metric=ComputeMetric(hessian,2/9,10^-1,100,10^5,find(md.nodeonwater)
+
+%first, find the eigen values of eah line of H=[hessian(i,1) hessian(i,2); hessian(i,2)  hessian(i,3)]
+a=hessian(:,1); b=hessian(:,2); d=hessian(:,3);
+lambda1=0.5*((a+d)+sqrt(4*b.^2+(a-d).^2));
+lambda2=0.5*((a+d)-sqrt(4*b.^2+(a-d).^2));
+pos1=find(lambda1==0);
+pos2=find(lambda2==0);
+pos3=find(b==0 & lambda1==lambda2);
+
+%Modify the eigen values to control the shape of the elements
+lambda1=min(max(abs(lambda1)*scale/epsilon,1/hmax^2),1/hmin^2);
+lambda2=min(max(abs(lambda2)*scale/epsilon,1/hmax^2),1/hmin^2);
+
+%compute eigen vectors
+norm1=sqrt(8*b.^2+2*(d-a).^2+2*(d-a).*sqrt((a-d).^2+4*b.^2));
+v1x=2*b./norm1;
+v1y=((d-a)+sqrt((a-d).^2+4*b.^2))./norm1;
+norm2=sqrt(8*b.^2+2*(d-a).^2-2*(d-a).*sqrt((a-d).^2+4*b.^2));
+v2x=2*b./norm2;
+v2y=((d-a)-sqrt((a-d).^2+4*b.^2))./norm2;
+
+v1x(pos3)=1; v1y(pos3)=0;
+v2x(pos3)=0; v2y(pos3)=1;
+
+%Compute new metric (for each node M=V*Lambda*V^-1)
+metric=full([(v1x.*v2y-v1y.*v2x).^(-1).*(lambda1.*v2y.*v1x-lambda2.*v1y.*v2x) ...
+	(v1x.*v2y-v1y.*v2x).^(-1).*(lambda1.*v1y.*v2y-lambda2.*v1y.*v2y) ...
+	(v1x.*v2y-v1y.*v2x).^(-1).*(-lambda1.*v2x.*v1y+lambda2.*v1x.*v2y)]);
+
+%some corrections for 0 eigen values
+metric(pos1,:)=repmat([1/hmax^2 0 1/hmax^2],length(pos1),1);
+metric(pos2,:)=repmat([1/hmax^2 0 1/hmax^2],length(pos2),1);
+
+%take care of water elements
+metric(pos,:)=repmat([1/hmax^2 0 1/hmax^2],length(pos),1);
+
+%take care of NaNs if any (use Matlab eig in a loop)
+[pos posj]=find(isnan(metric)); clear posj;
+if ~isempty(pos),
+	fprintf(' %i %s',length(pos),'NaN found in the metric. Use Matlab routine...');
+	for i=1:length(pos)
+		H=[hessian(pos(i),1) hessian(pos(i),2)
+		hessian(pos(i),2) hessian(pos(i),3)];
+		[u,v]=eig(full(H));
+		lambda1=v(1,1);
+		lambda2=v(2,2);
+		v(1,1)=min(max(abs(lambda1)*scale/epsilon,1/hmax^2),1/hmin^2);
+		v(2,2)=min(max(abs(lambda2)*scale/epsilon,1/hmax^2),1/hmin^2);
+
+		metricTria=u*v*u^(-1);
+		metric(pos(i),:)=[metricTria(1,1) metricTria(1,2) metricTria(2,2)];
+	end
+end
+
+if any(isnan(metric)),
+	error('ComputeMetric error message: NaN in the metric despite our efforts...')
+end
Index: /issm/trunk-jpl/src/m/Mesh/ElementsFromEdge.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/ElementsFromEdge.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/ElementsFromEdge.m	(revision 12996)
@@ -0,0 +1,15 @@
+function edgeelements=ElementsFromEdge(elements,A,B) 
+%ELEMENTSFROMEDGE: find elements connected to one edge defined by nodes A and B
+%
+% Usage: edgeelements=ElementsFromEdge(elements,A,B) 
+%
+% Eg:    edgeelements=ElementsFromEdge(md.mesh.elements,tip1,tip2)
+%
+%
+edgeelements=find(...
+(elements(:,1)==A & elements(:,2)==B )| ...
+(elements(:,1)==A & elements(:,3)==B )| ...
+(elements(:,2)==A & elements(:,3)==B )| ...
+(elements(:,2)==A & elements(:,1)==B )| ...
+(elements(:,3)==A & elements(:,1)==B )| ...
+(elements(:,3)==A & elements(:,2)==B ));
Index: /issm/trunk-jpl/src/m/Mesh/FixMesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/FixMesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/FixMesh.m	(revision 12996)
@@ -0,0 +1,45 @@
+function  [index2 x2 y2 value2]=FixMesh(index,x,y,value)
+%FixMesh fix mesh with broken triangles, orphan vertices, etc ...
+%
+% Usage: 
+%            [index2 x2 y2 value2]=FixMesh(index,x,y,value)
+%            where index,x,y is a delaunay triangulation, 
+%                  value is a field on the input triangulation, with values at the vertices
+%                  index2,x2,y2,value2 is the repaired triangulation, with new values on new vertices
+%
+%
+
+%duplicate inputs
+index2=index;
+x2=x;
+y2=y;
+value2=value;
+
+%First, look for orphan vertices, and take them out.
+flags=zeros(length(x2),1); flags(index2)=1;
+orphans=find(flags==0);
+
+while ~isempty(orphans),
+
+	%take the first orphan, the lower numbered, and take it out
+	orphan=orphans(1);
+
+	%first x,y,value
+	x2(orphan)=[];
+	y2(orphan)=[];
+	value2(orphan)=[];
+
+	%now, the index:
+	pos=find(index2>orphan); index2(pos)=index2(pos)-1;
+	
+	%look again for orphans on new mesh
+	flags=zeros(length(x2),1);flags(index2)=1;
+	orphans=find(flags==0);
+end
+
+%Check all triangles are well oriented.
+aires=GetAreas(index2,x2,y2);
+pos=find(aires<0);
+temp=index2(pos,1);
+index2(pos,1)=index2(pos,2);
+index2(pos,2)=temp;
Index: /issm/trunk-jpl/src/m/Mesh/GetAreas.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/GetAreas.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/GetAreas.m	(revision 12996)
@@ -0,0 +1,51 @@
+function areas=GetAreas(index,x,y,varargin)
+%GETAREAS - compute areas or volumes of elements
+%
+%   compute areas of triangular elements or volumes 
+%   of pentahedrons
+%
+%   Usage:
+%      areas  =GetAreas(index,x,y);
+%      volumes=GetAreas(index,x,y,z);
+%
+%   Examples:
+%      areas  =GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y);
+%      volumes=GetAreas(md.mesh.elements,md.mesh.x,md.mesh.y,md.z);
+
+%get number of elements and number of nodes
+nels=size(index,1);
+nods=length(x);
+if nargin==4, z=varargin{1}; end
+
+%some checks
+if nargout~=1 | (nargin~=3 & nargin~=4),
+	help GetAreas
+	error('GetAreas error message: bad usage')
+end
+if ((length(y)~=nods) | (nargin==4 & length(z)~=nods)),
+	error('GetAreas error message: x,y and z do not have the same length')
+end
+if max(index(:))>nods,
+	error(['GetAreas error message: index should not have values above ' num2str(nods) ])
+end
+if (nargin==3 & size(index,2)~=3),
+	error('GetAreas error message: index should have 3 columns for 2d meshes.')
+end
+if (nargin==4 & size(index,2)~=6),
+	error('GetAreas error message: index should have 6 columns for 3d meshes.')
+end
+
+%initialization
+areas=zeros(nels,1);
+x1=x(index(:,1)); x2=x(index(:,2)); x3=x(index(:,3));
+y1=y(index(:,1)); y2=y(index(:,2)); y3=y(index(:,3));
+
+%compute the volume of each element
+if nargin==3,
+	%compute the surface of the triangle
+	areas=(0.5*((x2-x1).*(y3-y1)-(y2-y1).*(x3-x1)));
+else
+	%V=area(triangle)*1/3(z1+z2+z3)
+	thickness=mean(z(index(:,4:6)),2)-mean(z(index(:,1:3)),2);
+	areas=(0.5*((x2-x1).*(y3-y1)-(y2-y1).*(x3-x1))).*thickness;
+end
Index: /issm/trunk-jpl/src/m/Mesh/GetCharacteristicLength.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/GetCharacteristicLength.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/GetCharacteristicLength.m	(revision 12996)
@@ -0,0 +1,45 @@
+function length=GetCharacteristicLength(index,x,y,varargin)
+%GETCHARACTERISTICLENGTH - compute characteristic length for a mesh
+%
+%   compute characteristic lengths of every element of a mesh.
+%
+%   Usage:
+%      length  =GetCharacteristicLength(index,x,y);
+%      length  =GetCharacteristicLength(index,x,y,z);
+%
+%   Examples:
+%      length  =GetCharacteristicLength(md.mesh.elements,md.mesh.x,md.mesh.y);
+%      length  =GetCharacteristicLength(md.mesh.elements,md.mesh.x,md.mesh.y,md.z);
+
+
+%get number of elements and number of nodes
+nels=size(index,1);
+nods=numel(x);
+
+%some checks
+if nargout~=1 | (nargin~=3 & nargin~=4),
+	help GetCharacteristicLength
+	error('GetCharacteristicLength error message: bad usage')
+end
+if ((numel(y)~=nods) | (nargin==4 & numel(z)~=nods)),
+	error('GetCharacteristicLength error message: x,y and z do not have the same length')
+end
+if max(index(:))>nods,
+	error(['GetCharacteristicLength error message: index should not have values above ' num2str(nods) ])
+end
+if (nargin==3 & size(index,2)~=3),
+	error('GetCharacteristicLength error message: index should have 3 columns for 2d meshes.')
+end
+if (nargin==4 & size(index,2)~=6),
+	error('GetCharacteristicLength error message: index should have 6 columns for 3d meshes.')
+end
+
+%get areas or volumes.
+areas=GetAreas(index,x,y,varargin{:});
+
+%for a 2d mesh: 
+if nargin==3,
+	length=sqrt(2*areas);
+else
+	error('not supported yet');
+end
Index: /issm/trunk-jpl/src/m/Mesh/GetNodalFunctionsCoeff.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/GetNodalFunctionsCoeff.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/GetNodalFunctionsCoeff.m	(revision 12996)
@@ -0,0 +1,56 @@
+function [alpha beta varargout]=GetNodalFunctionsCoeff(index,x,y)
+%GETNODELFUNCTIONSCOEFF - compute nodal functions coefficients
+%
+%   Compute the coefficients alpha beta and optionaly gamma of
+%   2d triangular elements. For each element, the nodal function
+%   is defined as:
+%   N(x,y)=sum(i=1:3) alpha_i * x + beta_i * y + gamma_i
+%
+%   Usage:
+%      [alpha beta]=GetNodalFunctionsCoeff(index,x,y);
+%      [alpha beta gamma]=GetNodalFunctionsCoeff(index,x,y);
+%
+%   Example:
+%      [alpha beta gamma]=GetNodalFunctionsCoeff(md.mesh.elements,md.mesh.x,md.mesh.y);
+
+%make columns out of x and y
+x=x(:); y=y(:);
+
+%get nels and nods
+nels=size(index,1);
+nods=length(x);
+
+%some checks
+if nargin~=3 | (nargout~=2 & nargout~=3),
+	help GetNodalFunctionsCoeff
+	error('GetNodalFunctionsCoeff error message: bad usage')
+end
+if length(y)~=nods,
+	error('GetNodalFunctionsCoeff error message: x and y do not have the same length')
+end
+if max(index(:))>nods,
+	error(['GetNodalFunctionsCoeff error message: index should not have values above ' num2str(nods) ])
+end
+if size(index,2)~=3,
+	error('GetNodalFunctionsCoeff error message: only 2d meshes supported. index should have 3 columns.')
+end
+
+%initialize output
+alpha=zeros(nels,3);
+beta=zeros(nels,3);
+
+%compute nodal functions coefficients N(x,y)=alpha x + beta y +gamma
+x1=x(index(:,1)); x2=x(index(:,2)); x3=x(index(:,3));
+y1=y(index(:,1)); y2=y(index(:,2)); y3=y(index(:,3));
+invdet=1./(x1.*(y2-y3)-x2.*(y1-y3)+x3.*(y1-y2));
+
+%get alpha and beta
+alpha=[invdet.*(y2-y3) invdet.*(y3-y1) invdet.*(y1-y2)];
+beta =[invdet.*(x3-x2) invdet.*(x1-x3) invdet.*(x2-x1)];
+
+%get gamma if requested
+if nargout==3,
+	gamma=zeros(nels,3);
+	gamma=[invdet.*(x2.*y3-x3.*y2) invdet.*(y1.*x3-y3.*x1) invdet.*(x1.*y2-x2.*y1)];
+	varargout{1}=gamma;
+end
Index: /issm/trunk-jpl/src/m/Mesh/MergeMetrics.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/MergeMetrics.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/MergeMetrics.m	(revision 12996)
@@ -0,0 +1,15 @@
+function metric=MergeMetrics(metric1,metric2)
+
+M1xx=metric1(:,1); M1xy=metric1(:,2); M1yy=metric1(:,3);
+M1lambda1=0.5*((M1xx+M1yy)+sqrt(4*M1xy.^2+(M1xx-M1yy).^2));
+M1lambda2=0.5*((M1xx+M1yy)-sqrt(4*M1xy.^2+(M1xx-M1yy).^2));
+lambda1=min(M1lambda1,M1lambda2);
+
+M2xx=metric1(:,1); M2xy=metric1(:,2); M2yy=metric1(:,3);
+M2lambda1=0.5*((M2xx+M2yy)+sqrt(4*M2xy.^2+(M2xx-M2yy).^2));
+M2lambda2=0.5*((M2xx+M2yy)-sqrt(4*M2xy.^2+(M2xx-M2yy).^2));
+lambda2=min(M2lambda2,M2lambda2);
+
+metric=metric1;
+pos=find(lambda2<lambda1);
+metric(pos,:)=metric2(pos,:);
Index: /issm/trunk-jpl/src/m/Mesh/MeshQuality.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/MeshQuality.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/MeshQuality.m	(revision 12996)
@@ -0,0 +1,82 @@
+function quality=MeshQuality(md,epsilon,hmin,hmax);
+%MESHQUALITY - compute mesh quality
+%
+%   Usage:
+%      MeshQuality(md,epsilon,hmin,hmax);
+
+%Get some variables from the model
+index=md.mesh.elements;
+x=md.mesh.x;
+y=md.mesh.y;
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%Compute Hessian
+hessian=ComputeHessian(index,x,y,md.inversion.vel_obs,'node');
+
+%Compute metric
+if length(md.nodeonwater)==md.mesh.numberofvertices,
+	pos=find(md.nodeonwater);
+else
+	pos=[];
+end
+metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos);
+
+%Get Areas
+areas=GetAreas(index,x,y);
+
+%length edges vectors
+e1x=[x(index(:,2))-x(index(:,1))];
+e1y=[y(index(:,2))-y(index(:,1))];
+e2x=[x(index(:,3))-x(index(:,2))];
+e2y=[y(index(:,3))-y(index(:,2))];
+e3x=[x(index(:,1))-x(index(:,3))];
+e3y=[y(index(:,1))-y(index(:,3))];
+
+%metric of each the 3 nodes for each element
+M1=metric(index(:,1),:);
+M2=metric(index(:,2),:);
+M3=metric(index(:,3),:);
+
+%Get edge length in the metric
+L1=1/2*(sqrt(e2x.*(M2(:,1).*e2x+M2(:,2).*e2y)+e2y.*(M2(:,2).*e2x+M2(:,3).*e2y))+sqrt(e1x.*(M1(:,1).*e1x+M1(:,2).*e1y)+e1y.*(M1(:,2).*e1x+M1(:,3).*e1y)));
+L2=1/2*(sqrt(e3x.*(M3(:,1).*e3x+M3(:,2).*e3y)+e3y.*(M3(:,2).*e3x+M3(:,3).*e3y))+sqrt(e2x.*(M2(:,1).*e2x+M2(:,2).*e2y)+e2y.*(M2(:,2).*e2x+M2(:,3).*e2y)));
+L3=1/2*(sqrt(e1x.*(M1(:,1).*e1x+M1(:,2).*e1y)+e1y.*(M1(:,2).*e1x+M1(:,3).*e1y))+sqrt(e3x.*(M3(:,1).*e3x+M3(:,2).*e3y)+e3y.*(M3(:,2).*e3x+M3(:,3).*e3y)));
+
+%area in the metric
+V=1/3*areas.*(sqrt(M1(:,1).*M1(:,3)-M1(:,2).^2)+sqrt(M2(:,1).*M2(:,3)-M2(:,2).^2)+sqrt(M3(:,1).*M3(:,3)-M3(:,2).^2));
+
+%compute quality:
+quality=4*sqrt(3)*V./(L1+L2+L3);
+
+%compute error
+a=hessian(:,1); b=hessian(:,2); d=hessian(:,3);
+a=a(index)*[1;1;1]/3;
+b=b(index)*[1;1;1]/3;
+d=d(index)*[1;1;1]/3;
+lambda1=0.5*((a+d)+sqrt(4*b.^2+(a-d).^2));
+lambda2=0.5*((a+d)-sqrt(4*b.^2+(a-d).^2));
+lambda1=min(max(abs(lambda1)*scale/epsilon,1/hmax^2),1/hmin^2);
+lambda2=min(max(abs(lambda2)*scale/epsilon,1/hmax^2),1/hmin^2);
+if length(md.nodeonwater)==md.mesh.numberofvertices;
+	pos=find(md.nodeonwater);
+	lambda1(pos)=0;
+	lambda2(pos)=0;
+end
+lambda1=lambda1(index)*[1;1;1]/3;
+lambda2=lambda2(index)*[1;1;1]/3;
+
+lambdamax=max(lambda1,lambda2);
+hmax=max(max(sqrt(e1x.^2+e1y.^2),sqrt(e2x.^2+e2y.^2)),sqrt(e3x.^2+e3y.^2));
+epsilon=scale*hmax.^2.*lambdamax;
+
+%display
+%X=0:0.1:4; hist(quality,X); xlim([0 3]); title('mesh quality distribution','FontSize',14);
+%plotmodel(md,'data',epsilon,'title','Interpolation error','figure',2)
+disp(sprintf('\n%s','Mesh Quality'));
+disp(sprintf('   %s %g','Average Mesh quality: ',mean(quality)));
+disp(sprintf('   %s %g','Worst Element quality:',max(quality)));
+disp(sprintf('\n%s','Interpolation Error'));
+disp(sprintf('   %s %g %s','Average interpolation error:',mean(epsilon),'m/yr'));
+disp(sprintf('   %s %g %s','Maximum interpolation error:',max(epsilon),'m/yr'));
Index: /issm/trunk-jpl/src/m/Mesh/NodeInElement.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/NodeInElement.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/NodeInElement.m	(revision 12996)
@@ -0,0 +1,41 @@
+function node_in_element=NodeInElement(newx,newy,elements,x,y,nodeconnectivity);
+%NODEINELEMENT: find for a list of nodes (in newx,newy), which elements in the mesh (elements,x,y) they belong to.
+%
+%  Usage: node_in_element=NodeInElement(newx,newy,elements,x,y,md.mesh.vertexconnectivity);
+%
+%  See also Nodeconnectivity
+%
+epsilon=10^-10;
+
+%compute some quantities that will speed up the process
+x3x1=x(elements(:,1))-x(elements(:,3));
+y3y1=y(elements(:,1))-y(elements(:,3));
+x3x2=x(elements(:,2))-x(elements(:,3));
+y3y2=y(elements(:,2))-y(elements(:,3));
+x3=x(elements(:,3));
+y3=y(elements(:,3));
+delta=x(elements(:,2)).*y(elements(:,3))-y(elements(:,2)).*x(elements(:,3))-x(elements(:,1)).*y(elements(:,3))+y(elements(:,1)).*x(elements(:,3))+x(elements(:,1)).*y(elements(:,2))-y(elements(:,1)).*x(elements(:,2));
+
+%max connectivity:
+max_connectivity=max(nodeconnectivity(:,end));
+node_in_element=zeros(length(newx),max_connectivity+1); %last column is the number of elements to which the row node is connected.
+
+for i=1:length(newx),
+	x0=newx(i);
+	y0=newy(i);
+	
+	%first area coordinate
+	area_1=(y3y2.*(x0-x3)-x3x2.*(y0-y3))./delta;
+	%second area coordinate
+	area_2=(x3x1.*(y0-y3)-y3y1.*(x0-x3))./delta;
+	%third area coordinate
+	area_3=1-area_1-area_2;
+	
+	%get elements for which all area coordinates are positive (meaning (x0,y0) belongs to these elements
+	pos=find((area_1>=0-epsilon) & (area_2>=0-epsilon) & (area_3>=0-epsilon));
+
+	num_elements=length(pos);
+
+	node_in_element(i,1:num_elements)=pos;
+	node_in_element(i,end)=num_elements;
+end
Index: /issm/trunk-jpl/src/m/Mesh/ProfileProjectOntoMesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/ProfileProjectOntoMesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/ProfileProjectOntoMesh.m	(revision 12996)
@@ -0,0 +1,66 @@
+function mesh_profile=ProfileProjectOntoMesh(md,profile)
+%PROFILEPROJECTONTOMESH: project a profile (made of arbitrary points) onto a mesh, so that we end 
+%                        up with a list of segments self contained onto elements.
+%
+% Usage: mesh_profile=ProfileProjectOntoMesh(md,profile)
+%
+% See also intersections.m
+
+%make a curve out of the mesh, to use the intersections routine.
+rows=[md.mesh.elements md.mesh.elements(:,1)]'; rows=rows(:);
+x=md.mesh.x(rows);
+y=md.mesh.y(rows);
+
+%[x0,y0] = intersections(profile.x,profile.y,x,y,1);
+[x0,y0,indices,j] = intersections(profile.x,profile.y,x,y);
+
+%  sort intersections to create segments in order and continuous along profile
+[indices,isort]=sort(indices);
+j =j (isort);
+x0=x0(isort);
+y0=y0(isort);
+
+%process x0,y0 so they do not include profile.x or profile.y
+processed_indices=[];
+processed_x=[];
+processed_y=[];
+for i=1:numel(indices),
+	if(((indices(i)-floor(indices(i)))~=0) && ((ceil(indices(i))-indices(i))~=0))
+		processed_indices=[processed_indices;floor(indices(i))];
+		processed_x=[processed_x;x0(i)];
+		processed_y=[processed_y;y0(i)];
+	end
+end
+
+%now merge profile.x,profile.y with processed_x,processed_y, at locations processed_indices:
+newx=profile.x;
+newy=profile.y;
+
+count=1;
+for i=1:numel(profile.x),
+	pos=find(processed_indices==i);
+	if ~isempty(pos),
+		newx=[newx(1:count); processed_x(pos); newx(count+1:end)];
+		newy=[newy(1:count); processed_y(pos); newy(count+1:end)];
+		count=count+length(pos)+1;
+	end
+end
+
+%now, for each node, figure out which element it belongs to.
+node_in_element=NodeInElement(newx,newy,md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.vertexconnectivity);
+
+% eliminate nodes that don't fall in any element
+% (profile may start and/or end externally and/or cross holes in the model)
+
+ind=find(node_in_element(:,9)>0);
+newx=newx(ind,:);
+newy=newy(ind,:);
+node_in_element=node_in_element(ind,:);
+
+mesh_profile=[newx(1:end-1) newy(1:end-1) newx(2:end) newy(2:end) zeros(length(newy(2:end)),1)];
+
+%find which element each segment belongs to.
+for i=1:length(newx)-1,
+	common=intersect(node_in_element(i,1:node_in_element(i,end)), node_in_element(i+1,1:node_in_element(i+1,end)));
+	mesh_profile(i,end)=common(1);
+end
Index: /issm/trunk-jpl/src/m/Mesh/YamsCall.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/YamsCall.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/YamsCall.m	(revision 12996)
@@ -0,0 +1,104 @@
+function md=YamsCall(md,field,hmin,hmax,gradation,epsilon),
+%YAMSCALL - call yams
+%
+%   build a metric using the Hessian of the given field
+%   call Yams and the output mesh is plugged onto the model
+%   -hmin = minimum edge length (m)
+%   -hmax = maximum edge length (m)
+%   -gradation = maximum edge length gradation between 2 elements
+%   -epsilon = average error on each element (m/yr)
+%
+%   Usage:
+%      md=YamsCall(md,field,hmin,hmax,gradation,epsilon);
+%
+%   Example:
+%      md=YamsCall(md,md.inversion.vel_obs,1500,10^8,1.3,0.9);
+
+%2d geometric parameter (do not change)
+scale=2/9; 
+
+%Compute Hessian
+t1=clock; fprintf('%s','      computing Hessian...');
+hessian=ComputeHessian(md.mesh.elements,md.mesh.x,md.mesh.y,field,'node');
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%Compute metric
+t1=clock; fprintf('%s','      computing metric...');
+if length(md.mask.vertexonwater)==md.mesh.numberofvertices,
+	pos=find(md.mask.vertexonwater);
+else
+	pos=[];
+end
+metric=ComputeMetric(hessian,scale,epsilon,hmin,hmax,pos);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%write files
+t1=clock; fprintf('%s','      writing initial mesh files...');
+save -ascii carre0.met  metric
+
+fid=fopen('carre0.mesh','w');
+
+%initialiation
+fprintf(fid,'\n%s\n%i\n','MeshVersionFormatted',1);
+
+%dimension
+fprintf(fid,'\n%s\n%i\n','Dimension',2);
+
+%Vertices
+fprintf(fid,'\n%s\n%i\n\n','Vertices',md.mesh.numberofvertices);
+fprintf(fid,'%8g %8g %i\n',[md.mesh.x md.mesh.y zeros(md.mesh.numberofvertices,1)]');
+
+%Triangles
+fprintf(fid,'\n\n%s\n%i\n\n','Triangles',md.mesh.numberofelements);
+fprintf(fid,'%i %i %i %i\n',[md.mesh.elements zeros(md.mesh.numberofelements,1)]');
+numberofelements1=md.mesh.numberofelements;
+	
+%Deal with rifts
+if ~isnan(md.rifts.riftstruct),
+	
+	%we have the list of triangles that make up the rift. keep those triangles around during refinement.
+	triangles=[];
+	for i=1:size(md.rifts.riftstruct,1),
+		triangles=[triangles md.rifts(i).segments(:,3)'];
+	end
+
+	fprintf(fid,'\n\n%s\n%i\n\n','RequiredTriangles',length(triangles));
+	fprintf(fid,'%i\n',triangles);
+end
+
+%close
+fclose(fid);
+t2=clock;fprintf('%s\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%call yams
+fprintf('%s\n','      call Yams...');
+if ispc
+	%windows
+	system(['yams2-win -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+elseif ismac
+	%Macosx
+	system(['yams2-osx -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+else
+	%Linux
+	system(['yams2-linux -O 1 -v -0 -ecp -hgrad ' num2str(gradation)  ' carre0 carre1']);
+end
+
+%plug new mesh
+t1=clock; fprintf('\n%s','      reading final mesh files...');
+Tria=load('carre1.tria');
+Coor=load('carre1.coor');
+md.mesh.x=Coor(:,1);
+md.mesh.y=Coor(:,2);
+md.mesh.z=zeros(size(Coor,1),1);
+md.mesh.elements=Tria;
+md.mesh.numberofvertices=size(Coor,1);
+md.mesh.numberofelements=size(Tria,1);
+numberofelements2=md.mesh.numberofelements;
+t2=clock;fprintf('%s\n\n',[' done (' num2str(etime(t2,t1)) ' seconds)']);
+
+%display number of elements
+fprintf('\n%s %i','      inital number of elements:',numberofelements1);
+fprintf('\n%s %i\n\n','      new    number of elements:',numberofelements2);
+
+%clean up:
+system('rm carre0.mesh carre0.met carre1.tria carre1.coor carre1.meshb');
Index: /issm/trunk-jpl/src/m/Mesh/argusmesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/argusmesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/argusmesh.m	(revision 12996)
@@ -0,0 +1,96 @@
+function md=argusmesh(md,infile)
+%ARGUSMESH - load an Argus mesh onto a model
+%
+%   Convert an Argus mesh contained in a file into
+%   fields needed for the mesh in a model md.
+%
+%   Usage:
+%      md=argusmesh(md,infile)
+%
+%   Example:
+%     md=argusmesh(md,'TriMesh.exp')
+
+%some argument check: 
+if nargin~=2 | nargout~=1,
+	help argustomodel;
+	error('argustomodel error message: bad usage');
+end
+
+%determine root of infile: strip extension
+[a,root,b,c]=fileparts(infile);
+
+%inform user we start the script: 
+disp(['   Translating argus file ''' infile ''' into matlab model object']);
+
+%open infile: 
+fileid=fopen(infile,'r');
+if fileid==-1,
+	error(['Could not open file ' infile  ' for reading']);
+end
+
+%Read first line of the argus mesh: node and element parameters
+[buffer,bytecount]=fscanf(fileid,'%i %i %i %i',[1 4]);
+if bytecount~=4, 
+	error(['Problem reading ' infile ' file at line #1']);
+end
+nel=buffer(1);
+nods=buffer(2);
+num_element_parameters=buffer(3);
+num_node_parameters=buffer(4);
+disp(['      argus model '''   root ''' contains ' num2str(nel) ' elements and ' num2str(nods) ' nodes.']);
+
+%initialize elements and nodes
+elements=zeros(nel,3);
+element_parameters=zeros(nel,num_element_parameters);
+x=zeros(nods,1);
+y=zeros(nods,1);
+z=zeros(nods,1);
+node_parameters=zeros(nods,num_node_parameters);
+
+%read nodes:
+format_string='%s %i %f %f ';
+for n=1:num_node_parameters,
+	format_string=[format_string ' %i '];
+end
+
+for n=1:nods,
+	[buffer,bytecount]=fscanf(fileid,format_string,[1,num_node_parameters+4]);
+	x(n)=buffer(3);
+	y(n)=buffer(4);
+	node_parameters(n,:)=buffer(5:length(buffer));
+end
+
+%read elements: 
+format_string='%s %i %i %i %i';
+for n=1:num_element_parameters,
+	format_string=[format_string ' %i '];
+end
+for n=1:nel,
+	[buffer,bytecount]=fscanf(fileid,format_string,[1,num_element_parameters+5]);
+	elements(n,:)=buffer(3:5);
+	element_parameters(n,:)=buffer(6:length(buffer));
+end
+
+%Create a name and a note for this model: 
+notes=['Model created by Argus from input file: ' infile ' and parameter file: ' root '.par on: ' date];
+name=root;
+
+%Finally, use model constructor to build a complete model: 
+md.mesh.elements=elements;
+md.mesh.x=x;
+md.mesh.y=y;
+md.z=z;
+md.mesh.numberofvertices=size(md.mesh.x,1);
+md.mesh.numberofelements=size(md.mesh.elements,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);
+md.mesh.dimension=2;
+md=addnote(md,notes);
+
+%Add segments and nodes on boundary
+md.mesh.segments=findsegments(md);
+md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1);
+md.mesh.vertexonboundary(md.mesh.segments(:,1))=1;
+md.mesh.vertexonboundary(md.mesh.segments(:,2))=1;
Index: /issm/trunk-jpl/src/m/Mesh/intersections.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/intersections.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/intersections.m	(revision 12996)
@@ -0,0 +1,279 @@
+function [x0,y0,iout,jout] = intersections(x1,y1,x2,y2,robust)
+%INTERSECTIONS Intersections of curves.
+%   Computes the (x,y) locations where two curves intersect.  The curves
+%   can be broken with NaNs or have vertical segments.
+%
+% Example:
+%   [X0,Y0] = intersections(X1,Y1,X2,Y2,ROBUST);
+%
+% where X1 and Y1 are equal-length vectors of at least two points and
+% represent curve 1.  Similarly, X2 and Y2 represent curve 2.
+% X0 and Y0 are column vectors containing the points at which the two
+% curves intersect.
+%
+% ROBUST (optional) set to 1 or true means to use a slight variation of the
+% algorithm that might return duplicates of some intersection points, and
+% then remove those duplicates.  The default is true, but since the
+% algorithm is slightly slower you can set it to false if you know that
+% your curves don't intersect at any segment boundaries.  Also, the robust
+% version properly handles parallel and overlapping segments.
+%
+% The algorithm can return two additional vectors that indicate which
+% segment pairs contain intersections and where they are:
+%
+%   [X0,Y0,I,J] = intersections(X1,Y1,X2,Y2,ROBUST);
+%
+% For each element of the vector I, I(k) = (segment number of (X1,Y1)) +
+% (how far along this segment the intersection is).  For example, if I(k) =
+% 45.25 then the intersection lies a quarter of the way between the line
+% segment connecting (X1(45),Y1(45)) and (X1(46),Y1(46)).  Similarly for
+% the vector J and the segments in (X2,Y2).
+%
+% You can also get intersections of a curve with itself.  Simply pass in
+% only one curve, i.e.,
+%
+%   [X0,Y0] = intersections(X1,Y1,ROBUST);
+%
+% where, as before, ROBUST is optional.
+
+% Version: 1.10, 25 February 2008
+% Author:  Douglas M. Schwarz
+% Email:   dmschwarz=ieee*org, dmschwarz=urgrad*rochester*edu
+% Real_email = regexprep(Email,{'=','*'},{'@','.'})
+
+
+% Theory of operation:
+%
+% Given two line segments, L1 and L2,
+%
+%   L1 endpoints:  (x1(1),y1(1)) and (x1(2),y1(2))
+%   L2 endpoints:  (x2(1),y2(1)) and (x2(2),y2(2))
+%
+% we can write four equations with four unknowns and then solve them.  The
+% four unknowns are t1, t2, x0 and y0, where (x0,y0) is the intersection of
+% L1 and L2, t1 is the distance from the starting point of L1 to the
+% intersection relative to the length of L1 and t2 is the distance from the
+% starting point of L2 to the intersection relative to the length of L2.
+%
+% So, the four equations are
+%
+%    (x1(2) - x1(1))*t1 = x0 - x1(1)
+%    (x2(2) - x2(1))*t2 = x0 - x2(1)
+%    (y1(2) - y1(1))*t1 = y0 - y1(1)
+%    (y2(2) - y2(1))*t2 = y0 - y2(1)
+%
+% Rearranging and writing in matrix form,
+%
+%  [x1(2)-x1(1)       0       -1   0;      [t1;      [-x1(1);
+%        0       x2(2)-x2(1)  -1   0;   *   t2;   =   -x2(1);
+%   y1(2)-y1(1)       0        0  -1;       x0;       -y1(1);
+%        0       y2(2)-y2(1)   0  -1]       y0]       -y2(1)]
+%
+% Let's call that A*T = B.  We can solve for T with T = A\B.
+%
+% Once we have our solution we just have to look at t1 and t2 to determine
+% whether L1 and L2 intersect.  If 0 <= t1 < 1 and 0 <= t2 < 1 then the two
+% line segments cross and we can include (x0,y0) in the output.
+%
+% In principle, we have to perform this computation on every pair of line
+% segments in the input data.  This can be quite a large number of pairs so
+% we will reduce it by doing a simple preliminary check to eliminate line
+% segment pairs that could not possibly cross.  The check is to look at the
+% smallest enclosing rectangles (with sides parallel to the axes) for each
+% line segment pair and see if they overlap.  If they do then we have to
+% compute t1 and t2 (via the A\B computation) to see if the line segments
+% cross, but if they don't then the line segments cannot cross.  In a
+% typical application, this technique will eliminate most of the potential
+% line segment pairs.
+
+
+% Input checks.
+error(nargchk(2,5,nargin))
+
+% Adjustments when fewer than five arguments are supplied.
+switch nargin
+	case 2
+		robust = true;
+		x2 = x1;
+		y2 = y1;
+		self_intersect = true;
+	case 3
+		robust = x2;
+		x2 = x1;
+		y2 = y1;
+		self_intersect = true;
+	case 4
+		robust = true;
+		self_intersect = false;
+	case 5
+		self_intersect = false;
+end
+
+% x1 and y1 must be vectors with same number of points (at least 2).
+if sum(size(x1) > 1) ~= 1 || sum(size(y1) > 1) ~= 1 || ...
+		length(x1) ~= length(y1)
+	error('X1 and Y1 must be equal-length vectors of at least 2 points.')
+end
+% x2 and y2 must be vectors with same number of points (at least 2).
+if sum(size(x2) > 1) ~= 1 || sum(size(y2) > 1) ~= 1 || ...
+		length(x2) ~= length(y2)
+	error('X2 and Y2 must be equal-length vectors of at least 2 points.')
+end
+
+
+% Force all inputs to be column vectors.
+x1 = x1(:);
+y1 = y1(:);
+x2 = x2(:);
+y2 = y2(:);
+
+% Compute number of line segments in each curve and some differences we'll
+% need later.
+n1 = length(x1) - 1;
+n2 = length(x2) - 1;
+xy1 = [x1 y1];
+xy2 = [x2 y2];
+dxy1 = diff(xy1);
+dxy2 = diff(xy2);
+
+% Determine the combinations of i and j where the rectangle enclosing the
+% i'th line segment of curve 1 overlaps with the rectangle enclosing the
+% j'th line segment of curve 2.
+[i,j] = find(repmat(min(x1(1:end-1),x1(2:end)),1,n2) <= ...
+	repmat(max(x2(1:end-1),x2(2:end)).',n1,1) & ...
+	repmat(max(x1(1:end-1),x1(2:end)),1,n2) >= ...
+	repmat(min(x2(1:end-1),x2(2:end)).',n1,1) & ...
+	repmat(min(y1(1:end-1),y1(2:end)),1,n2) <= ...
+	repmat(max(y2(1:end-1),y2(2:end)).',n1,1) & ...
+	repmat(max(y1(1:end-1),y1(2:end)),1,n2) >= ...
+	repmat(min(y2(1:end-1),y2(2:end)).',n1,1));
+
+% For one segment in x1,y1, i and j are returned as row vectors.  They
+% need to be column vectors, or iout and jout below will err out.
+% (jes, 6/11/10)
+
+if (size(i,1) == 1)
+    i=i';
+end
+if (size(j,1) == 1)
+    j=j';
+end
+
+% Find segments pairs which have at least one vertex = NaN and remove them.
+% This line is a fast way of finding such segment pairs.  We take
+% advantage of the fact that NaNs propagate through calculations, in
+% particular subtraction (in the calculation of dxy1 and dxy2, which we
+% need anyway) and addition.
+% At the same time we can remove redundant combinations of i and j in the
+% case of finding intersections of a line with itself.
+if self_intersect
+	remove = isnan(sum(dxy1(i,:) + dxy2(j,:),2)) | j <= i + 1;
+else
+	remove = isnan(sum(dxy1(i,:) + dxy2(j,:),2));
+end
+i(remove) = [];
+j(remove) = [];
+
+% Initialize matrices.  We'll put the T's and B's in matrices and use them
+% one column at a time.  AA is a 3-D extension of A where we'll use one
+% plane at a time.
+n = length(i);
+T = zeros(4,n);
+AA = zeros(4,4,n);
+AA([1 2],3,:) = -1;
+AA([3 4],4,:) = -1;
+AA([1 3],1,:) = dxy1(i,:).';
+AA([2 4],2,:) = dxy2(j,:).';
+B = -[x1(i) x2(j) y1(i) y2(j)].';
+
+% Loop through possibilities.  Trap singularity warning and then use
+% lastwarn to see if that plane of AA is near singular.  Process any such
+% segment pairs to determine if they are colinear (overlap) or merely
+% parallel.  That test consists of checking to see if one of the endpoints
+% of the curve 2 segment lies on the curve 1 segment.  This is done by
+% checking the cross product
+%
+%   (x1(2),y1(2)) - (x1(1),y1(1)) x (x2(2),y2(2)) - (x1(1),y1(1)).
+%
+% If this is close to zero then the segments overlap.
+
+% If the robust option is false then we assume no two segment pairs are
+% parallel and just go ahead and do the computation.  If A is ever singular
+% a warning will appear.  This is faster and obviously you should use it
+% only when you know you will never have overlapping or parallel segment
+% pairs.
+
+if robust
+	overlap = false(1,n);
+	warning_state = warning('off','MATLAB:singularMatrix');
+	% Use try-catch to guarantee original warning state is restored.
+	try
+		lastwarn('')
+		for k = 1:n
+			T(:,k) = AA(:,:,k)\B(:,k);
+			[unused,last_warn] = lastwarn;
+			lastwarn('')
+			if strcmp(last_warn,'MATLAB:singularMatrix')
+				% Force in_range(k) to be false.
+				T(1,k) = NaN;
+				% Determine if these segments overlap or are just parallel.
+				overlap(k) = rcond([dxy1(i(k),:);xy2(j(k),:) - xy1(i(k),:)]) < eps;
+			end
+		end
+		warning(warning_state)
+	catch
+		warning(warning_state)
+		rethrow(lasterror)
+	end
+	% Find where t1 and t2 are between 0 and 1 and return the corresponding
+	% x0 and y0 values.
+	in_range = T(1,:) >= 0 & T(2,:) >= 0 & T(1,:) <= 1 & T(2,:) <= 1;
+	% For overlapping segment pairs the algorithm will return an
+	% intersection point that is at the center of the overlapping region.
+	if any(overlap)
+		ia = i(overlap);
+		ja = j(overlap);
+		% set x0 and y0 to middle of overlapping region.
+		T(3,overlap) = (max(min(x1(ia),x1(ia+1)),min(x2(ja),x2(ja+1))) + ...
+			min(max(x1(ia),x1(ia+1)),max(x2(ja),x2(ja+1)))).'/2;
+		T(4,overlap) = (max(min(y1(ia),y1(ia+1)),min(y2(ja),y2(ja+1))) + ...
+			min(max(y1(ia),y1(ia+1)),max(y2(ja),y2(ja+1)))).'/2;
+		selected = in_range | overlap;
+	else
+		selected = in_range;
+	end
+	xy0 = T(3:4,selected).';
+	
+	% Remove duplicate intersection points.
+	[xy0,index] = unique(xy0,'rows');
+	x0 = xy0(:,1);
+	y0 = xy0(:,2);
+	
+	% Compute how far along each line segment the intersections are.
+	if nargout > 2
+		sel_index = find(selected);
+		sel = sel_index(index);
+		iout = i(sel) + T(1,sel).';
+		jout = j(sel) + T(2,sel).';
+	end
+else % non-robust option
+	for k = 1:n
+		[L,U] = lu(AA(:,:,k));
+		T(:,k) = U\(L\B(:,k));
+	end
+	
+	% Find where t1 and t2 are between 0 and 1 and return the corresponding
+	% x0 and y0 values.
+	in_range = T(1,:) >= 0 & T(2,:) >= 0 & T(1,:) < 1 & T(2,:) < 1;
+	x0 = T(3,in_range).';
+	y0 = T(4,in_range).';
+	
+	% Compute how far along each line segment the intersections are.
+	if nargout > 2
+		iout = i(in_range) + T(1,in_range).';
+		jout = j(in_range) + T(2,in_range).';
+	end
+end
+
+% Plot the results (useful for debugging).
+% plot(x1,y1,x2,y2,x0,y0,'ok');
Index: /issm/trunk-jpl/src/m/Mesh/isconnected.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/isconnected.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/isconnected.m	(revision 12996)
@@ -0,0 +1,13 @@
+function flag=isconnected(elements,A,B)
+%ISCONNECTED: are two nodes connected by a triangulation?
+%
+%   Usage: flag=isconnected(elements,A,B)
+%
+%
+
+elements=ElementsFromEdge(elements,A,B);
+if isempty(elements),
+	flag=0;
+else
+	flag=1;
+end
Index: /issm/trunk-jpl/src/m/Mesh/meshread.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/meshread.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/meshread.m	(revision 12996)
@@ -0,0 +1,41 @@
+function Struct=meshread(filename);
+
+%some checks
+if ~exist(filename),
+	error(['meshread error message: file ' filename ' not found!']);
+end
+
+fid=fopen(filename,'r');
+
+while (~feof(fid)),
+
+	A=fscanf(fid,'%s',1);
+
+	if strcmp(A,'MeshVersionFormatted');
+		Struct.Version=fscanf(fid,'%s',1);
+
+	elseif strcmp(A,'Dimension'),
+		Struct.Dimension=fscanf(fid,'%i',1);
+
+	elseif strcmp(A,'Vertices'),
+		Struct.nods=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%f %f %f',[3 Struct.nods]);
+		Struct.x=A(1,:)';
+		Struct.y=A(2,:)';
+
+	elseif strcmp(A,'Triangles'),
+		Struct.nels=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%i %i %i',[4 Struct.nels]);
+		Struct.index=A(1:3,:)';
+
+	elseif strcmp(A,'Quadrilaterals'),
+		Struct.nels=fscanf(fid,'%i',1);
+		A=fscanf(fid,'%i %i %i %i',[5 Struct.nels]);
+		Struct.index=A(1:4,:)';
+	else
+		%do nothing
+
+	end
+end
+
+fclose(fid);
Index: /issm/trunk-jpl/src/m/Mesh/rifttipsonmesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/rifttipsonmesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/rifttipsonmesh.m	(revision 12996)
@@ -0,0 +1,26 @@
+function tips=rifttipsonmesh(md,riftoutline)
+%RIFTTIPSONMESH: identify, using a rift outline, the nodes that are tips of 
+%                rifts.
+
+%read rifts from outline file
+rifts=expread(riftoutline,1);
+
+tips=[];
+
+for i=1:length(rifts),
+	rift=rifts(i);
+
+	x_tip=rift.x(1);
+	y_tip=rift.y(1);
+	
+	index=find_point(md.mesh.x,md.mesh.y,x_tip,y_tip);
+	tips(end+1)=index;
+
+	x_tip=rift.x(end);
+	y_tip=rift.y(end);
+	
+	index=find_point(md.mesh.x,md.mesh.y,x_tip,y_tip);
+	tips(end+1)=index;
+
+end
+
Index: /issm/trunk-jpl/src/m/Mesh/roundmesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/roundmesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/roundmesh.m	(revision 12996)
@@ -0,0 +1,34 @@
+function md=roundmesh(md,radius,resolution)
+%ROUNDMESH - create an unstructured round mesh 
+%
+%   This script will generate a structured round mesh
+%   - radius     : specifies the radius of the circle in meters
+%   - resolution : specifies the resolution in meters
+%
+%   Usage:
+%      md=roundmesh(md,radius,resolution)
+
+%First we have to create the domain outline 
+
+%Get number of points on the circle
+pointsonedge=floor((2*pi*radius) / resolution);
+
+%Calculate the cartesians coordinates of the points
+x_list=ones(pointsonedge,1); y_list=ones(pointsonedge,1);
+theta=(0:2*pi/pointsonedge:2*pi*(1-1/pointsonedge))';
+x_list=radius*x_list.*cos(theta);
+y_list=radius*y_list.*sin(theta);
+A=struct('x',x_list,'y',y_list,'density',1);
+expgen('RoundDomainOutline.exp',A,1);
+
+%Call Bamg
+md=triangle(md,'RoundDomainOutline.exp',resolution);
+%md=bamg(md,'domain','RoundDomainOutline.exp','hmin',resolution);
+
+%move the closest node to the center
+[mini pos]=min(md.mesh.x.^2+md.mesh.y.^2);
+md.mesh.x(pos)=0;
+md.mesh.y(pos)=0;
+
+%delete domain
+delete('RoundDomainOutline.exp')
Index: /issm/trunk-jpl/src/m/Mesh/squaremesh.m
===================================================================
--- /issm/trunk-jpl/src/m/Mesh/squaremesh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Mesh/squaremesh.m	(revision 12996)
@@ -0,0 +1,78 @@
+function md=squaremesh(md,Lx,Ly,nx,ny)
+%SQUAREMESH - create a structured square mesh 
+%
+%   This script will generate a structured square mesh
+%   Lx and Ly are the dimension of the domain (in meters)
+%   nx anx ny are the number of nodes in the x and y direction
+%   The coordinates x and y returned are in meters.
+%
+%   Usage:
+%      [md]=squaremesh(md,Lx,Ly,nx,ny)
+
+%get number of elements and number of nodes
+nel=(nx-1)*(ny-1)*2;
+nods=nx*ny;
+
+%initialization
+segments=zeros(0,3);
+index=zeros(nel,3);
+x=zeros(nx*ny,1);
+y=zeros(nx*ny,1);
+
+%create coordinates
+for n=1:nx,
+	for m=1:ny,
+		x((n-1)*ny+m)=(n-1);
+		y((n-1)*ny+m)=(m-1);
+	end
+end
+
+%create index
+for n=1:(nx-1)
+	for m=1:(ny-1),
+		A=(n-1)*ny+m;
+		B=A+1;
+		C=n*ny+m;
+		D=C+1;
+		index((n-1)*(ny-1)*2+2*(m-1)+1,:)=[A C B];
+		index((n-1)*(ny-1)*2+2*m,:)=[B C D];
+	end
+end
+
+%Scale  x and y
+x=x/max(x)*Lx;
+y=y/max(y)*Ly;
+
+%create segments
+segments=zeros(2*(nx-1)+2*(ny-1),3);
+%left edge:
+segments(1:ny-1,:)=[[2:ny]' [1:ny-1]' 2*[1:ny-1]'-1];
+%right edge:
+segments(ny:2*(ny-1),:)=[[ny*(nx-1)+1:nx*ny-1]' [ny*(nx-1)+2:nx*ny]' 2*[(ny-1)*(nx-2)+1:(nx-1)*(ny-1)]'];
+%front edge:
+segments(2*(ny-1)+1:2*(ny-1)+(nx-1),:)=[[2*ny:ny:ny*nx]' [ny:ny:ny*(nx-1)]' [2*(ny-1):2*(ny-1):2*(nx-1)*(ny-1)]'];
+%back edge
+segments(2*(ny-1)+(nx-1)+1:2*(nx-1)+2*(ny-1),:)=[[1:ny:(nx-2)*ny+1]' [ny+1:ny:ny*(nx-1)+1]' [1:2*(ny-1):2*(nx-2)*(ny-1)+1]'];
+
+%plug coordinates and nodes
+md.mesh.x=x;
+md.mesh.y=y;
+md.mesh.z=zeros(nods,1);
+md.mesh.numberofvertices=nods;
+md.mesh.vertexonboundary=zeros(nods,1);md.mesh.vertexonboundary(segments(:,1:2))=1;
+md.mesh.vertexonbed=ones(nods,1);
+md.mesh.vertexonsurface=ones(nods,1);
+
+%plug elements
+md.mesh.elements=index;
+md.mesh.segments=segments;
+md.mesh.numberofelements=nel;
+md.mesh.elementonbed=ones(nel,1);
+md.mesh.elementonsurface=ones(nel,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);
+
+%plug other field
+md.mesh.dimension=2;
Index: /issm/trunk-jpl/src/m/Miscellaneous/create_region.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/create_region.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/create_region.m	(revision 12996)
@@ -0,0 +1,15 @@
+function create_region(name)
+%CREATE_REGION - create region  ????
+%
+%   very temporary function.
+%   
+%   Usage: 
+%      create_region(name)
+
+eval(['mkdir ' name]);
+eval(['cd ' name ]);
+!mkdir Delivery Exp_Par Results
+cd Exp_Par
+!cp ../../RonneShelf/Exp_Par/* ./
+!rm -rf Hole*
+eval(['!mv Ronne.par ' name '.par']);
Index: /issm/trunk-jpl/src/m/Miscellaneous/findarg.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/findarg.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/findarg.m	(revision 12996)
@@ -0,0 +1,51 @@
+function  vals=findarg(arglist,field)
+%FINDARG - find argument associated to a field in a list
+%
+%   This function parses through an argument list (typically varargin in a routine)
+%   looking for a character array equal to field. Once this is found, we return the 
+%   next value in the varargin (if possible). 
+%   Because field might appear several times in the argument list, we return a structure 
+%   holding all these values. 
+%   Note that all comparisons to field value are case independent.
+%
+%   Usage:
+%      vals=findarg(arglist,field)
+%
+%   Example:
+%      routine foobar calls vals=findarg('Data',varargin)
+%      with varargin='Data',1,'Data','foo','Plot','velocity','Arrow',4
+%      findarg would return the following structure: vals(1).value=1, vals(2).value='foo'; 
+
+%some argument checking: 
+if ((nargin==0) | (nargout==0)),
+	help findarg;
+	error('findarg error message');
+end
+
+if ~ischar(field),
+	error('findarg error message: field should be a string');
+end
+
+if ~iscell(arglist),
+	error('findarg error message: argument list should be a cell array.');
+end
+
+%Recover data to plot
+founddata=0;
+
+for i=1:(length(arglist)-1), %data in arglist comes in pairs, hence the -1.
+	if ischar(arglist{i}),
+		if (strcmpi(arglist{i},field)),
+			founddata=founddata+1;
+			if founddata==1,
+				vals.value=arglist{i+1};
+			else
+				vals(end+1).value=arglist{i+1};
+			end
+		end
+	end
+end
+
+if founddata==0,
+	vals=[];
+end
Index: /issm/trunk-jpl/src/m/Miscellaneous/issmdoc.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/issmdoc.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/issmdoc.m	(revision 12996)
@@ -0,0 +1,15 @@
+%Quick documentation for ISSM
+
+%First get ISSM tier: 
+ISSM_DIR=issmdir;
+
+disp(sprintf('\n%s','  A comprehensive documentation is available on http://issm.jpl.nasa.gov'));
+disp(sprintf('\n%s','  Example: how to create a square ice shelf'));
+disp(sprintf('%s','	   go to ',ISSM_DIR,'/examples/SquareIceshelf'));
+disp(sprintf('%s','	   md=model;                                %creates a new empty model structure'));
+disp(sprintf('%s','	   md=triangle(md,''DomainOutline.exp'',50000);   %creates a mesh of the domain outline with a resolution of 50000m'));
+disp(sprintf('%s','	   md=setmask(md,''all'','''');               %defines the glacier system as an ice shelf (no island)'));
+disp(sprintf('%s','	   md=parameterize(md,''Square.par'');        %fills all the other fields of the model'));
+disp(sprintf('%s','	   md=setflowequation(md,''macayeal'',''all''); %defines all elements as MacAyeal''s'));
+disp(sprintf('%s','	   md=solve(md,DiagnosticSolutionEnum);   %generate the velocity field'));
+disp(sprintf('%s','	   plotmodel(md,''data'',md.results.DiagnosticSolution.Vel);    %displays the velocity (type plotdoc for plotmodel help)'));
Index: /issm/trunk-jpl/src/m/Miscellaneous/netcdf.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/netcdf.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/netcdf.m	(revision 12996)
@@ -0,0 +1,136 @@
+function S = netcdf(File,varargin)
+% Function to read NetCDF files
+%   S = netcdf(File)
+% Input Arguments
+%   File = NetCDF file to read
+% Optional Input Arguments:
+%   'Var',Var - Read data for VarArray(Var), default [1:length(S.VarArray)]
+%   'Rec',Rec - Read data for Record(Rec), default [1:S.NumRecs]
+% Output Arguments:
+%   S    = Structure of NetCDF data organised as per NetCDF definition
+% Notes:
+%   Only version 1, classic 32bit, NetCDF files are supported. By default
+% data are extracted into the S.VarArray().Data field for all variables.
+% To read the header only call S = netcdf(File,'Var',[]);
+%
+% SEE ALSO
+% ---------------------------------------------------------------------------
+S = [];
+
+try
+   if exist(File,'file') fp = fopen(File,'r','b');
+   else fp = []; error('File not found'); end
+   if fp == -1   error('Unable to open file'); end
+
+% Read header
+   Magic = fread(fp,4,'uint8=>char');
+   if strcmp(Magic(1:3),'CDF') error('Not a NetCDF file'); end
+   if uint8(Magic(4))~=1       error('Version not supported'); end
+   S.NumRecs  = fread(fp,1,'uint32=>uint32');
+   S.DimArray = DimArray(fp);
+   S.AttArray = AttArray(fp);
+   S.VarArray = VarArray(fp);
+
+% Setup indexing to arrays and records
+   Var = ones(1,length(S.VarArray));
+   Rec = ones(1,S.NumRecs);
+   for i = 1:2:length(varargin)
+      if     strcmp(upper(varargin{i}),'VAR') Var=Var*0; Var(varargin{i+1})=1;
+      elseif strcmp(upper(varargin{i}),'REC') Rec=Rec*0; Rec(varargin{i+1})=1;
+      else error('Optional input argument not recognised'); end
+   end
+   if sum(Var)==0 fclose(fp); return; end
+
+% Read non-record variables
+   Dim = double(cat(2,S.DimArray.Dim));
+   ID  = double(cat(2,S.VarArray.Type));
+
+   for i = 1:length(S.VarArray)
+      D = Dim(S.VarArray(i).DimID+1); N = prod(D); RecID{i}=find(D==0);
+      if isempty(RecID{i})
+         if length(D)==0 D = [1,1]; N = 1; elseif length(D)==1 D=[D,1]; end
+         if Var(i)
+            S.VarArray(i).Data = ReOrder(fread(fp,N,[Type(ID(i)),'=>',Type(ID(i))]),D);
+            fread(fp,(Pad(N,ID(i))-N)*Size(ID(i)),'uint8=>uint8');
+         else fseek(fp,Pad(N,ID(i))*Size(ID(i)),'cof'); end
+      else S.VarArray(i).Data = []; end
+   end
+
+% Read record variables
+   for k = 1:S.NumRecs
+      for i = 1:length(S.VarArray)
+         if ~isempty(RecID{i})
+            D = Dim(S.VarArray(i).DimID+1); D(RecID{i}) = 1; N = prod(D);
+            if length(D)==1 D=[D,1]; end
+            if Var(i) & Rec(k)
+               S.VarArray(i).Data = cat(RecID{i},S.VarArray(i).Data,...
+                  ReOrder(fread(fp,N,[Type(ID(i)),'=>',Type(ID(i))]),D));
+               if N > 1 fread(fp,(Pad(N,ID(i))-N)*Size(ID(i)),'uint8=>uint8'); end
+            else fseek(fp,Pad(N,ID(i))*Size(ID(i)),'cof'); end
+         end
+      end
+   end
+
+   fclose(fp);
+catch
+   Err = lasterror; fprintf('%s\n',Err.message);
+   if ~isempty(fp) && fp ~= -1 fclose(fp); end
+end
+
+% ---------------------------------------------------------------------------------------
+% Utility functions
+
+function S = Size(ID)
+% Size of NetCDF data type, ID, in bytes
+   S = subsref([1,1,2,4,4,8],struct('type','()','subs',{{ID}}));
+
+function T = Type(ID)
+% Matlab string for CDF data type, ID
+   T = subsref({'int8','char','int16','int32','single','double'},...
+               struct('type','{}','subs',{{ID}}));
+
+function N = Pad(Num,ID)
+% Number of elements to read after padding to 4 bytes for type ID
+   N = (double(Num) + mod(4-double(Num)*Size(ID),4)/Size(ID)).*(Num~=0);
+
+function S = String(fp)
+% Read a CDF string; Size,[String,[Padding]]
+   S = fread(fp,Pad(fread(fp,1,'uint32=>uint32'),1),'uint8=>char').';
+
+function A = ReOrder(A,S)
+% Rearrange CDF array A to size S with matlab ordering
+   A = permute(reshape(A,fliplr(S)),fliplr(1:length(S)));
+
+function S = DimArray(fp)
+% Read DimArray into structure
+   if fread(fp,1,'uint32=>uint32') == 10 % NC_DIMENSION
+      for i = 1:fread(fp,1,'uint32=>uint32')
+         S(i).Str = String(fp);
+         S(i).Dim = fread(fp,1,'uint32=>uint32');
+      end
+   else fread(fp,1,'uint32=>uint32'); S = []; end
+
+function S = AttArray(fp)
+% Read AttArray into structure
+   if fread(fp,1,'uint32=>uint32') == 12 % NC_ATTRIBUTE
+      for i = 1:fread(fp,1,'uint32=>uint32')
+         S(i).Str = String(fp);
+         ID       = fread(fp,1,'uint32=>uint32');
+         Num      = fread(fp,1,'uint32=>uint32');
+         S(i).Val = fread(fp,Pad(Num,ID),[Type(ID),'=>',Type(ID)]).';
+      end
+   else fread(fp,1,'uint32=>uint32'); S = []; end
+
+function S = VarArray(fp)
+% Read VarArray into structure
+   if fread(fp,1,'uint32=>uint32') == 11 % NC_VARIABLE
+      for i = 1:fread(fp,1,'uint32=>uint32')
+         S(i).Str      = String(fp);
+         Num           = double(fread(fp,1,'uint32=>uint32'));
+         S(i).DimID    = double(fread(fp,Num,'uint32=>uint32'));
+         S(i).AttArray = AttArray(fp);
+         S(i).Type     = fread(fp,1,'uint32=>uint32');
+         S(i).VSize    = fread(fp,1,'uint32=>uint32');
+         S(i).Begin    = fread(fp,1,'uint32=>uint32'); % Classic 32 bit format only
+      end
+   else fread(fp,1,'uint32=>uint32'); S = []; end
Index: /issm/trunk-jpl/src/m/Miscellaneous/netcdf2struct.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/netcdf2struct.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/netcdf2struct.m	(revision 12996)
@@ -0,0 +1,27 @@
+function S=netcdf2struct(File)
+%NETCDF2STRUCT - load netcdf file and convert to a matlab structure
+%
+%   Usage:
+%      S=netcdf2struct(File);
+
+%Read netcdf file
+data=netcdf(File);
+
+%initialize output
+S=struct();
+
+%All the variables are in VarArray field
+variables=data.VarArray;
+for i=1:size(variables,2),
+	fieldname=deblank(variables(i).Str);
+	fieldvalue=double(squeeze(variables(i).Data));
+	S.(fieldname)=fieldvalue;
+end
+
+%All the variables are in AttArray field
+variables=data.AttArray;
+for i=1:size(variables,2),
+	fieldname=deblank(variables(i).Str);
+	fieldvalue=double(variables(i).Val);
+	S.(fieldname)=fieldvalue;
+end
Index: /issm/trunk-jpl/src/m/Miscellaneous/structtoobj.m
===================================================================
--- /issm/trunk-jpl/src/m/Miscellaneous/structtoobj.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Miscellaneous/structtoobj.m	(revision 12996)
@@ -0,0 +1,16 @@
+function obj=structtoobj(obj,S),
+%Convert struct to object
+
+	%Get object and structure fields
+	structfields=fields(S);
+	objprops    =properties(class(obj));
+
+	%recover object properties
+	for i=1:length(structfields),
+		fieldname =structfields{i};
+		if ismember(fieldname,objprops),
+			fieldvalue=getfield(S,fieldname);
+			obj=setfield(obj,fieldname,fieldvalue);
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/Model/loadmodel.m
===================================================================
--- /issm/trunk-jpl/src/m/Model/loadmodel.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Model/loadmodel.m	(revision 12996)
@@ -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/Model/loadmodellist.m
===================================================================
--- /issm/trunk-jpl/src/m/Model/loadmodellist.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Model/loadmodellist.m	(revision 12996)
@@ -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/Numerics/cfl_step.m
===================================================================
--- /issm/trunk-jpl/src/m/Numerics/cfl_step.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Numerics/cfl_step.m	(revision 12996)
@@ -0,0 +1,23 @@
+function maxtime=cfl_step(md,vx,vy);
+%CFL_STEP - return the maximum time step for the model in years
+%
+%   Dt < 0.5 / ( u/Dx +v/Dy )
+%
+%   Usage:
+%      maxtime=cfl_step(md,vx,vy);
+%
+%   Example:
+%      dt=cfl_step(md,md.results.DiagnosticSolution.Vx,md.results.DiagnosticSolution.Vy)
+
+%Check length of velocities 
+if size(vx,1)~=md.mesh.numberofvertices & size(vy,1)~=md.mesh.numberofvertices,
+	error('timestpes error message: size of velocity components must be the same as md.mesh.numberofvertices');
+end
+
+index=md.mesh.elements;
+edgex=max(md.mesh.x(index),[],2)-min(md.mesh.x(index),[],2);
+edgey=max(md.mesh.y(index),[],2)-min(md.mesh.y(index),[],2);
+vx=max(abs(vx(index)),[],2);
+vy=max(abs(vy(index)),[],2);
+
+maxtime=1/2*min(1./(vx./edgex+vy./edgey));
Index: /issm/trunk-jpl/src/m/OS/ismumps.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/ismumps.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/ismumps.m	(revision 12996)
@@ -0,0 +1,33 @@
+function flag=ismumps()
+%ISMUMPS - figure out if MUMPS package was compiled with ISSM
+%
+%   Usage:
+%       flag=ismumps();
+
+
+configfile=[issmdir() '/bin/config.h']; %should find it in the install target
+if ~exist(configfile,'file'),
+	error(['File ' configfile ' not found. ISSM has not been configured yet!']);
+end
+
+%go through the file, and recover the line we want
+flag=2;
+fid=fopen(configfile,'r');
+if(fid==-1), error(['could not open file: ' configfile]); end
+
+while(true),
+	tline=fgets(fid);
+	if ~ischar(tline), break, end
+	if strncmp(tline,'/* #undef _HAVE_MUMPS_ */',25),
+		flag=0;
+		break;
+	end
+	if  strncmp(tline,'#define _HAVE_MUMPS_',20),
+		flag=1;
+		break;
+	end
+end
+fclose(fid);
+if flag==2,
+	error('could not determine whether MUMPS was or was not compiled');
+end
Index: /issm/trunk-jpl/src/m/OS/ismumps.py
===================================================================
--- /issm/trunk-jpl/src/m/OS/ismumps.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/ismumps.py	(revision 12996)
@@ -0,0 +1,37 @@
+import os
+from issmdir import *
+from MatlabFuncs import *
+
+def ismumps():
+	"""
+	ISMUMPS - figure out if MUMPS package was compiled with ISSM
+ 
+	   Usage:
+	      flag=ismumps();
+	"""
+
+	configfile=os.path.join(issmdir(),'bin','config.h')    #should find it in the install target
+	if not os.path.exists(configfile):
+		raise RuntimeError("File '%s' not found. ISSM has not been configured yet!" % configfile)
+
+	#go through the file, and recover the line we want
+	flag=2
+	try:
+		fid=open(configfile,'r')
+	except IOError as e:
+		raise IOError("could not open file: '%s'" % configfile)
+
+	for tline in fid:
+		if strncmp(tline,'/* #undef _HAVE_MUMPS_ */',25):
+			flag=0
+			break
+		if  strncmp(tline,'#define _HAVE_MUMPS_',20):
+			flag=1
+			break
+
+	fid.close()
+	if flag==2:
+		raise RuntimeError("could not determine whether MUMPS was or was not compiled.")
+
+	return flag
+
Index: /issm/trunk-jpl/src/m/OS/ispetsc.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/ispetsc.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/ispetsc.m	(revision 12996)
@@ -0,0 +1,33 @@
+function flag=ispetsc()
+%ISPETSC - figure out if PETSC package was compiled with ISSM
+%
+%   Usage:
+%       flag=ispetsc();
+
+
+configfile=[issmdir() '/bin/config.h']; %should find it in the install target
+if ~exist(configfile,'file'),
+	error(['File ' configfile ' not found. ISSM has not been configured yet!']);
+end
+
+%go through the file, and recover the line we want
+flag=2;
+fid=fopen(configfile,'r');
+if(fid==-1), error(['could not open file: ' configfile]); end
+
+while(true),
+	tline=fgets(fid);
+	if ~ischar(tline), break, end
+	if strncmp(tline,'/* #undef _HAVE_PETSC_ */',25),
+		flag=0;
+		break;
+	end
+	if  strncmp(tline,'#define _HAVE_PETSC_',20),
+		flag=1;
+		break;
+	end
+end
+fclose(fid);
+if flag==2,
+	error('could not determine whether PETSC was or was not compiled');
+end
Index: /issm/trunk-jpl/src/m/OS/ispetsc.py
===================================================================
--- /issm/trunk-jpl/src/m/OS/ispetsc.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/ispetsc.py	(revision 12996)
@@ -0,0 +1,37 @@
+import os
+from issmdir import *
+from MatlabFuncs import *
+
+def ispetsc():
+	"""
+	ISPETSC - figure out if PETSC package was compiled with ISSM
+ 
+	   Usage:
+	      flag=ispetsc();
+	"""
+
+	configfile=os.path.join(issmdir(),'bin','config.h')    #should find it in the install target
+	if not os.path.exists(configfile):
+		raise RuntimeError("File '%s' not found. ISSM has not been configured yet!" % configfile)
+
+	#go through the file, and recover the line we want
+	flag=2
+	try:
+		fid=open(configfile,'r')
+	except IOError as e:
+		raise IOError("could not open file: '%s'" % configfile)
+
+	for tline in fid:
+		if strncmp(tline,'/* #undef _HAVE_PETSC_ */',25):
+			flag=0
+			break
+		if  strncmp(tline,'#define _HAVE_PETSC_',20):
+			flag=1
+			break
+
+	fid.close()
+	if flag==2:
+		raise RuntimeError("could not determine whether PETSC was or was not compiled.")
+
+	return flag
+
Index: /issm/trunk-jpl/src/m/OS/issmbbftpin.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmbbftpin.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmbbftpin.m	(revision 12996)
@@ -0,0 +1,48 @@
+function issmbbftpin(host, login,port,numstreams,path, packages)
+%BBFTPIN get packages from host, using bbftp. assuming unix system here.
+%
+%   usage: scpin(host,packages,path)
+%
+%
+
+%first get hostname
+hostname=oshostname();
+
+%first be sure packages are not in the current directory, this could conflict with pscp on windows. 
+%get initial warning mode
+state=warning('query', 'all');
+%remove warnings in case the files do not exist
+warning off
+for i=1:numel(packages),
+	delete(packages{i});
+end
+%back to initial warning state
+warning(state);
+
+%if hostname and host are the same, do a simple copy
+if strcmpi(hostname,host),
+
+    for i=1:numel(packages),
+		success=copyfile([path '/' packages{i}]); %keep going, even if success=0
+	end
+
+else
+
+	%build a string of the type: bbftp -s -u elarour -e 'setnbstream 8; cd /nobackupp10/elarour/Testing/Interactive3/; get Antarctica.outbin' pfe1.nas.nasa.gov
+	command=['!bbftp -s -V -u ' login ' -e ''setnbstream 8; cd ' path '; '];
+	for i=1:length(packages),
+		command=[command 'get ' packages{i} ';'];
+	end
+	command=[command '''  pfe1.nas.nasa.gov'];
+	
+	eval(command);
+
+	%check bbftp worked
+	for i=1:numel(packages),
+		if ~exist(['./' packages{i}]),
+			error('scpin error message: could not call scp on *nix system');
+		end
+	end
+
+
+end
Index: /issm/trunk-jpl/src/m/OS/issmbbftpout.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmbbftpout.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmbbftpout.m	(revision 12996)
@@ -0,0 +1,30 @@
+function issmbbftpout(host,path,login,port,numstreams,packages)
+%BBFTPOUT put packages onto host, using bbftp. assuming unix system here.
+%
+%   usage: bbftpout(host,path,login,port,numstream,packages)
+%
+%
+
+%get hostname
+hostname=oshostname();
+
+%if hostname and host are the same, do a simple copy
+if strcmpi(host,hostname),
+	for i=1:numel(packages),
+		here=pwd;
+		eval(['cd ' path])
+		system(['rm -rf ' packages{i} ]);
+		system(['ln -s ' here '/' packages{i} ' .']);
+		eval(['cd ' here]);
+	end
+else 
+	
+	%build a string of the type: bbftp -s -u elarour -e 'setnbstream 8; cd /nobackupp10/elarour/Testing/Interactive3/; put Antarctica.tar.gz' pfe1.nas.nasa.gov
+	command=['!bbftp -s -V -u ' login ' -e ''setnbstream 8; cd ' path '; ']
+	for i=1:length(packages),
+		command=[command 'put ' packages{i} ';'];
+	end
+	command=[command '''  pfe1.nas.nasa.gov'];
+	
+	eval(command);
+end
Index: /issm/trunk-jpl/src/m/OS/issmscpin.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmscpin.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmscpin.m	(revision 12996)
@@ -0,0 +1,78 @@
+function scpin(host, login,port,path, packages)
+%SCPIN get packages from host, using scp on unix, and pscp on windows
+%
+%   usage: scpin(host,packages,path)
+%
+%
+
+%first get hostname
+hostname=oshostname();
+
+%first be sure packages are not in the current directory, this could conflict with pscp on windows. 
+%get initial warning mode
+state=warning('query', 'all');
+%remove warnings in case the files do not exist
+warning off
+for i=1:numel(packages),
+	delete(packages{i});
+end
+%back to initial warning state
+warning(state);
+
+%if hostname and host are the same, do a simple copy
+if strcmpi(hostname,host),
+
+    for i=1:numel(packages),
+		success=copyfile([path '/' packages{i}]); %keep going, even if success=0
+	end
+
+else
+
+	if ispc,
+		%use the putty project pscp.exe: it should be in the path.
+		
+		%get ISSM_DIR variable
+		[status,ISSM_DIR]=system('echo [%ISSM_DIR_WIN%]');
+		if status, 
+			error('scpin error message: could not find ISSM_DIR_WIN environment variable');
+		end
+		ISSM_DIR=ISSM_DIR(2:end-2);
+
+		username=input('Username: (quoted string) ');
+		key=input('Key: (quoted string) ');
+
+		for i=1:numel(packages),
+			[status,result]=system([ISSM_DIR '/externalpackages/ssh/pscp.exe -l "' username '" -pw "' key '" ' host ':' path '/' packages{i} ' ./']);
+			if status, 
+				error('scpin error message: could not call putty pscp');
+			end
+		end
+
+	else
+		%just use standard unix scp
+		%string to copy multiple files using scp: 
+		if numel(packages)==1,
+			string=packages{1};
+		else
+			string='\{';
+			for i=1:numel(packages)-1,
+				string=[string packages{i} ','];
+			end
+			string=[string packages{end} '\}'];
+		end
+
+
+		if port,
+			eval(['!scp -P ' num2str(port) ' ' login '@localhost:' path '/' string ' ./']);
+		else
+			eval(['!scp ' login '@' host ':' path '/' string ' ./']);
+		end
+		
+		%check scp worked
+		for i=1:numel(packages),
+			if ~exist(['./' packages{i}]),
+				error('scpin error message: could not call scp on *nix system');
+			end
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/OS/issmscpin.py
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmscpin.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmscpin.py	(revision 12996)
@@ -0,0 +1,76 @@
+import socket
+import platform
+import subprocess
+import os
+import shutil
+from MatlabFuncs import *
+
+def scpin(host, login,port,path, packages):
+	"""
+	SCPIN get packages from host, using scp on unix, and pscp on windows
+ 
+	   usage: scpin(host,packages,path)
+	"""
+
+	#first get hostname
+	hostname=socket.gethostname().lower().split('.')[0]
+
+	#first be sure packages are not in the current directory, this could conflict with pscp on windows. 
+	#remove warnings in case the files do not exist
+	for package in packages:
+		try:
+			os.remove(package)
+		except OSError as e:
+			pass
+
+	#if hostname and host are the same, do a simple copy
+	if strcmpi(hostname,host):
+
+		for package in packages:
+			try:
+				shutil.copy(os.path.join(path,package),os.getcwd())    #keep going, even if success=0
+			except OSError as e:
+				pass
+
+	else:
+
+		if 'Windows' in platform.system():
+			#use the putty project pscp.exe: it should be in the path.
+		
+			#get ISSM_DIR variable
+			if 'ISSM_DIR_WIN' in os.environ:
+				ISSM_DIR=os.environ['ISSM_DIR_WIN'][1:-2]
+			else:
+				raise OSError("scpin error message: could not find ISSM_DIR_WIN environment variable.")
+
+			username=raw_input('Username: (quoted string) ')
+			key=raw_input('Key: (quoted string) ')
+
+			for package in packages:
+				try:
+					subprocess.check_call('%s/externalpackages/ssh/pscp.exe -l "%s" -pw "%s" %s:%s %s' % (ISSM_DIR,username,key,host,os.path.join(path,package),os.getcwd()),shell=True)
+				except CalledProcessError as e:
+					raise CalledProcessError("scpin error message: could not call putty pscp.")
+
+		else:
+			#just use standard unix scp
+			#string to copy multiple files using scp: 
+			if len(packages)==1:
+				string=packages[0]
+			else:
+				string='{'
+				for package in packages:
+					string+=packages[i]+','
+				string=string[:-1]+'}'
+
+
+			if port:
+				subprocess.call('scp -P %d %s@localhost:%s %s' % (port,login,os.path.join(path,string),os.getcwd),shell=True)
+			else:
+				subprocess.call('scp %s@%s:%s %s' % (login,host,os.path.join(path,string),os.getcwd),shell=True)
+		
+			#check scp worked
+			for package in packages:
+				if not os.path.exists(os.path.join('.',package)):
+					raise OSError("scpin error message: could not call scp on *nix system.")
+
Index: /issm/trunk-jpl/src/m/OS/issmscpout.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmscpout.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmscpout.m	(revision 12996)
@@ -0,0 +1,57 @@
+function issmscpout(host,path,login,port,packages)
+%SCPOUT send packages to a host, using scp on unix, and pscp on windows
+%
+%   usage: scpout(host,path,packages)
+%
+%
+
+%get hostname
+hostname=oshostname();
+
+%if hostname and host are the same, do a simple copy
+
+if strcmpi(host,hostname),
+	for i=1:numel(packages),
+		here=pwd;
+		eval(['cd ' path])
+		system(['rm -rf ' packages{i} ]);
+		system(['ln -s ' here '/' packages{i} ' .']);
+		eval(['cd ' here]);
+	end
+else 
+	if ispc,
+		%use the putty project pscp.exe: it should be in the path.
+		
+		%get ISSM_DIR variable
+		[status,ISSM_DIR]=system('echo [%ISSM_DIR_WIN%]');
+		if status, 
+			error('scpout error message: could not find ISSM_DIR_WIN environment variable');
+		end
+		ISSM_DIR=ISSM_DIR(2:end-2);
+
+		username=input('Username: (quoted string) ');
+		key=input('Key: (quoted string) ');
+
+		for i=1:numel(packages),
+			[status,result]=system([ISSM_DIR '/externalpackages/ssh/pscp.exe -l "' username '" -pw "' key '" ' packages{i} ' ' host ':' path]);
+			if status, 
+				error('scpout error message: could not call putty pscp');
+			end
+		end
+
+	else
+		%just use standard unix scp
+		%create string of packages being sent
+		string='';
+		for i=1:numel(packages),
+			string=[string ' ' packages{i}];
+		end
+		string=[string ' '];
+		
+		if port,
+			eval(['!scp -P ' num2str(port) ' ' string ' ' login '@localhost:' path]);
+		else
+			eval(['!scp ' string ' ' login '@' host ':' path]);
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/OS/issmscpout.py
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmscpout.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmscpout.py	(revision 12996)
@@ -0,0 +1,58 @@
+import socket
+import platform
+import subprocess
+import os
+import shutil
+from MatlabFuncs import *
+
+def issmscpout(host,path,login,port,packages):
+	"""
+	SCPOUT send packages to a host, using scp on unix, and pscp on windows
+ 
+	   usage: scpout(host,path,packages)
+	"""
+
+	#get hostname
+	hostname=socket.gethostname().lower().split('.')[0]
+
+	#if hostname and host are the same, do a simple copy
+
+	if strcmpi(host,hostname):
+		for package in packages:
+			here=os.getcwd()
+			os.chdir(path)
+			shutil.rmtree(package)
+			subprocess.call('ln -s %s %s' % (os.path.join(here,package),path),shell=True)
+			os.chdir(here)
+	else:
+		if 'Windows' in platform.system():
+			#use the putty project pscp.exe: it should be in the path.
+		
+			#get ISSM_DIR variable
+			if 'ISSM_DIR_WIN' in os.environ:
+				ISSM_DIR=os.environ['ISSM_DIR_WIN'][1:-2]
+			else:
+				raise OSError("scpout error message: could not find ISSM_DIR_WIN environment variable.")
+
+			username=raw_input('Username: (quoted string) ')
+			key=raw_input('Key: (quoted string) ')
+
+			for package in packages:
+				try:
+					subprocess.check_call('%s/externalpackages/ssh/pscp.exe -l "%s" -pw "%s" %s %s:%s' % (ISSM_DIR,username,key,package,host,path),shell=True)
+				except CalledProcessError as e:
+					raise CalledProcessError("scpout error message: could not call putty pscp.")
+
+		else:
+			#just use standard unix scp
+			#create string of packages being sent
+			string=''
+			for package in packages:
+				string+=' '+package
+			string+=' '
+		
+			if port:
+				subprocess.call('scp -P %d %s %s@localhost:%s' % (port,string,login,path),shell=True)
+			else:
+				subprocess.call('scp %s %s@%s:%s' % (string,login,host,path),shell=True)
+
Index: /issm/trunk-jpl/src/m/OS/issmssh.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmssh.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmssh.m	(revision 12996)
@@ -0,0 +1,37 @@
+function issmssh(host,login,port,command)
+%ISSMSSH - wrapper for OS independent ssh command.
+%
+%   usage: 
+%      issmssh(host,command)
+
+%first get hostname 
+hostname=oshostname();
+
+%if same as host, just run the command. 
+if strcmpi(host,hostname),
+	system(command);
+else
+	if ispc,
+		%use the putty project plink.exe: it should be in the path.
+		
+		%get ISSM_DIR variable
+		[status,ISSM_DIR]=system('echo [%ISSM_DIR_WIN%]');
+		if status, 
+			error('issmssh error message: could not find ISSM_DIR_WIN environment variable');
+		end
+		ISSM_DIR=ISSM_DIR(2:end-2);
+
+		username=input('Username: (quoted string) ');
+		key=input('Key: (quoted string) ');
+
+		system([ISSM_DIR '/externalpackages/ssh/plink.exe -ssh -l "' username '" -pw "' key '" ' host ' "' command '"']);
+
+	else
+		%just use standard unix ssh
+		if port,
+			eval(['!ssh -l ' login ' -p ' num2str(port) ' localhost "' command '"']);
+		else
+			eval(['!ssh -l ' login ' ' host ' "' command '"']);
+		end
+	end
+end
Index: /issm/trunk-jpl/src/m/OS/issmssh.py
===================================================================
--- /issm/trunk-jpl/src/m/OS/issmssh.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/issmssh.py	(revision 12996)
@@ -0,0 +1,42 @@
+import socket
+import platform
+import subprocess
+import os
+from MatlabFuncs import *
+
+def issmssh(host,login,port,command):
+	"""
+	ISSMSSH - wrapper for OS independent ssh command.
+ 
+	   usage: 
+	      issmssh(host,command)
+	"""
+
+	#first get hostname 
+	hostname=socket.gethostname().lower().split('.')[0]
+
+	#if same as host, just run the command. 
+	if strcmpi(host,hostname):
+		subprocess.call(command,shell=True)
+	else:
+		if 'Windows' in platform.system():
+			#use the putty project plink.exe: it should be in the path.
+		
+			#get ISSM_DIR variable
+			if 'ISSM_DIR_WIN' in os.environ:
+				ISSM_DIR=os.environ['ISSM_DIR_WIN'][1:-2]
+			else:
+				raise OSError("issmssh error message: could not find ISSM_DIR_WIN environment variable.")
+
+			username=raw_input('Username: (quoted string) ')
+			key=raw_input('Key: (quoted string) ')
+
+			subprocess.call('%s/externalpackages/ssh/plink.exe -ssh -l "%s" -pw "%s" %s "%s"' % (ISSM_DIR,username,key,host,command),shell=True);
+
+		else:
+			#just use standard unix ssh
+			if port:
+				subprocess.call('ssh -l %s -p %d localhost "%s"' % (login,port,command),shell=True)
+			else:
+				subprocess.call('ssh -l %s %s "%s"' % (login,host,command),shell=True)
+
Index: /issm/trunk-jpl/src/m/OS/listfiles.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/listfiles.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/listfiles.m	(revision 12996)
@@ -0,0 +1,22 @@
+function list=listfiles()
+%LISTFILES list files inside a directory
+%        this is very OS dependent.
+%
+%   usage: list=listfiles;
+%
+%
+%   see also LS DIR
+
+%use dir, as it seems to act OS independent
+
+first_list=dir;
+list={};
+
+for i=1:numel(first_list),
+	if (  ~strcmpi(first_list(i).name,'.') &...
+			~strcmpi(first_list(i).name,'..') &...
+			~strcmpi(first_list(i).name,'NightlyRun') &...
+			~strcmpi(first_list(i).name,'.svn')),
+		list{end+1}=first_list(i).name;
+	end
+end
Index: /issm/trunk-jpl/src/m/OS/listfilesparallel.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/listfilesparallel.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/listfilesparallel.m	(revision 12996)
@@ -0,0 +1,15 @@
+function list=listfilesparallel(rank,numprocs)
+%LISTFILESPARALLEL list files inside a directory, depending on rank  and number of processors running this routine.
+%        this is very OS dependent.
+%
+%   usage: list=listfilesparallel(rank,numprocs);
+%
+%
+%   see also LS DIR LISTFILES
+
+list=listfiles';
+numfiles=numel(list);
+
+%we now have a list, split it between all the processors.
+[i1,i2]=parallelrange(rank,numprocs,numfiles);
+list=list(i1:i2);
Index: /issm/trunk-jpl/src/m/OS/oshostname.m
===================================================================
--- /issm/trunk-jpl/src/m/OS/oshostname.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/OS/oshostname.m	(revision 12996)
@@ -0,0 +1,22 @@
+function hostname=oshostname()
+%OSHOSTNAME figure out hostname, irrespective of os type
+%
+%   usage: hostname=oshostname();
+%
+%
+
+if ispc,
+	[status,hostname]=system('hostname | sed ''s/-//g''');hostname=hostname(1:end-1);
+
+	if status, 
+		error('oshostname error message: could not run hostname command on windows os');
+	end
+
+else
+	[status,hostname]=system(['hostname -s | sed ''s/-//g''']);
+	if status, 
+		error('oshostname error message: could not run hostname command on *nix os');
+	end
+	hostname=hostname(1:end-1);
+	hostname=ddewhite(hostname);
+end
Index: /issm/trunk-jpl/src/m/Plot/plot2patch.m
===================================================================
--- /issm/trunk-jpl/src/m/Plot/plot2patch.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Plot/plot2patch.m	(revision 12996)
@@ -0,0 +1,16 @@
+function [px py]=plot2patch(x,y,miny)
+%PLOT2PATCH: build patch out of x,y plot.
+%
+% Usage: [px,py]=plot2patch(x,y,miny)
+%
+%        where px and py are a list of point defining a closed polygon.
+%              x,y are the values of the plot
+%              miny is the y-value used to close the plot into a closed polygon.
+% 
+%      See also patch, plot
+
+px=x;
+py=y;
+
+px=[px; flipud(x)];
+py=[py; ; miny*ones(length(x),1)];
Index: /issm/trunk-jpl/src/m/Plot/squarezoom.m
===================================================================
--- /issm/trunk-jpl/src/m/Plot/squarezoom.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Plot/squarezoom.m	(revision 12996)
@@ -0,0 +1,20 @@
+function squarezoom()
+%SQUAREZOOM - zoom on a part of a figure
+%
+%   Usage:
+%      squarezoom()
+
+disp('Click twice to define a square where you want to zoom. First click for upper left corner, second for lower right corner');
+[x,y]=ginput(2);
+dx=x(2)-x(1);
+dy=y(1)-y(2);
+
+if dx>dy,
+	delta=dx-dy;
+	xlim([x(1) x(2)]);
+	ylim([y(2)-delta/2 y(1)+delta/2]);
+else
+	delta=dy-dx;
+	xlim([x(1)-delta/2 x(2)+delta/2]);
+	ylim([y(2) y(1)]);
+end
Index: /issm/trunk-jpl/src/m/Shell/flaimdir.m
===================================================================
--- /issm/trunk-jpl/src/m/Shell/flaimdir.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Shell/flaimdir.m	(revision 12996)
@@ -0,0 +1,7 @@
+function FLAIM_DIR=flaimdir()
+%ISSMDIR - Get FLAIM installation directory
+%
+%   Usage:
+%      FLAIM_DIR=flaimdir()
+
+FLAIM_DIR=[issmdir '/externalpackages/flaim/install'];
Index: /issm/trunk-jpl/src/m/Shell/issmdir.m
===================================================================
--- /issm/trunk-jpl/src/m/Shell/issmdir.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Shell/issmdir.m	(revision 12996)
@@ -0,0 +1,18 @@
+function ISSM_DIR=issmdir()
+%ISSMDIR - Get ISSM_DIR environment variable
+%
+%   Usage:
+%      ISSM_DIR=issmdir()
+
+if ~ispc,
+	ISSM_DIR =getenv('ISSM_DIR');
+else
+	ISSM_DIR =getenv('ISSM_DIR_WIN');
+	if strcmpi(ISSM_DIR(end),'/') | strcmpi(ISSM_DIR(end),'\'),
+		ISSM_DIR = ISSM_DIR(1:end-1); %shave off the last '/'
+	end
+end
+
+if (isempty(ISSM_DIR)),
+	error('issmdir error message: ''ISSM_DIR'' environment variable is empty! You should define ISSM_DIR in your .cshrc or .bashrc!');
+end
Index: /issm/trunk-jpl/src/m/Shell/issmdir.py
===================================================================
--- /issm/trunk-jpl/src/m/Shell/issmdir.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/Shell/issmdir.py	(revision 12996)
@@ -0,0 +1,24 @@
+import platform
+import os
+from MatlabFuncs import *
+
+def issmdir():
+	"""
+	ISSMDIR - Get ISSM_DIR environment variable
+ 
+	   Usage:
+	      ISSM_DIR=issmdir()
+	"""
+
+	if not 'Windows' in platform.system():
+		ISSM_DIR =os.environ['ISSM_DIR']
+	else:
+		ISSM_DIR =os.environ['ISSM_DIR_WIN']
+		if strcmpi(ISSM_DIR[-1],'/') or strcmpi(ISSM_DIR[-1],'\\'):
+			ISSM_DIR = ISSM_DIR[:-1]    #shave off the last '/'
+
+	if not ISSM_DIR:
+		raise RuntimeError("issmdir error message: 'ISSM_DIR' environment variable is empty! You should define ISSM_DIR in your .cshrc or .bashrc!")
+
+	return ISSM_DIR
+
Index: /issm/trunk-jpl/src/m/Shell/jplsvn.m
===================================================================
--- /issm/trunk-jpl/src/m/Shell/jplsvn.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Shell/jplsvn.m	(revision 12996)
@@ -0,0 +1,15 @@
+function JPL_SVN=jplsvn()
+%ISSMDIR - Get JPL_SVN environment variable
+%
+%   Usage:
+%      JPL_SVN=jplsvn()
+
+if ~ispc,
+	JPL_SVN =getenv('JPL_SVN');
+else
+	JPL_SVN =getenv('JPL_SVN_WIN');
+end
+
+if (isempty(JPL_SVN)),
+	error('jplsvn error message: ''JPL_SVN'' environment variable is empty! You should define JPL_SVN in your .cshrc or .bashrc');
+end
Index: /issm/trunk-jpl/src/m/Shell/ucisvn.m
===================================================================
--- /issm/trunk-jpl/src/m/Shell/ucisvn.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/Shell/ucisvn.m	(revision 12996)
@@ -0,0 +1,15 @@
+function UCI_SVN=ucisvn()
+%ISSMDIR - Get UCI_SVN environment variable
+%
+%   Usage:
+%      UCI_SVN=ucisvn()
+
+if ~ispc,
+	UCI_SVN =getenv('UCI_SVN');
+else
+	UCI_SVN =getenv('UCI_SVN_WIN');
+end
+
+if (isempty(UCI_SVN)),
+	error('ucisvn error message: ''UCI_SVN'' environment variable is empty! You should define UCI_SVN in your .cshrc or .bashrc');
+end
Index: /issm/trunk-jpl/src/m/String/ddeblank.m
===================================================================
--- /issm/trunk-jpl/src/m/String/ddeblank.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/ddeblank.m	(revision 12996)
@@ -0,0 +1,29 @@
+function sout = ddeblank(s)
+%DDEBLANK Double deblank. Strip both leading and trailing blanks.
+%
+%   DDEBLANK(S) removes leading and trailing blanks and null characters from
+%   the string S.  A null character is one that has a value of 0.
+%
+%   See also DEBLANK, DEWHITE, DDEWHITE.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2003-10-13 11:13:07 +0200
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   error(nargchk(1, 1, nargin));
+   if ~ischar(s)
+      warning('Input must be a string (char array).');
+   end
+
+   if isempty(s)
+      sout = s;
+      return;
+   end
+
+   [r, c] = find( (s ~= ' ') & (s ~= 0) );
+   if size(s, 1) == 1
+      sout = s(min(c) : max(c));
+   else
+      sout = s(:, min(c) : max(c));
+   end
Index: /issm/trunk-jpl/src/m/String/ddewhite.m
===================================================================
--- /issm/trunk-jpl/src/m/String/ddewhite.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/ddewhite.m	(revision 12996)
@@ -0,0 +1,30 @@
+function sout = ddewhite(s)
+%DDEWHITE Double dewhite. Strip both leading and trailing whitespace.
+%
+%   DDEWHITE(S) removes leading and trailing white space and any null
+%   characters from the string S.  A null character is one that has an absolute
+%   value of 0.
+%
+%   See also DEWHITE, DEBLANK, DDEBLANK.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2003-10-13 11:12:57 +0200
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   error(nargchk(1, 1, nargin));
+   if ~ischar(s)
+      error('Input must be a string (char array).');
+   end
+
+   if isempty(s)
+      sout = s;
+      return;
+   end
+
+   [r, c] = find(~isspace(s));
+   if size(s, 1) == 1
+      sout = s(min(c) : max(c));
+   else
+      sout = s(:, min(c) : max(c));
+   end
Index: /issm/trunk-jpl/src/m/String/dewhite.m
===================================================================
--- /issm/trunk-jpl/src/m/String/dewhite.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/dewhite.m	(revision 12996)
@@ -0,0 +1,30 @@
+function sout = dewhite(s)
+%DEWHITE Dewhite. Strip trailing whitespace.
+%
+%   DEWHITE(S) removes leading and trailing white space and any null characters
+%   from the string S.  A null character is one that has an absolute value of
+%   0.
+%
+%   See also DDEWHITE, DEBLANK, DDEBLANK.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2003-10-13 11:12:52 +0200
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   error(nargchk(1, 1, nargin));
+   if ~ischar(s)
+      error( 'Input must be a string (char array).' );
+   end
+
+   if isempty(s)
+      sout = s;
+      return;
+   end
+
+   [r, c] = find(~isspace(s));
+   if size(s, 1) == 1
+      sout = s(1:max(c));
+   else
+      sout = s(:,1:max(c));
+   end
Index: /issm/trunk-jpl/src/m/String/discardnum.m
===================================================================
--- /issm/trunk-jpl/src/m/String/discardnum.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/discardnum.m	(revision 12996)
@@ -0,0 +1,14 @@
+function string2=discardnum(string)
+%DISCARDNUM -  ??????
+%
+%   Usage:
+%      string2=discardnum(string)
+
+string2=string;
+
+for i=1:length(string),
+	if (((string(i)-0) <=57) & ((string(i)-0) >=48)),
+		string2=string(1:i-1);
+		break;
+	end
+end
Index: /issm/trunk-jpl/src/m/String/ismemberi.m
===================================================================
--- /issm/trunk-jpl/src/m/String/ismemberi.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/ismemberi.m	(revision 12996)
@@ -0,0 +1,26 @@
+function flag=ismemberi(string,list),
+%ISMEMBERI - return 1 if a string belongs to a list (case insensitive)
+%
+%   same function as Matlab's ismember except that it
+%   is case insensitive
+%
+%   Usage:
+%      flag=ismemberi(string,list);
+%
+%   Example:
+%      flag=ismemberi('test','{'test1','test2','test3'});
+
+if ~iscell(list)
+	error('ismemberi error message: the list of string must be a cell!')
+end
+
+%initialize output
+flag=0;
+
+%go through the list
+for i=1:length(list),
+	if strcmpi(string,list{i}),
+		flag=i;
+		return
+	end
+end
Index: /issm/trunk-jpl/src/m/String/issmprintf.m
===================================================================
--- /issm/trunk-jpl/src/m/String/issmprintf.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/issmprintf.m	(revision 12996)
@@ -0,0 +1,13 @@
+function issmprintf(flag,format,varargin)
+%ISSMPRINTF -  display string in solution sequences. wrapper to disp and sprintf.  
+%
+%   Usage:
+%      issmprintf(flag,format,string)
+%      flag can be used to switch display on and off
+%
+%   Example:
+%      issmprintf(1,'%s\n','string to display');
+	
+if flag,
+	disp(sprintf(format,varargin{:}));
+end
Index: /issm/trunk-jpl/src/m/String/logoutput.m
===================================================================
--- /issm/trunk-jpl/src/m/String/logoutput.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/logoutput.m	(revision 12996)
@@ -0,0 +1,7 @@
+function logoutput(logstring,message)
+%LOGOUTPUT - embed a log string into an error message, used in the nightly runs.
+%
+%   Usage:
+%      logoutput(logstring,message)
+
+disp(sprintf('%s%s',logstring,message));
Index: /issm/trunk-jpl/src/m/String/strsplit.m
===================================================================
--- /issm/trunk-jpl/src/m/String/strsplit.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/strsplit.m	(revision 12996)
@@ -0,0 +1,91 @@
+function splittedstring = strsplit(inpstr,delimiter)
+%STRSPLIT - split a tring of delimiter separated values
+%
+%   This function should be used to split a string of delimiter separated
+%   values.  If all values are numerical values the returned matrix is a
+%   double array but if there is one non numerical value a cell array is
+%   returned.  You can check this with the iscell() function.
+%   inpstr: string containing delimiter separatede numerical values, eg
+%           3498,48869,23908,34.67
+%   Output: An x by 1 matrix containing the splitted values
+%   Delimiter: optional, if omitted the delimiter is , (comma)
+%
+%   Usage:
+%      output = strsplit(inpstr[,delimiter])
+%
+
+%   mailto:    gie.spaepen@ua.ac.be
+
+
+
+%Check input arguments
+if(nargin < 1)
+    error('There is no argument defined');
+else
+    if(nargin == 1)
+        strdelim = ',';
+        %Verbose off!! disp 'Delimiter set to ,';
+    else
+        strdelim = delimiter;
+    end
+end
+
+%deblank string
+deblank(inpstr);
+
+%Get number of substrings
+idx  = findstr(inpstr,strdelim);
+if size(idx) == 0
+    disp 'No delimiter in string, inputString is returned';
+    splittedstring = inpstr;
+else
+    %Define size of the indices
+    sz = size(idx,2);
+    %Define splittedstring
+    tempsplit = {};
+    %Loop through string and itinerate from delimiter to delimiter
+    for i = 1:sz
+        %Define standard start and stop positions for the start position,
+        %choose 1 as startup position because otherwise you get an array
+        %overflow, for the endposition you can detemine it from the
+        %delimiter position
+        strtpos = 1;
+        endpos = idx(i)-1;
+        %If i is not the beginning of the string get it from the delimiter
+        %position
+        if i ~= 1
+            strtpos = idx(i-1)+1;
+        end
+        %If i is equal to the number of delimiters get the last element
+        %first by determining the lengt of the string and then replace the
+        %endpos back to a standard position
+        if i == sz
+            endpos = size(inpstr,2); 
+            tempsplit(i+1) = {inpstr(idx(i)+1 : endpos)};
+            endpos = idx(i)-1;
+        end
+        %Add substring to output: splittedstring a cell array
+        tempsplit(i) = {inpstr(strtpos : endpos)};   
+    end
+    %Flag 
+    isallnums = 1;
+    %Check is there are NaN values if matrix elements are converted to
+    %doubles
+    for i = 1:size(tempsplit,2)
+        tempdouble = str2double(tempsplit(i));
+        if(isnan(tempdouble))
+            isallnums = 0;
+        end
+    end
+    %If isallnums = 1 then return a double array otherwise return a cell
+    %array
+    if(isallnums == 1)
+        for i = 1:size(tempsplit,2)
+            splittedstring(i) = str2double(tempsplit(i));
+        end
+    else
+        splittedstring = tempsplit;
+    end
+    
+        
+end
Index: /issm/trunk-jpl/src/m/String/strsplit_strict.m
===================================================================
--- /issm/trunk-jpl/src/m/String/strsplit_strict.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/String/strsplit_strict.m	(revision 12996)
@@ -0,0 +1,37 @@
+function splittedstring = strsplit(inpstr,delimiter)
+%STRSPLIT - split a tring of delimiter separated values
+%
+%   Usage:
+%      output = strsplit_strict(inpstr,delimiter)
+
+
+%Check input arguments
+if(nargin ~= 2)
+    error('There is no argument defined');
+end
+
+%deblank string
+deblank(inpstr);
+
+%Get number of substrings
+idx  = findstr(inpstr,delimiter);
+if size(idx) == 0
+    splittedstring = {inpstr};
+else
+    sz = size(idx,2);
+    splittedstring = {};
+    %Loop through string and itinerate from delimiter to delimiter
+    for i = 1:sz
+        strtpos = 1;
+        endpos = idx(i)-1;
+        if i ~= 1
+            strtpos = idx(i-1)+1;
+        end
+        if i == sz
+            endpos = size(inpstr,2); 
+            splittedstring(i+1) = {inpstr(idx(i)+1 : endpos)};
+            endpos = idx(i)-1;
+        end
+        splittedstring(i) = {inpstr(strtpos : endpos)};   
+    end
+end
Index: /issm/trunk-jpl/src/m/consistency/checkfield.m
===================================================================
--- /issm/trunk-jpl/src/m/consistency/checkfield.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/consistency/checkfield.m	(revision 12996)
@@ -0,0 +1,195 @@
+function md = checkfield(md,fieldname,varargin)
+%CHECKFIELD - check field consistency
+%
+%   Used to check model consistency.
+%   Available options:
+%      - NaN: 1 if check that there is no NaN
+%      - size: [lines cols], NaN for non checked dimensions
+%      - >:  greater than provided value
+%      - >=: greater or equal to provided value
+%      - <:  smallerthan provided value
+%      - <=: smaller or equal to provided value
+%      - < vec:  smallerthan provided values on each vertex
+%      - forcing: 1 if check forcing consistency (size and time)
+%      - values: cell of strings or vector of acceptable values
+%      - numel: list of acceptable number of elements
+%      - cell: 1 if check that is cell
+%      - empty: 1 if check that non empty
+%      - message: overloaded error message
+%
+%   Usage:
+%      md = checkfield(md,fieldname,options);
+%
+%   Example:
+%      md = checkfield(md,'mesh.elementonbed','size',[md.mesh.numberofelements 1],'values',[0 1]);
+%      md = checkfield(md,'diagnostic.icefront','size',[NaN 4],'NaN',1);
+%      md = checkfield(md,'diagnostic.icefront(:,end)','values',[0 1 2]);
+
+%get options
+options=pairoptions(varargin{:});
+
+%get field from model
+eval(['field=md.' fieldname ';']);
+
+%check empty
+if exist(options,'empty')
+	if isempty(field),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' is empty']));
+	end
+end
+
+%Check size
+if exist(options,'size')
+	fieldsize=getfieldvalue(options,'size');
+	if isnan(fieldsize(1)),
+		if (size(field,2)~=fieldsize(2)),
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' should have ' num2str(fieldsize(2)) ' columns']));
+		end
+	elseif isnan(fieldsize(2)),
+		if (size(field,1)~=fieldsize(1)),
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' should have ' num2str(fieldsize(1)) ' lines']));
+		end
+	else
+		if ((size(field,1)~=fieldsize(1)) |  (size(field,2)~=fieldsize(2)))
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' size should be ' num2str(fieldsize(1)) ' x ' num2str(fieldsize(2))]));
+		end
+	end
+end
+
+%Check numel
+if exist(options,'numel')
+	fieldnumel=getfieldvalue(options,'numel');
+	if ~ismember(numel(field),fieldnumel),
+		if length(fieldnumel)==1
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' size should be ' sprintf('%g ',fieldnumel) ]));
+		elseif length(fieldnumel)==2
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' size should be ' num2str(fieldnumel(1)) ' or ' num2str(fieldnumel(2)) ]));
+		else
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' size should be ' sprintf('%g, ',fieldnumel(1:end-1)) ' or ' num2str(fieldnumel(end)) ]));
+		end
+	end
+end
+
+%check NaN
+if getfieldvalue(options,'NaN',0);
+	field2=reshape(field,prod(size(field)),1);
+	if any(isnan(field2)),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['NaN values found in field ''' fieldname '''']));
+	end
+end
+
+%check cell
+if getfieldvalue(options,'cell',0);
+	if ~iscell(field),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should be a cell']));
+	end
+end
+
+%check values
+if exist(options,'values')
+	fieldvalues=getfieldvalue(options,'values');
+	if iscell(fieldvalues), %strings
+		if ischar(field) | iscell(fieldvalues),
+			if any(~ismember(field,fieldvalues)),
+				if length(fieldvalues)==1
+					md = checkmessage(md,getfieldvalue(options,'message',...
+						['field ''' fieldname ''' value should be ''' fieldvalues{1} '''']));
+				elseif length(fieldvalues)==2
+					md = checkmessage(md,getfieldvalue(options,'message',...
+						['field ''' fieldname ''' values should be ''' fieldvalues{1} ''' or ''' fieldvalues{2} '''']));
+				else
+					md = checkmessage(md,getfieldvalue(options,'message',...
+						['field ''' fieldname ''' should have values in ' sprintf('''%s'', ',fieldvalues{1:end-1}) 'or ''' fieldvalues{end} '''']));
+				end
+			end
+		else
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' should be one of the following strings: ' sprintf('''%s'', ',fieldvalues{1:end-1}) 'or ''' fieldvalues{end} '''']));
+		end
+	else
+		field2=reshape(field,prod(size(field)),1);
+		if isnumeric(field),
+			if any(~ismember(field2,fieldvalues)),
+				md = checkmessage(md,getfieldvalue(options,'message',...
+					['field ''' fieldname ''' should have values in [' num2str(fieldvalues) ']']));
+			end
+		else
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' should be a number in [' num2str(fieldvalues) ']']));
+		end
+	end
+end
+
+%check greater
+if exist(options,'>=')
+	lowerbound=getfieldvalue(options,'>=');
+	field2=reshape(field,prod(size(field)),1);
+	if any(field2<lowerbound),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should have values above ' num2str(lowerbound(1,1))]));
+	end
+end
+if exist(options,'>')
+	lowerbound=getfieldvalue(options,'>');
+	field2=reshape(field,prod(size(field)),1);
+	if any(field2<=lowerbound),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should have values above ' num2str(lowerbound(1,1))]));
+	end
+end
+
+%check smaller
+if exist(options,'<=')
+	upperbound=getfieldvalue(options,'<=');
+	field2=reshape(field,prod(size(field)),1);
+	if any(field2>upperbound),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should have values below ' num2str(upperbound(1,1))]));
+	end
+end
+if exist(options,'<')
+	upperbound=getfieldvalue(options,'<');
+	field2=reshape(field,prod(size(field)),1);
+	if any(field2>=upperbound),
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should have values below ' num2str(upperbound(1,1))]));
+	end
+end
+
+%check file
+if getfieldvalue(options,'file',0),
+	if ~exist(field,'file')
+		md = checkmessage(md,['file provided in ''' fieldname ''': ''' field ''' does not exist']);
+	end
+end
+
+%Check forcings (size and times)
+if getfieldvalue(options,'forcing',0),
+	if size(field,1)==md.mesh.numberofvertices,
+		if ~size(field,2)==1,
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' should have only one column as there are md.mesh.numberofvertices lines']));
+		end
+	elseif size(field,1)==md.mesh.numberofvertices+1
+		if any(field(end,:)~=sort(field(end,:))),
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' columns should be sorted chronologically']));
+		end
+		if any(field(end,1:end-1)==field(end,2:end)),
+			md = checkmessage(md,getfieldvalue(options,'message',...
+				['field ''' fieldname ''' columns must not contain duplicate timesteps']));
+		end
+	else
+		md = checkmessage(md,getfieldvalue(options,'message',...
+			['field ''' fieldname ''' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines']));
+	end
+end
Index: /issm/trunk-jpl/src/m/consistency/checkfield.py
===================================================================
--- /issm/trunk-jpl/src/m/consistency/checkfield.py	(revision 12996)
+++ /issm/trunk-jpl/src/m/consistency/checkfield.py	(revision 12996)
@@ -0,0 +1,156 @@
+import numpy
+import os
+from pairoptions import *
+from MatlabFuncs import *
+
+def checkfield(md,fieldname,*args):
+	"""
+	CHECKFIELD - check field consistency
+
+	   Used to check model consistency.
+	   Available options:
+	      - NaN: 1 if check that there is no NaN
+	      - size: [lines cols], NaN for non checked dimensions
+	      - >:  greater than provided value
+	      - >=: greater or equal to provided value
+	      - <:  smallerthan provided value
+	      - <=: smaller or equal to provided value
+	      - < vec:  smallerthan provided values on each vertex
+	      - forcing: 1 if check forcing consistency (size and time)
+	      - values: cell of strings or vector of acceptable values
+	      - numel: list of acceptable number of elements
+	      - cell: 1 if check that is cell
+	      - empty: 1 if check that non empty
+	      - message: overloaded error message
+
+	   Usage:
+	      md = checkfield(md,fieldname,options);
+
+	   Example:
+	      md = checkfield(md,'mesh.elementonbed','size',[md.mesh.numberofelements 1],'values',[0 1]);
+	      md = checkfield(md,'diagnostic.icefront','size',[NaN 4],'NaN',1);
+	      md = checkfield(md,'diagnostic.icefront(:,end)','values',[0 1 2]);
+	"""
+
+	#get options
+	options=pairoptions(*args)
+
+	#get field from model
+#	field=getattr(md,fieldname)
+	exec("field=md.%s" % fieldname)
+
+	#check empty
+	if options.exist('empty'):
+		if not field:
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' is empty" % fieldname))
+
+	#Check size
+	if options.exist('size'):
+		fieldsize=options.getfieldvalue('size')
+		if   len(fieldsize) == 1:
+			if (not numpy.size(field,0)==fieldsize[0]):
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' size should be %d" % (fieldname,fieldsize[0])))
+		elif len(fieldsize) == 2:
+			if   numpy.isnan(fieldsize[0]):
+				if not numpy.size(field,1)==fieldsize[1]:
+					md = md.checkmessage(options.getfieldvalue('message',\
+						"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
+			elif numpy.isnan(fieldsize[1]):
+				if not numpy.size(field,0)==fieldsize[0]:
+					md = md.checkmessage(options.getfieldvalue('message',\
+						"field '%s' should have %d lines" % (fieldname,fieldsize[0])))
+			else:
+				if (not numpy.size(field,0)==fieldsize[0]) or (not numpy.size(field,1)==fieldsize[1]):
+					md = md.checkmessage(options.getfieldvalue('message',\
+						"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
+	
+	#Check numel
+	if options.exist('numel'):
+		fieldnumel=options.getfieldvalue('numel')
+		if not numpy.size(field) in fieldnumel:
+			if   len(fieldnumel)==1:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' size should be %d" % (fieldname,fieldnumel)))
+			elif len(fieldnumel)==2:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1])))
+			else:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' size should be %s" % (fieldname,fieldnumel)))
+
+	#check NaN
+	if options.getfieldvalue('NaN',0):
+		if True in numpy.isnan(field):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"NaN values found in field '%s'" % fieldname))
+
+	#check cell
+	if options.getfieldvalue('cell',0):
+		if not isinstance(field,(tuple,list,dict)):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should be a cell" % fieldname))
+
+	#check values
+	if options.exist('values'):
+		fieldvalues=options.getfieldvalue('values')
+		if False in ismember(field,fieldvalues):
+			if   len(fieldvalues)==1:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' value should be '%s'"  % (fieldname,fieldvalues[0])))
+			elif len(fieldvalues)==2:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' values should be '%s' or '%s'"  % (fieldname,fieldvalues[0],fieldvalues[1])))
+			else:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' should have values in %s" % (fieldname,fieldvalues)))
+
+	#check greater
+	if options.exist('>='):
+		lowerbound=options.getfieldvalue('>=')
+		if numpy.any(field<lowerbound):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have values above %d" % (fieldname,lowerbound)))
+	if options.exist('>'):
+		lowerbound=options.getfieldvalue('>')
+		if numpy.any(field<=lowerbound):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have values above %d" % (fieldname,lowerbound)))
+
+	#check smaller
+	if options.exist('<='):
+		upperbound=options.getfieldvalue('<=')
+		if numpy.any(field>upperbound):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have values below %d" % (fieldname,upperbound)))
+	if options.exist('<'):
+		upperbound=options.getfieldvalue('<')
+		if numpy.any(field>=upperbound):
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have values below %d" % (fieldname,upperbound)))
+
+	#check file
+	if options.getfieldvalue('file',0):
+		if not os.path.exists(field):
+			md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
+
+	#Check forcings (size and times)
+	if options.getfieldvalue('forcing',0):
+		if   numpy.size(field,0)==md.mesh.numberofvertices:
+			if not numpy.size(field,1)==1:
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
+		elif numpy.size(field,0)==md.mesh.numberofvertices+1:
+			if not numpy.all(field[-1,:]==numpy.sort(field[-1,:])):
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' columns should be sorted chronologically" % fieldname))
+			if nump.any(field[-1,0:-1]==field[-1,1:]):
+				md = md.checkmessage(options.getfieldvalue('message',\
+					"field '%s' columns must not contain duplicate timesteps" % fieldname))
+		else:
+			md = md.checkmessage(options.getfieldvalue('message',\
+				"field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
+
+	return md
+
Index: /issm/trunk-jpl/src/m/recursivepath.m
===================================================================
--- /issm/trunk-jpl/src/m/recursivepath.m	(revision 12996)
+++ /issm/trunk-jpl/src/m/recursivepath.m	(revision 12996)
@@ -0,0 +1,38 @@
+function p = recursivepath(d)
+%RECURSIVEPATH - generate paths in a directory
+%
+%   this routine is equivalent to Matlab's genpath except that it skips CVS and .svn directories
+%
+%   Usage:
+%      p = recursivepath(d)
+
+%initialize path to be returned
+p = '';
+sep=pathsep;  %directory separator
+
+% Generate path based on given root directory
+files=dir(d);
+if isempty(files)
+	return
+end
+
+% Add d to the path even if it is empty.
+p = [p d sep];
+
+% set logical vector for subdirectory entries in d
+isdir = logical(cat(1,files.isdir));
+
+% Recursively goes through the subdirectories of d
+dirs=files(isdir); % select only directory entries from the current listing
+for i=1:length(dirs)
+	dirname=dirs(i).name;
+	if ~strcmp(dirname,'.')    & ...
+		~strcmp(dirname,'..')   & ...
+		~strcmp(dirname,'.svn') & ...
+		~strcmp(dirname,'CVS')  & ...
+		~strncmp(dirname,'@',1) & ... %Method directories not allowed in MATLAB path
+		~strcmp(dirname,'private')    %private directories not allowed in MATLAB path
+
+		p = [p recursivepath(fullfile(d,dirname))];
+	end
+end
